summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--README.md4
-rw-r--r--build.sbt58
-rw-r--r--build.xml2
-rw-r--r--project/JarJar.scala4
-rw-r--r--project/Osgi.scala1
-rw-r--r--project/ScalaTool.scala21
-rw-r--r--project/ScriptCommands.scala19
-rw-r--r--project/VersionUtil.scala99
-rw-r--r--scripts/common3
-rwxr-xr-xscripts/jobs/integrate/bootstrap16
-rwxr-xr-xscripts/jobs/validate/publish-core13
-rw-r--r--src/compiler/scala/reflect/quasiquotes/Parsers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala57
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala32
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala281
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Logic.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala18
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala12
-rw-r--r--src/library/scala/Array.scala31
-rw-r--r--src/library/scala/Byte.scala8
-rw-r--r--src/library/scala/Char.scala8
-rw-r--r--src/library/scala/Int.scala8
-rw-r--r--src/library/scala/Long.scala8
-rw-r--r--src/library/scala/Short.scala8
-rw-r--r--src/library/scala/collection/JavaConverters.scala5
-rw-r--r--src/library/scala/collection/Searching.scala12
-rw-r--r--src/library/scala/collection/convert/DecorateAsJava.scala12
-rw-r--r--src/library/scala/collection/immutable/ListSet.scala6
-rw-r--r--src/library/scala/collection/immutable/Vector.scala10
-rw-r--r--src/library/scala/collection/mutable/AnyRefMap.scala6
-rw-r--r--src/library/scala/collection/mutable/ArrayBuilder.scala153
-rw-r--r--src/library/scala/collection/mutable/Builder.scala16
-rw-r--r--src/library/scala/collection/mutable/GrowingBuilder.scala4
-rw-r--r--src/library/scala/collection/mutable/LazyBuilder.scala4
-rw-r--r--src/library/scala/collection/mutable/ListBuffer.scala6
-rw-r--r--src/library/scala/collection/mutable/LongMap.scala6
-rw-r--r--src/library/scala/collection/mutable/MapBuilder.scala2
-rw-r--r--src/library/scala/collection/mutable/ReusableBuilder.scala51
-rw-r--r--src/library/scala/collection/mutable/SetBuilder.scala4
-rw-r--r--src/library/scala/collection/mutable/StringBuilder.scala8
-rw-r--r--src/library/scala/collection/mutable/WrappedArrayBuilder.scala13
-rw-r--r--src/library/scala/concurrent/Future.scala2
-rw-r--r--src/library/scala/concurrent/duration/Duration.scala4
-rw-r--r--src/library/scala/math/package.scala12
-rw-r--r--src/library/scala/reflect/Manifest.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala16
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala4
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala4
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/Settings.scala24
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala110
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/base/comment/Comment.scala3
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala5
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala15
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.eotbin0 -> 137002 bytes
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.ttfbin0 -> 122640 bytes
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.woffbin0 -> 56792 bytes
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.css86
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.js209
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.mousewheel.min.js8
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.panzoom.min.js9
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css4
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js20
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala13
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala2
-rw-r--r--test/files/jvm/future-spec/FutureTests.scala2
-rw-r--r--test/files/jvm/innerClassEnclMethodJavaReflection.scala9
-rw-r--r--test/files/jvm/t6941.check1
-rw-r--r--test/files/jvm/t6941.flags1
-rw-r--r--test/files/jvm/t6941/Analyzed_1.flags1
-rw-r--r--test/files/jvm/t6941/Analyzed_1.scala11
-rw-r--r--test/files/jvm/t6941/test.scala15
-rw-r--r--test/files/neg/choices.check6
-rw-r--r--test/files/neg/override-object-no.check10
-rw-r--r--test/files/neg/override-object-no.scala11
-rw-r--r--test/files/neg/partestInvalidFlag.check4
-rw-r--r--test/files/neg/partestInvalidFlag.flags1
-rw-r--r--test/files/neg/partestInvalidFlag.scala1
-rw-r--r--test/files/neg/t9572.check7
-rw-r--r--test/files/neg/t9572.scala6
-rw-r--r--test/files/pos/t2171.flags1
-rw-r--r--test/files/pos/t2171.scala7
-rw-r--r--test/files/pos/t3252.flags1
-rw-r--r--test/files/pos/t3252.scala15
-rw-r--r--test/files/pos/t3420.flags2
-rw-r--r--test/files/pos/t3430.flags1
-rw-r--r--test/files/pos/t3430.scala13
-rw-r--r--test/files/pos/t4579.flags1
-rw-r--r--test/files/pos/t4840.flags2
-rw-r--r--test/files/pos/t6157.flags1
-rw-r--r--test/files/pos/t6157.scala25
-rw-r--r--test/files/pos/t6547.flags1
-rw-r--r--test/files/pos/t6547.scala6
-rw-r--r--test/files/pos/t8062.flags1
-rw-r--r--test/files/pos/t8062/A_1.scala5
-rw-r--r--test/files/pos/t8062/B_2.scala3
-rw-r--r--test/files/pos/t8306.flags1
-rw-r--r--test/files/pos/t8306.scala8
-rw-r--r--test/files/pos/t8359-closelim-crash.flags1
-rw-r--r--test/files/pos/t8359-closelim-crash.scala23
-rw-r--r--test/files/pos/t9123.flags1
-rw-r--r--test/files/pos/t9123.scala10
-rw-r--r--test/files/pos/trait-force-info.flags1
-rw-r--r--test/files/pos/trait-force-info.scala18
-rw-r--r--test/files/presentation/doc/doc.scala6
-rw-r--r--test/files/run/elidable-opt.scala3
-rw-r--r--test/files/run/lisp.check26
-rw-r--r--test/files/run/lisp.scala (renamed from test/files/pos/t4579.scala)2
-rw-r--r--test/files/run/t7008-scala-defined.flags0
-rw-r--r--test/files/run/t7008-scala-defined/Test_3.scala3
-rw-r--r--test/files/run/t7582.check5
-rw-r--r--test/files/run/t7582.flags2
-rw-r--r--test/files/run/t7582/InlineHolder.scala3
-rw-r--r--test/files/run/t7582b.check5
-rw-r--r--test/files/run/t7582b.flags2
-rw-r--r--test/files/run/t7582b/InlineHolder.scala3
-rw-r--r--test/files/run/t7807.check3
-rw-r--r--test/files/run/t7807.scala21
-rw-r--r--test/files/run/t9567.scala18
-rw-r--r--test/files/run/t9567b.scala19
-rw-r--r--test/files/run/t9567c.scala29
-rw-r--r--test/junit/scala/collection/ReusableBuildersTest.scala48
-rw-r--r--test/junit/scala/collection/SearchingTest.scala48
-rw-r--r--test/junit/scala/collection/immutable/VectorTest.scala30
-rw-r--r--test/junit/scala/issues/OptimizedBytecodeTest.scala331
-rw-r--r--test/junit/scala/reflect/ClassTagTest.scala12
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala6
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala70
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala23
-rw-r--r--test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala25
-rw-r--r--test/pending/run/private-inline.check13
-rw-r--r--test/pending/run/private-inline.flags1
-rw-r--r--test/pending/run/private-inline.scala52
-rw-r--r--test/scaladoc/run/SI-9620.check1
-rw-r--r--test/scaladoc/run/SI-9620.scala43
-rw-r--r--test/scaladoc/run/tag-requirements.check16
-rw-r--r--test/scaladoc/run/tag-requirements.scala53
-rwxr-xr-xtools/scaladoc-diff117
-rw-r--r--versions.properties2
149 files changed, 1974 insertions, 946 deletions
diff --git a/.gitignore b/.gitignore
index d6571a377f..061cd274ac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,9 @@
/build.properties
/buildcharacter.properties
+# might get generated when testing Jenkins scripts locally
+/jenkins.properties
+
# target directories for ant build
/build/
/dists/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d01a71b9bd..462b5404b2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -14,7 +14,7 @@ By the way, the team at Typesafe is: @adriaanm, @lrytz, @retronym, and @SethTisu
## What kind of PR are you submitting?
-Regardless of the nature of your Pull Request, we have to ask you to digitally sign the [Scala CLA](http://typesafe.com/contribute/cla/scala), to protect the OSS nature of the code base.
+Regardless of the nature of your Pull Request, we have to ask you to digitally sign the [Scala CLA](http://www.typesafe.com/contribute/cla/scala), to protect the OSS nature of the code base.
You don't need to submit separate PRs for 2.11.x, 2.12.x, and 2.13.x. Any changes accepted on one of these branches will, in time, be merged into the later branches.
diff --git a/README.md b/README.md
index ce232758dc..45b7cb28f9 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@ This is the official repository for the [Scala Programming Language](http://www.
# How to contribute
-To contribute to the Scala Standard Library, Scala Compiler and Scala Language Specification, please send us a [pull request](https://help.github.com/articles/using-pull-requests/#fork--pull) from your fork of this repository! We do have to ask you to sign the [Scala CLA](http://typesafe.com/contribute/cla/scala) before we can merge any of your work into our code base, to protect its open source nature.
+To contribute to the Scala Standard Library, Scala Compiler and Scala Language Specification, please send us a [pull request](https://help.github.com/articles/using-pull-requests/#fork--pull) from your fork of this repository! We do have to ask you to sign the [Scala CLA](http://www.typesafe.com/contribute/cla/scala) before we can merge any of your work into our code base, to protect its open source nature.
For more information on building and developing the core of Scala, read on!
@@ -23,7 +23,7 @@ If you need some help with your PR at any time, please feel free to @-mention an
| username | talk to me about... |
--------------------------------------------------------------------------------------------------|----------------------------------------------------------------|---------------------------------------------------|
<img src="https://avatars.githubusercontent.com/adriaanm" height="50px" title="Adriaan Moors"/> | [`@adriaanm`](https://github.com/adriaanm) | type checker, pattern matcher, infrastructure, language spec |
- <img src="https://avatars.githubusercontent.com/SethTisue" height="50px" title="Seth Tisue"/> | [`@SethTisue`](https://github.com/SethTisue) | back-end, library, the welcome-to-Scala experience, build |
+ <img src="https://avatars.githubusercontent.com/SethTisue" height="50px" title="Seth Tisue"/> | [`@SethTisue`](https://github.com/SethTisue) | build, developer docs, community build, Jenkins, library, the welcome-to-Scala experience |
<img src="https://avatars.githubusercontent.com/retronym" height="50px" title="Jason Zaugg"/> | [`@retronym`](https://github.com/retronym) | compiler performance, weird compiler bugs, Java 8 lambdas, REPL |
<img src="https://avatars.githubusercontent.com/Ichoran" height="50px" title="Rex Kerr"/> | [`@Ichoran`](https://github.com/Ichoran) | collections library, performance |
<img src="https://avatars.githubusercontent.com/lrytz" height="50px" title="Lukas Rytz"/> | [`@lrytz`](https://github.com/lrytz) | optimizer, named & default arguments |
diff --git a/build.sbt b/build.sbt
index fb5849a2d1..b31bde8078 100644
--- a/build.sbt
+++ b/build.sbt
@@ -53,7 +53,7 @@
* https://groups.google.com/d/topic/scala-internals/gp5JsM1E0Fo/discussion
*/
-import VersionUtil.{versionProps, versionNumber, generatePropertiesFileSettings, versionProperties, versionPropertiesSettings}
+import VersionUtil._
val bootstrapScalaVersion = versionProps("starr.version")
@@ -64,7 +64,7 @@ val scalaParserCombinatorsDep = withoutScalaLang("org.scala-lang.modules" %% "sc
val scalaSwingDep = withoutScalaLang("org.scala-lang.modules" %% "scala-swing" % versionNumber("scala-swing"))
val scalaXmlDep = withoutScalaLang("org.scala-lang.modules" %% "scala-xml" % versionNumber("scala-xml"))
val partestDep = withoutScalaLang("org.scala-lang.modules" %% "scala-partest" % versionNumber("partest"))
-val partestInterfaceDep = withoutScalaLang("org.scala-lang.modules" %% "scala-partest-interface" % "0.5.0")
+val partestInterfaceDep = withoutScalaLang("org.scala-lang.modules" %% "scala-partest-interface" % "0.7.0")
val junitDep = "junit" % "junit" % "4.11"
val junitIntefaceDep = "com.novocode" % "junit-interface" % "0.11" % "test"
val asmDep = "org.scala-lang.modules" % "scala-asm" % versionProps("scala-asm.version")
@@ -94,13 +94,27 @@ lazy val publishSettings : Seq[Setting[_]] = Seq(
(f, to)
}
IO.copy(mappings)
- }
+ },
+ credentials ++= {
+ val file = Path.userHome / ".credentials"
+ if (file.exists) List(Credentials(file))
+ else Nil
+ },
+ publishMavenStyle := true
)
-lazy val commonSettings = clearSourceAndResourceDirectories ++ versionPropertiesSettings ++ publishSettings ++ Seq[Setting[_]](
+// Set the version number: The ANT build uses the file "build.number" to get the base version. Overriding versions or
+// suffixes for certain builds is done by directly setting variables from the shell scripts. For example, in
+// publish-core this requires computing the commit SHA first and then passing it to ANT. In the sbt build we use
+// the two settings `baseVersion` and `baseVersionSuffix` to compute all versions (canonical, Maven, OSGi). See
+// VersionUtil.versionPropertiesImpl for details. The standard sbt `version` setting should not be set directly. It
+// is the same as the Maven version and derived automatically from `baseVersion` and `baseVersionSuffix`.
+globalVersionSettings
+baseVersion in Global := "2.12.0"
+baseVersionSuffix in Global := "SNAPSHOT"
+
+lazy val commonSettings = clearSourceAndResourceDirectories ++ publishSettings ++ Seq[Setting[_]](
organization := "org.scala-lang",
- // The ANT build uses the file "build.number" and the property "build.release" to compute the version
- version := "2.12.0-SNAPSHOT",
scalaVersion := bootstrapScalaVersion,
// we don't cross build Scala itself
crossPaths := false,
@@ -524,8 +538,8 @@ lazy val test = project
.settings(
publishArtifact := false,
libraryDependencies ++= Seq(asmDep, partestDep, scalaXmlDep, partestInterfaceDep, scalacheckDep),
- unmanagedBase in Test := baseDirectory.value / "files" / "lib",
- unmanagedJars in Test <+= (unmanagedBase) (j => Attributed.blank(j)) map(identity),
+ unmanagedBase in IntegrationTest := baseDirectory.value / "files" / "lib",
+ unmanagedJars in IntegrationTest <+= (unmanagedBase) (j => Attributed.blank(j)) map(identity),
// no main sources
sources in Compile := Seq.empty,
// test sources are compiled in partest run, not here
@@ -534,6 +548,7 @@ lazy val test = project
javaOptions in IntegrationTest += "-Xmx1G",
testFrameworks += new TestFramework("scala.tools.partest.Framework"),
testOptions in IntegrationTest += Tests.Setup( () => root.base.getAbsolutePath + "/pull-binary-libs.sh" ! ),
+ testOptions in IntegrationTest += Tests.Argument("-Dpartest.java_opts=-Xmx1024M -Xms64M -XX:MaxPermSize=128M"),
definedTests in IntegrationTest += (
new sbt.TestDefinition(
"partest",
@@ -619,7 +634,13 @@ lazy val scalaDist = Project("scala-dist", file(".") / "target" / "scala-dist-di
lazy val root = (project in file("."))
.settings(disableDocs: _*)
- .settings(publishArtifact := false)
+ .settings(generateBuildCharacterFileSettings: _*)
+ .settings(
+ publishArtifact := false,
+ publish := {},
+ publishLocal := {},
+ commands ++= ScriptCommands.all
+ )
.aggregate(library, reflect, compiler, interactive, repl, replJline, replJlineEmbedded,
scaladoc, scalap, partestExtras, junit, libraryAll, scalaDist).settings(
sources in Compile := Seq.empty,
@@ -637,8 +658,14 @@ lazy val dist = (project in file("dist"))
.settings(
libraryDependencies ++= Seq(scalaSwingDep, jlineDep),
mkBin := mkBinImpl.value,
- mkQuick <<= Def.task {} dependsOn ((distDependencies.map(products in Runtime in _) :+ mkBin): _*),
- mkPack <<= Def.task {} dependsOn (packageBin in Compile, mkBin),
+ mkQuick <<= Def.task {
+ val cp = (fullClasspath in IntegrationTest in LocalProject("test")).value
+ val propsFile = (buildDirectory in ThisBuild).value / "quick" / "partest.properties"
+ val props = new java.util.Properties()
+ props.setProperty("partest.classpath", cp.map(_.data.getAbsolutePath).mkString(sys.props("path.separator")))
+ IO.write(props, null, propsFile)
+ } dependsOn ((distDependencies.map(products in Runtime in _) :+ mkBin): _*),
+ mkPack <<= Def.task {} dependsOn (packagedArtifact in (Compile, packageBin), mkBin),
target := (baseDirectory in ThisBuild).value / "target" / thisProject.value.id,
packageBin in Compile := {
val extraDeps = Set(scalaSwingDep, scalaParserCombinatorsDep, scalaXmlDep)
@@ -655,7 +682,7 @@ lazy val dist = (project in file("dist"))
},
cleanFiles += (buildDirectory in ThisBuild).value / "quick",
cleanFiles += (buildDirectory in ThisBuild).value / "pack",
- packageBin in Compile <<= (packageBin in Compile).dependsOn(distDependencies.map(packageBin in Compile in _): _*)
+ packagedArtifact in (Compile, packageBin) <<= (packagedArtifact in (Compile, packageBin)).dependsOn(distDependencies.map(packagedArtifact in (Compile, packageBin) in _): _*)
)
.dependsOn(distDependencies.map(p => p: ClasspathDep[ProjectReference]): _*)
@@ -708,9 +735,10 @@ lazy val mkBinImpl: Def.Initialize[Task[Seq[File]]] = Def.task {
scalaTool.writeScript(file, "windows", rootDir, outDir)
)
res.foreach { f =>
- //TODO 2.12: Use Files.setPosixFilePermissions() (Java 7+) instead of calling out to chmod
- if(Process(List("chmod", "ugo+rx", f.getAbsolutePath())).! > 0)
- throw new IOException("chmod failed")
+ if(!f.getAbsoluteFile.setExecutable(true, /* ownerOnly: */ false))
+ throw new IOException("setExecutable failed")
+ if(!f.getAbsoluteFile.setReadable(true, /* ownerOnly: */ false))
+ throw new IOException("setReadable failed")
}
res
}
diff --git a/build.xml b/build.xml
index 0a41870b21..78c7a9a230 100644
--- a/build.xml
+++ b/build.xml
@@ -483,6 +483,8 @@ TODO:
<property name="scalac.args.quick" value="${scalac.args.all}"/>
<property name="scalac.args.strap" value="${scalac.args.quick}"/>
+ <property name="partest.scalac_opts" value=""/> <!-- set default value, otherwise the property name will be passed to partest if undefined -->
+
<!-- This is the start time for the distribution -->
<tstamp prefix="time">
<format property="human" pattern="d MMMM yyyy, HH:mm:ss" locale="en,US"/>
diff --git a/project/JarJar.scala b/project/JarJar.scala
index 2eec0e9033..918060c9ee 100644
--- a/project/JarJar.scala
+++ b/project/JarJar.scala
@@ -35,12 +35,12 @@ object JarJar {
}
case class JarEntryInput(jarFile: JarFile, entry: JarEntry) extends Entry {
- def name = entry.getName
+ def name = entry.getName.replace('\\', '/')
def time = entry.getTime
def data = sbt.IO.readBytes(jarFile.getInputStream(entry))
}
case class FileInput(base: File, file: File) extends Entry {
- def name = file.relativeTo(base).get.getPath
+ def name = file.relativeTo(base).get.getPath.replace('\\', '/')
def time = file.lastModified
def data = sbt.IO.readBytes(file)
}
diff --git a/project/Osgi.scala b/project/Osgi.scala
index 78370b695b..4676119076 100644
--- a/project/Osgi.scala
+++ b/project/Osgi.scala
@@ -63,6 +63,7 @@ object Osgi {
val jar = synchronized { builder.build }
builder.getWarnings.foreach(s => log.warn(s"bnd: $s"))
builder.getErrors.foreach(s => log.error(s"bnd: $s"))
+ IO.createDirectory(artifactPath.getParentFile)
jar.write(artifactPath)
artifactPath
}
diff --git a/project/ScalaTool.scala b/project/ScalaTool.scala
index 559b215c18..e9531f229e 100644
--- a/project/ScalaTool.scala
+++ b/project/ScalaTool.scala
@@ -1,4 +1,5 @@
import sbt._
+import org.apache.commons.lang3.SystemUtils
import org.apache.commons.lang3.StringUtils.replaceEach
/**
@@ -15,8 +16,15 @@ case class ScalaTool(mainClass: String,
// demarcation of any script variables (e.g. `${SCALA_HOME}` or
// `%SCALA_HOME%`) can be specified in a platform independent way (e.g.
// `@SCALA_HOME@`) and automatically translated for you.
- def patchedToolScript(template: String, platform: String) = {
+ def patchedToolScript(template: String, forWindows: Boolean) = {
val varRegex = """@(\w+)@""" // the group should be able to capture each of the keys of the map below
+ val platformClasspath =
+ if(forWindows) classpath.mkString(";").replace('/', '\\').replaceAll(varRegex, "%$1%")
+ else if(SystemUtils.IS_OS_WINDOWS) {
+ // When building on Windows, use a Windows classpath in the shell script (for MSYS/Cygwin).
+ // This is only used for "quick", which uses absolute paths, so it is not portable anyway.
+ classpath.mkString(";").replace("\\", "\\\\").replaceAll(varRegex, """\${$1}""")
+ } else classpath.mkString(":").replace('\\', '/').replaceAll(varRegex, """\${$1}""")
val variables = Map(
("@@" -> "@"), // for backwards compatibility
@@ -24,10 +32,7 @@ case class ScalaTool(mainClass: String,
("@properties@" -> (properties map { case (k, v) => s"""-D$k="$v""""} mkString " ")),
("@javaflags@" -> javaOpts),
("@toolflags@" -> toolFlags),
- ("@classpath@" -> (platform match {
- case "unix" => classpath.mkString(":").replace('\\', '/').replaceAll(varRegex, """\${$1}""")
- case "windows" => classpath.mkString(";").replace('/', '\\').replaceAll(varRegex, "%$1%")
- }))
+ ("@classpath@" -> platformClasspath)
)
val (from, to) = variables.unzip
@@ -35,10 +40,12 @@ case class ScalaTool(mainClass: String,
}
def writeScript(file: String, platform: String, rootDir: File, outDir: File): File = {
+ val forWindows = platform match { case "windows" => true case _ => false }
val templatePath = s"scala/tools/ant/templates/tool-$platform.tmpl"
- val suffix = platform match { case "windows" => ".bat" case _ => "" }
+ val suffix = if(forWindows) ".bat" else ""
val scriptFile = outDir / s"$file$suffix"
- IO.write(scriptFile, patchedToolScript(IO.read(rootDir / templatePath), platform))
+ val patched = patchedToolScript(IO.read(rootDir / templatePath).replace("\r", ""), forWindows)
+ IO.write(scriptFile, if(forWindows) patched.replace("\n", "\r\n") else patched)
scriptFile
}
}
diff --git a/project/ScriptCommands.scala b/project/ScriptCommands.scala
new file mode 100644
index 0000000000..537990d985
--- /dev/null
+++ b/project/ScriptCommands.scala
@@ -0,0 +1,19 @@
+import sbt._
+import Keys._
+import complete.DefaultParsers._
+
+/** Custom commands for use by the Jenkins scripts. This keeps the surface area and call syntax small. */
+object ScriptCommands {
+ def all = Seq(setupPublishCore)
+
+ /** Set up the environment for `validate/publish-core`. The argument is the Artifactory snapshot repository URL. */
+ def setupPublishCore = Command.single("setupPublishCore") { case (state, url) =>
+ Project.extract(state).append(Seq(
+ VersionUtil.baseVersionSuffix in Global := "SHA-SNAPSHOT",
+ // Append build.timestamp to Artifactory URL to get consistent build numbers (see https://github.com/sbt/sbt/issues/2088):
+ publishTo in Global := Some("scala-pr" at url.replaceAll("/$", "") + ";build.timestamp=" + System.currentTimeMillis),
+ publishArtifact in (Compile, packageDoc) in ThisBuild := false,
+ scalacOptions in Compile in ThisBuild += "-optimise"
+ ), state)
+ }
+}
diff --git a/project/VersionUtil.scala b/project/VersionUtil.scala
index 71de772b08..f237c35c68 100644
--- a/project/VersionUtil.scala
+++ b/project/VersionUtil.scala
@@ -5,21 +5,29 @@ import java.io.FileInputStream
import scala.collection.JavaConverters._
object VersionUtil {
+ lazy val baseVersion = settingKey[String]("The base version number from which all others are derived")
+ lazy val baseVersionSuffix = settingKey[String]("Identifies the kind of version to build")
lazy val copyrightString = settingKey[String]("Copyright string.")
lazy val versionProperties = settingKey[Versions]("Version properties.")
lazy val generateVersionPropertiesFile = taskKey[File]("Generating version properties file.")
+ lazy val generateBuildCharacterPropertiesFile = taskKey[File]("Generating buildcharacter.properties file.")
- lazy val versionPropertiesSettings = Seq[Setting[_]](
- versionProperties := versionPropertiesImpl.value
+ lazy val globalVersionSettings = Seq[Setting[_]](
+ // Set the version properties globally (they are the same for all projects)
+ versionProperties in Global := versionPropertiesImpl.value,
+ version in Global := versionProperties.value.mavenVersion
)
lazy val generatePropertiesFileSettings = Seq[Setting[_]](
copyrightString := "Copyright 2002-2015, LAMP/EPFL",
resourceGenerators in Compile += generateVersionPropertiesFile.map(file => Seq(file)).taskValue,
- versionProperties := versionPropertiesImpl.value,
generateVersionPropertiesFile := generateVersionPropertiesFileImpl.value
)
+ lazy val generateBuildCharacterFileSettings = Seq[Setting[_]](
+ generateBuildCharacterPropertiesFile := generateBuildCharacterPropertiesFileImpl.value
+ )
+
case class Versions(canonicalVersion: String, mavenVersion: String, osgiVersion: String, commitSha: String, commitDate: String, isRelease: Boolean) {
val githubTree =
if(isRelease) "v" + mavenVersion
@@ -28,30 +36,36 @@ object VersionUtil {
override def toString = s"Canonical: $canonicalVersion, Maven: $mavenVersion, OSGi: $osgiVersion, github: $githubTree"
- def toProperties: Properties = {
- val props = new Properties
- props.put("version.number", canonicalVersion)
- props.put("maven.version.number", mavenVersion)
- props.put("osgi.version.number", osgiVersion)
- props
- }
+ def toMap: Map[String, String] = Map(
+ "version.number" -> canonicalVersion,
+ "maven.version.number" -> mavenVersion,
+ "osgi.version.number" -> osgiVersion
+ )
}
- lazy val versionPropertiesImpl: Def.Initialize[Versions] = Def.setting {
- /** Regexp that splits version number split into two parts: version and suffix.
- * Examples of how the split is performed:
- *
- * "2.11.5": ("2.11.5", null)
- * "2.11.5-acda7a": ("2.11.5", "-acda7a")
- * "2.11.5-SNAPSHOT": ("2.11.5", "-SNAPSHOT") */
- val versionSplitted = """([\w+\.]+)(-[\w+\.]+)??""".r
-
- val versionSplitted(ver, suffixOrNull) = version.value
-
- val osgiSuffix = suffixOrNull match {
- case null => "-VFINAL"
- case "-SNAPSHOT" => ""
- case suffixStr => suffixStr
+ /** Compute the canonical, Maven and OSGi version number from `baseVersion` and `baseVersionSuffix`.
+ * Examples of the generated versions:
+ *
+ * ("2.11.8", "SNAPSHOT" ) -> ("2.11.8-20151215-133023-7559aed3c5", "2.11.8-SNAPSHOT", "2.11.8.v20151215-133023-7559aed3c5")
+ * ("2.11.8", "SHA-SNAPSHOT") -> ("2.11.8-20151215-133023-7559aed3c5", "2.11.8-7559aed3c5-SNAPSHOT", "2.11.8.v20151215-133023-7559aed3c5")
+ * ("2.11.8", "" ) -> ("2.11.8", "2.11.8", "2.11.8.v20151215-133023-VFINAL-7559aed3c5")
+ * ("2.11.8", "M3" ) -> ("2.11.8-M3", "2.11.8-M3", "2.11.8.v20151215-133023-M3-7559aed3c5")
+ * ("2.11.8", "RC4" ) -> ("2.11.8-RC4", "2.11.8-RC4", "2.11.8.v20151215-133023-RC4-7559aed3c5")
+ * ("2.11.8-RC4", "SPLIT" ) -> ("2.11.8-RC4", "2.11.8-RC4", "2.11.8.v20151215-133023-RC4-7559aed3c5")
+ *
+ * A `baseVersionSuffix` of "SNAPSHOT" is the default, which is used for local snapshot builds. The PR validation
+ * job uses "SHA-SNAPSHOT". An empty suffix is used for releases. All other suffix values are treated as RC /
+ * milestone builds. The special suffix value "SPLIT" is used to split the real suffix off from `baseVersion`
+ * instead and then apply the usual logic. */
+ private lazy val versionPropertiesImpl: Def.Initialize[Versions] = Def.setting {
+
+ val (base, suffix) = {
+ val (b, s) = (baseVersion.value, baseVersionSuffix.value)
+ if(s == "SPLIT") {
+ val split = """([\w+\.]+)(-[\w+\.]+)??""".r
+ val split(b2, sOrNull) = b
+ (b2, Option(sOrNull).map(_.drop(1)).getOrElse(""))
+ } else (b, s)
}
def executeTool(tool: String) = {
@@ -62,24 +76,31 @@ object VersionUtil {
Process(cmd).lines.head
}
- val commitDate = executeTool("get-scala-commit-date")
- val commitSha = executeTool("get-scala-commit-sha")
+ val date = executeTool("get-scala-commit-date")
+ val sha = executeTool("get-scala-commit-sha").substring(0, 7) // The script produces 10 digits at the moment
- Versions(
- canonicalVersion = s"$ver-$commitDate-$commitSha",
- mavenVersion = s"${version.value}",
- osgiVersion = s"$ver.v$commitDate$osgiSuffix-$commitSha",
- commitSha = commitSha,
- commitDate = commitDate,
- isRelease = !osgiSuffix.isEmpty
- )
+ val (canonicalV, mavenV, osgiV, release) = suffix match {
+ case "SNAPSHOT" => (s"$base-$date-$sha", s"$base-SNAPSHOT", s"$base.v$date-$sha", false)
+ case "SHA-SNAPSHOT" => (s"$base-$date-$sha", s"$base-$sha-SNAPSHOT", s"$base.v$date-$sha", false)
+ case "" => (s"$base", s"$base", s"$base.v$date-VFINAL-$sha", true)
+ case suffix => (s"$base-$suffix", s"$base-$suffix", s"$base.v$date-$suffix-$sha", true)
+ }
+
+ Versions(canonicalV, mavenV, osgiV, sha, date, release)
}
- lazy val generateVersionPropertiesFileImpl: Def.Initialize[Task[File]] = Def.task {
- val props = versionProperties.value.toProperties
- val propFile = (resourceManaged in Compile).value / s"${thisProject.value.id}.properties"
- props.put("copyright.string", copyrightString.value)
+ private lazy val generateVersionPropertiesFileImpl: Def.Initialize[Task[File]] = Def.task {
+ writeProps(versionProperties.value.toMap + ("copyright.string" -> copyrightString.value),
+ (resourceManaged in Compile).value / s"${thisProject.value.id}.properties")
+ }
+
+ private lazy val generateBuildCharacterPropertiesFileImpl: Def.Initialize[Task[File]] = Def.task {
+ writeProps(versionProperties.value.toMap, (baseDirectory in ThisBuild).value / "buildcharacter.properties")
+ }
+ private def writeProps(m: Map[String, String], propFile: File): File = {
+ val props = new Properties
+ m.foreach { case (k, v) => props.put(k, v) }
// unfortunately, this will write properties in arbitrary order
// this makes it harder to test for stability of generated artifacts
// consider using https://github.com/etiennestuder/java-ordered-properties
diff --git a/scripts/common b/scripts/common
index b075469379..35199992bc 100644
--- a/scripts/common
+++ b/scripts/common
@@ -18,6 +18,9 @@ IVY_CACHE="$WORKSPACE/.ivy2"
mkdir -p $IVY_CACHE
rm -rf $IVY_CACHE/cache/org.scala-lang
+SBT_CMD=${sbtCmd-sbt}
+SBT_CMD="$SBT_CMD -sbt-version 0.13.9"
+
# temp dir where all 'non-build' operation are performed
TMP_ROOT_DIR=$(mktemp -d -t pr-scala.XXXX)
TMP_DIR="${TMP_ROOT_DIR}/tmp"
diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap
index b2ae195dc4..410fe573f8 100755
--- a/scripts/jobs/integrate/bootstrap
+++ b/scripts/jobs/integrate/bootstrap
@@ -22,7 +22,7 @@
# - To prevent staging on sonatype (for testing), set publishToSonatype to anything but "yes"
# - Note: After building a release, the jenkins job provides an updated versions.properties file as artifact.
# Put this file in the Scala repo and create a pull request, and also update the file build.number.
-#
+#
# - Otherwise, a nightly release is built:
# - version number is read from the build.number file, extended with -$sha-nightly
@@ -73,7 +73,7 @@
# Requirements
-# - sbtCmd must point to sbt from sbt-extras
+# - SBT_CMD must point to sbt from sbt-extras
# - ~/.sonatype-curl, ~/.m2/settings.xml, ~/.credentials, ~/.credentials-sonatype, ~/.credentials-private-repo
# as defined by https://github.com/scala/scala-jenkins-infra/tree/master/templates/default
# - ~/.sbt/0.13/plugins/gpg.sbt with:
@@ -89,10 +89,6 @@ publishSonatypeTaskCore=${publishSonatypeTaskCore-"publish-signed"}
publishSonatypeTaskModules=${publishSonatypeTaskModules-"publish-signed"}
publishLockerPrivateTask=${publishLockerPrivateTask-$publishPrivateTask} # set to "init" to speed up testing of the script (if you already built locker before)
-sbtCmd=${sbtCmd-sbt} # TESTING (this is a marker for defaults to change when testing locally: should be sbtx on my mac)
-
-sbtCmd="$sbtCmd -sbt-version 0.13.8"
-
forceRebuild=${forceRebuild-no}
antBuildTask="${antBuildTask-nightly}" # TESTING leave empty to avoid the sanity check (don't set it to "init" because ant will croak)
@@ -180,8 +176,8 @@ function st_stagingRepoClose() {
sbtArgs="-no-colors -ivy $baseDir/ivy2 -Dsbt.override.build.repos=true -Dsbt.repository.config=$sbtRepositoryConfig -Dsbt.global.base=$HOME/.sbt/0.13 -sbt-dir $HOME/.sbt/0.13"
sbtBuild() {
- echo "### sbtBuild: "$sbtCmd $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@"
- $sbtCmd $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@" >> $baseDir/logs/builds 2>&1
+ echo "### sbtBuild: "$SBT_CMD $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@"
+ $SBT_CMD $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@" >> $baseDir/logs/builds 2>&1
}
sbtResolve() {
@@ -189,8 +185,8 @@ sbtResolve() {
touch build.sbt
# Can be set to `full` if a module requires cross-versioning against the full Scala version, like the continuations plugin used to.
cross=${4-binary}
- echo "### sbtResolve: $sbtCmd $sbtArgs " "${scalaVersionTasks[@]}" "\"$1\" % \"$2\" % \"$3\" cross CrossVersion.$cross"
- $sbtCmd $sbtArgs "${scalaVersionTasks[@]}" \
+ echo "### sbtResolve: $SBT_CMD $sbtArgs " "${scalaVersionTasks[@]}" "\"$1\" % \"$2\" % \"$3\" cross CrossVersion.$cross"
+ $SBT_CMD $sbtArgs "${scalaVersionTasks[@]}" \
"set libraryDependencies := Seq(\"$1\" % \"$2\" % \"$3\" cross CrossVersion.$cross)" \
'show update' >> $baseDir/logs/resolution 2>&1
}
diff --git a/scripts/jobs/validate/publish-core b/scripts/jobs/validate/publish-core
index 9dff5a34b0..bb0056722d 100755
--- a/scripts/jobs/validate/publish-core
+++ b/scripts/jobs/validate/publish-core
@@ -15,17 +15,8 @@ case $prDryRun in
mkdir -p build/pack ; mkdir -p dists/maven/latest
;;
*)
- sha=$(git rev-parse HEAD) # TODO: warn if $repo_ref != $sha (we shouldn't do PR validation using symbolic gitrefs)
- echo "sha/repo_ref == $sha/$repo_ref ?"
-
- parseScalaProperties build.number
-
- ./pull-binary-libs.sh
- # "noyoudont" is there juuuust in case
- antDeployArgs="-Dmaven.version.suffix=\"-${sha:0:7}-SNAPSHOT\" -Dremote.snapshot.repository=$prRepoUrl -Drepository.credentials.id=pr-scala -Dremote.release.repository=noyoudont"
-
echo ">>> Getting Scala version number."
- ant -q $antDeployArgs init
+ $SBT_CMD "setupPublishCore $prRepoUrl" generateBuildCharacterPropertiesFile
parseScalaProperties buildcharacter.properties # produce maven_version_number
echo ">>> Checking availability of Scala ${maven_version_number} in $prRepoUrl."
@@ -36,7 +27,7 @@ case $prDryRun in
if $libraryAvailable && $reflectAvailable && $compilerAvailable; then
echo "Scala core already built!"
else
- ant $antDeployArgs $antBuildArgs publish-opt-nodocs
+ $SBT_CMD "setupPublishCore $prRepoUrl" $antBuildArgs publish
fi
mv buildcharacter.properties jenkins.properties # parsed by the jenkins job
diff --git a/src/compiler/scala/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/reflect/quasiquotes/Parsers.scala
index 6972c4070c..c695f438a4 100644
--- a/src/compiler/scala/reflect/quasiquotes/Parsers.scala
+++ b/src/compiler/scala/reflect/quasiquotes/Parsers.scala
@@ -56,6 +56,10 @@ trait Parsers { self: Quasiquotes =>
override implicit lazy val fresh: FreshNameCreator = new FreshNameCreator(nme.QUASIQUOTE_PREFIX)
+ // Do not check for tuple arity. The placeholders can support arbitrary tuple sizes.
+ override def makeSafeTupleTerm(trees: List[Tree], offset: Offset): Tree = treeBuilder.makeTupleTerm(trees)
+ override def makeSafeTupleType(trees: List[Tree], offset: Offset): Tree = treeBuilder.makeTupleType(trees)
+
override val treeBuilder = new ParserTreeBuilder {
override implicit def fresh: FreshNameCreator = parser.fresh
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 1d96b940ae..831a0412cd 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -774,7 +774,58 @@ self =>
@inline final def caseSeparated[T](part: => T): List[T] = tokenSeparated(CASE, sepFirst = true, part)
def readAnnots(part: => Tree): List[Tree] = tokenSeparated(AT, sepFirst = true, part)
-/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
+ /** Create a tuple type Tree. If the arity is not supported, a syntax error is emitted. */
+ def makeSafeTupleType(elems: List[Tree], offset: Offset) = {
+ if (checkTupleSize(elems, offset)) makeTupleType(elems)
+ else makeTupleType(Nil) // create a dummy node; makeTupleType(elems) would fail
+ }
+
+ /** Create a tuple term Tree. If the arity is not supported, a syntax error is emitted. */
+ def makeSafeTupleTerm(elems: List[Tree], offset: Offset) = {
+ checkTupleSize(elems, offset)
+ makeTupleTerm(elems)
+ }
+
+ private[this] def checkTupleSize(elems: List[Tree], offset: Offset): Boolean =
+ if (elems.lengthCompare(definitions.MaxTupleArity) > 0) {
+ syntaxError(offset, "too many elements for tuple: "+elems.length+", allowed: "+definitions.MaxTupleArity, skipIt = false)
+ false
+ } else true
+
+ /** Strip the artifitial `Parens` node to create a tuple term Tree. */
+ def stripParens(t: Tree) = t match {
+ case Parens(ts) => atPos(t.pos) { makeSafeTupleTerm(ts, t.pos.point) }
+ case _ => t
+ }
+
+ /** Create tree representing (unencoded) binary operation expression or pattern. */
+ def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position, targs: List[Tree] = Nil): Tree = {
+ require(isExpr || targs.isEmpty || targs.exists(_.isErroneous), s"Incompatible args to makeBinop: !isExpr but targs=$targs")
+
+ def mkSelection(t: Tree) = {
+ def sel = atPos(opPos union t.pos)(Select(stripParens(t), op.encode))
+ if (targs.isEmpty) sel else atPos(left.pos)(TypeApply(sel, targs))
+ }
+ def mkNamed(args: List[Tree]) = if (isExpr) args map treeInfo.assignmentToMaybeNamedArg else args
+ val arguments = right match {
+ case Parens(args) => mkNamed(args)
+ case _ => List(right)
+ }
+ if (isExpr) {
+ if (treeInfo.isLeftAssoc(op)) {
+ Apply(mkSelection(left), arguments)
+ } else {
+ val x = freshTermName()
+ Block(
+ List(ValDef(Modifiers(symtab.Flags.SYNTHETIC | symtab.Flags.ARTIFACT), x, TypeTree(), stripParens(left))),
+ Apply(mkSelection(right), List(Ident(x))))
+ }
+ } else {
+ Apply(Ident(op.encode), stripParens(left) :: arguments)
+ }
+ }
+
+ /* --------- OPERAND/OPERATOR STACK --------------------------------------- */
/** Modes for infix types. */
object InfixMode extends Enumeration {
@@ -878,7 +929,7 @@ self =>
atPos(start, in.skipToken()) { makeFunctionTypeTree(ts, typ()) }
else {
ts foreach checkNotByNameOrVarargs
- val tuple = atPos(start) { makeTupleType(ts) }
+ val tuple = atPos(start) { makeSafeTupleType(ts, start) }
infixTypeRest(
compoundTypeRest(
annotTypeRest(
@@ -945,7 +996,7 @@ self =>
def simpleType(): Tree = {
val start = in.offset
simpleTypeRest(in.token match {
- case LPAREN => atPos(start)(makeTupleType(inParens(types())))
+ case LPAREN => atPos(start)(makeSafeTupleType(inParens(types()), start))
case USCORE => wildcardType(in.skipToken())
case _ =>
path(thisOK = false, typeOK = true) match {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 6b564197a1..473a40f42a 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -42,44 +42,12 @@ abstract class TreeBuilder {
def makeTupleType(elems: List[Tree]) = gen.mkTupleType(elems)
- def stripParens(t: Tree) = t match {
- case Parens(ts) => atPos(t.pos) { makeTupleTerm(ts) }
- case _ => t
- }
-
def makeAnnotated(t: Tree, annot: Tree): Tree =
atPos(annot.pos union t.pos)(Annotated(annot, t))
def makeSelfDef(name: TermName, tpt: Tree): ValDef =
ValDef(Modifiers(PRIVATE), name, tpt, EmptyTree)
- /** Create tree representing (unencoded) binary operation expression or pattern. */
- def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position, targs: List[Tree] = Nil): Tree = {
- require(isExpr || targs.isEmpty || targs.exists(_.isErroneous), s"Incompatible args to makeBinop: !isExpr but targs=$targs")
-
- def mkSelection(t: Tree) = {
- def sel = atPos(opPos union t.pos)(Select(stripParens(t), op.encode))
- if (targs.isEmpty) sel else atPos(left.pos)(TypeApply(sel, targs))
- }
- def mkNamed(args: List[Tree]) = if (isExpr) args map treeInfo.assignmentToMaybeNamedArg else args
- val arguments = right match {
- case Parens(args) => mkNamed(args)
- case _ => List(right)
- }
- if (isExpr) {
- if (treeInfo.isLeftAssoc(op)) {
- Apply(mkSelection(left), arguments)
- } else {
- val x = freshTermName()
- Block(
- List(ValDef(Modifiers(SYNTHETIC | ARTIFACT), x, TypeTree(), stripParens(left))),
- Apply(mkSelection(right), List(Ident(x))))
- }
- } else {
- Apply(Ident(op.encode), stripParens(left) :: arguments)
- }
- }
-
/** Tree for `od op`, start is start0 if od.pos is borked. */
def makePostfixSelect(start0: Int, end: Int, od: Tree, op: Name): Tree = {
val start = if (od.pos.isDefined) od.pos.start else start0
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
index 4a10756468..328a8187c8 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
@@ -40,7 +40,7 @@ abstract class BCodeIdiomatic extends SubComponent {
if (emitStackMapFrame) asm.ClassWriter.COMPUTE_FRAMES else 0
)
- val StringBuilderClassName = "scala/collection/mutable/StringBuilder"
+ lazy val JavaStringBuilderClassName = jlStringBuilderRef.internalName
val EMPTY_STRING_ARRAY = Array.empty[String]
val EMPTY_INT_ARRAY = Array.empty[Int]
@@ -184,10 +184,10 @@ abstract class BCodeIdiomatic extends SubComponent {
* can-multi-thread
*/
final def genStartConcat(pos: Position): Unit = {
- jmethod.visitTypeInsn(Opcodes.NEW, StringBuilderClassName)
+ jmethod.visitTypeInsn(Opcodes.NEW, JavaStringBuilderClassName)
jmethod.visitInsn(Opcodes.DUP)
invokespecial(
- StringBuilderClassName,
+ JavaStringBuilderClassName,
INSTANCE_CONSTRUCTOR_NAME,
"()V",
pos
@@ -198,21 +198,23 @@ abstract class BCodeIdiomatic extends SubComponent {
* can-multi-thread
*/
final def genStringConcat(el: BType, pos: Position): Unit = {
-
- val jtype =
- if (el.isArray || el.isClass) ObjectRef
- else el
+ val jtype = el match {
+ case ct: ClassBType if ct.isSubtypeOf(StringRef).get => StringRef
+ case ct: ClassBType if ct.isSubtypeOf(jlStringBufferRef).get => jlStringBufferRef
+ case ct: ClassBType if ct.isSubtypeOf(jlCharSequenceRef).get => jlCharSequenceRef
+ case rt: RefBType => ObjectRef
+ case pt: PrimitiveBType => pt // Currently this ends up being boxed in erasure
+ }
val bt = MethodBType(List(jtype), jlStringBuilderRef)
-
- invokevirtual(StringBuilderClassName, "append", bt.descriptor, pos)
+ invokevirtual(JavaStringBuilderClassName, "append", bt.descriptor, pos)
}
/*
* can-multi-thread
*/
final def genEndConcat(pos: Position): Unit = {
- invokevirtual(StringBuilderClassName, "toString", "()Ljava/lang/String;", pos)
+ invokevirtual(JavaStringBuilderClassName, "toString", "()Ljava/lang/String;", pos)
}
/*
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
index 8bb71a386f..6d322d1a34 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
@@ -95,7 +95,9 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) {
lazy val ObjectRef : ClassBType = classBTypeFromSymbol(ObjectClass)
lazy val StringRef : ClassBType = classBTypeFromSymbol(StringClass)
lazy val PredefRef : ClassBType = classBTypeFromSymbol(PredefModule.moduleClass)
- lazy val jlStringBuilderRef : ClassBType = classBTypeFromSymbol(StringBuilderClass)
+ lazy val jlStringBuilderRef : ClassBType = classBTypeFromSymbol(JavaStringBuilderClass)
+ lazy val jlStringBufferRef : ClassBType = classBTypeFromSymbol(JavaStringBufferClass)
+ lazy val jlCharSequenceRef : ClassBType = classBTypeFromSymbol(JavaCharSequenceClass)
lazy val jlThrowableRef : ClassBType = classBTypeFromSymbol(ThrowableClass)
lazy val jlCloneableRef : ClassBType = classBTypeFromSymbol(JavaCloneableClass) // java/lang/Cloneable
lazy val jiSerializableRef : ClassBType = classBTypeFromSymbol(JavaSerializableClass) // java/io/Serializable
@@ -343,6 +345,8 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes:
def StringRef : ClassBType = _coreBTypes.StringRef
def PredefRef : ClassBType = _coreBTypes.PredefRef
def jlStringBuilderRef : ClassBType = _coreBTypes.jlStringBuilderRef
+ def jlStringBufferRef : ClassBType = _coreBTypes.jlStringBufferRef
+ def jlCharSequenceRef : ClassBType = _coreBTypes.jlCharSequenceRef
def jlThrowableRef : ClassBType = _coreBTypes.jlThrowableRef
def jlCloneableRef : ClassBType = _coreBTypes.jlCloneableRef
def jiSerializableRef : ClassBType = _coreBTypes.jiSerializableRef
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala
index 4ecaf17a10..16fe2e5cff 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala
@@ -21,7 +21,7 @@ class BoxUnbox[BT <: BTypes](val btypes: BT) {
import backendUtils._
/**
- * Eliminate box-unbox paris within `method`. Such appear commonly after closure elimination:
+ * Eliminate box-unbox pairs within `method`. Such appear commonly after closure elimination:
*
* def t2 = {
* val f = (b: Byte, i: Int) => i + b // no specialized variant for this function type
@@ -767,7 +767,7 @@ class BoxUnbox[BT <: BTypes](val btypes: BT) {
private def isSpecializedTupleClass(tupleClass: InternalName) = specializedTupleClassR.pattern.matcher(tupleClass).matches
private val specializedTupleGetterR = "_[12]\\$mc[IJDCZ]\\$sp".r
- private def isSpecializedTupleGetter(mi: MethodInsnNode) = specializedTupleGetterR.pattern.matcher(mi.name)matches
+ private def isSpecializedTupleGetter(mi: MethodInsnNode) = specializedTupleGetterR.pattern.matcher(mi.name).matches
private val tupleGetterR = "_\\d\\d?".r
private def isTupleGetter(mi: MethodInsnNode) = tupleGetterR.pattern.matcher(mi.name).matches
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
index ff36f36589..9a90c53d3e 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
@@ -125,7 +125,7 @@ object BytecodeUtils {
}
def sameTargetExecutableInstruction(a: JumpInsnNode, b: JumpInsnNode): Boolean = {
- // Compare next executable instead of the the labels. Identifies a, b as the same target:
+ // Compare next executable instead of the labels. Identifies a, b as the same target:
// LabelNode(a)
// LabelNode(b)
// Instr
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
index 039e6a6d03..b8547e1dc6 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
@@ -75,10 +75,10 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) {
def rewriteClosureApplyInvocations(): Unit = {
// sort all closure invocations to rewrite to ensure bytecode stability
- val toRewrite = new java.util.TreeMap[ClosureInstantiation, mutable.ArrayBuffer[(MethodInsnNode, Int)]](closureInitOrdering)
+ val toRewrite = mutable.TreeMap.empty[ClosureInstantiation, mutable.ArrayBuffer[(MethodInsnNode, Int)]](closureInitOrdering)
def addRewrite(init: ClosureInstantiation, invocation: MethodInsnNode, stackHeight: Int): Unit = {
- if (!toRewrite.containsKey(init)) toRewrite.put(init, mutable.ArrayBuffer.empty[(MethodInsnNode, Int)])
- toRewrite.get(init) += ((invocation, stackHeight))
+ val callsites = toRewrite.getOrElseUpdate(init, mutable.ArrayBuffer.empty[(MethodInsnNode, Int)])
+ callsites += ((invocation, stackHeight))
}
// For each closure instantiation find callsites of the closure and add them to the toRewrite
@@ -113,9 +113,7 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) {
case _ =>
}
- for (entry <- toRewrite.entrySet.iterator().asScala) {
- val closureInit = entry.getKey
- val invocations = entry.getValue
+ for ((closureInit, invocations) <- toRewrite) {
// Local variables that hold the captured values and the closure invocation arguments.
val (localsForCapturedValues, argumentLocalsList) = localsForClosureRewrite(closureInit)
for ((invocation, stackHeight) <- invocations)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
index c1fdb7eb59..f486bb0cb9 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
@@ -771,154 +771,173 @@ object LocalOptImpls {
// A set of all exception handlers that guard the current instruction, required for simplifyGotoReturn
var activeHandlers = Set.empty[TryCatchBlockNode]
- // Instructions that need to be removed. simplifyBranchOverGoto returns an instruction to be
- // removed. It cannot remove it itself because the instruction may be the successor of the current
- // instruction of the iterator, which is not supported in ASM.
- var instructionsToRemove = Set.empty[AbstractInsnNode]
+ val jumpInsns = mutable.LinkedHashMap.empty[JumpInsnNode, Boolean]
- val iterator = method.instructions.iterator()
- while (iterator.hasNext) {
- val instruction = iterator.next()
+ for (insn <- method.instructions.iterator().asScala) insn match {
+ case l: LabelNode =>
+ activeHandlers ++= allHandlers.filter(_.start == l)
+ activeHandlers = activeHandlers.filter(_.end != l)
- instruction match {
- case l: LabelNode =>
- activeHandlers ++= allHandlers.filter(_.start == l)
- activeHandlers = activeHandlers.filter(_.end != l)
- case _ =>
+ case ji: JumpInsnNode =>
+ jumpInsns(ji) = activeHandlers.nonEmpty
+
+ case _ =>
+ }
+
+ var _jumpTargets: Set[AbstractInsnNode] = null
+ def jumpTargets = {
+ if (_jumpTargets == null) {
+ _jumpTargets = jumpInsns.keysIterator.map(_.label).toSet
}
+ _jumpTargets
+ }
- if (instructionsToRemove(instruction)) {
- iterator.remove()
- instructionsToRemove -= instruction
- } else if (isJumpNonJsr(instruction)) { // fast path - all of the below only treat jumps
- var jumpRemoved = simplifyThenElseSameTarget(method, instruction)
+ def removeJumpFromMap(jump: JumpInsnNode) = {
+ jumpInsns.remove(jump)
+ _jumpTargets = null
+ }
- if (!jumpRemoved) {
- changed = collapseJumpChains(instruction) || changed
- jumpRemoved = removeJumpToSuccessor(method, instruction)
+ def replaceJumpByPop(jump: JumpInsnNode) = {
+ removeJumpAndAdjustStack(method, jump)
+ removeJumpFromMap(jump)
+ }
- if (!jumpRemoved) {
- val staleGoto = simplifyBranchOverGoto(method, instruction)
- instructionsToRemove ++= staleGoto
- changed ||= staleGoto.nonEmpty
- changed = simplifyGotoReturn(method, instruction, inTryBlock = activeHandlers.nonEmpty) || changed
- }
+ /**
+ * Removes a conditional jump if it is followed by a GOTO to the same destination.
+ *
+ * CondJump l; [nops]; GOTO l; [...]
+ * POP*; [nops]; GOTO l; [...]
+ *
+ * Introduces 1 or 2 POP instructions, depending on the number of values consumed by the CondJump.
+ */
+ def simplifyThenElseSameTarget(insn: AbstractInsnNode): Boolean = insn match {
+ case ConditionalJump(jump) =>
+ nextExecutableInstruction(insn) match {
+ case Some(Goto(elseJump)) if sameTargetExecutableInstruction(jump, elseJump) =>
+ replaceJumpByPop(jump)
+ true
+
+ case _ => false
}
- changed ||= jumpRemoved
- }
+
+ case _ => false
}
- assert(instructionsToRemove.isEmpty, "some optimization required removing a previously traversed instruction. add `instructionsToRemove.foreach(method.instructions.remove)`")
- changed
- }
- /**
- * Removes a conditional jump if it is followed by a GOTO to the same destination.
- *
- * CondJump l; [nops]; GOTO l; [...]
- * POP*; [nops]; GOTO l; [...]
- *
- * Introduces 1 or 2 POP instructions, depending on the number of values consumed by the CondJump.
- */
- private def simplifyThenElseSameTarget(method: MethodNode, instruction: AbstractInsnNode): Boolean = instruction match {
- case ConditionalJump(jump) =>
- nextExecutableInstruction(instruction) match {
- case Some(Goto(elseJump)) if sameTargetExecutableInstruction(jump, elseJump) =>
- removeJumpAndAdjustStack(method, jump)
+ /**
+ * Replace jumps to a sequence of GOTO instructions by a jump to the final destination.
+ *
+ * Jump l; [any ops]; l: GOTO m; [any ops]; m: GOTO n; [any ops]; n: NotGOTO; [...]
+ * => Jump n; [rest unchanged]
+ *
+ * If there's a loop of GOTOs, the initial jump is replaced by one of the labels in the loop.
+ */
+ def collapseJumpChains(insn: AbstractInsnNode): Boolean = insn match {
+ case JumpNonJsr(jump) =>
+ val target = finalJumpTarget(jump)
+ if (jump.label == target) false else {
+ jump.label = target
+ _jumpTargets = null
true
+ }
- case _ => false
- }
- case _ => false
- }
+ case _ => false
+ }
- /**
- * Replace jumps to a sequence of GOTO instructions by a jump to the final destination.
- *
- * Jump l; [any ops]; l: GOTO m; [any ops]; m: GOTO n; [any ops]; n: NotGOTO; [...]
- * => Jump n; [rest unchanged]
- *
- * If there's a loop of GOTOs, the initial jump is replaced by one of the labels in the loop.
- */
- private def collapseJumpChains(instruction: AbstractInsnNode): Boolean = instruction match {
- case JumpNonJsr(jump) =>
- val target = finalJumpTarget(jump)
- if (jump.label == target) false else {
- jump.label = target
+ /**
+ * Eliminates unnecessary jump instructions
+ *
+ * Jump l; [nops]; l: [...]
+ * => POP*; [nops]; l: [...]
+ *
+ * Introduces 0, 1 or 2 POP instructions, depending on the number of values consumed by the Jump.
+ */
+ def removeJumpToSuccessor(insn: AbstractInsnNode): Boolean = insn match {
+ case JumpNonJsr(jump) if nextExecutableInstruction(jump, alsoKeep = Set(jump.label)) contains jump.label =>
+ replaceJumpByPop(jump)
true
- }
- case _ => false
- }
+ case _ => false
+ }
- /**
- * Eliminates unnecessary jump instructions
- *
- * Jump l; [nops]; l: [...]
- * => POP*; [nops]; l: [...]
- *
- * Introduces 0, 1 or 2 POP instructions, depending on the number of values consumed by the Jump.
- */
- private def removeJumpToSuccessor(method: MethodNode, instruction: AbstractInsnNode) = instruction match {
- case JumpNonJsr(jump) if nextExecutableInstruction(jump, alsoKeep = Set(jump.label)) == Some(jump.label) =>
- removeJumpAndAdjustStack(method, jump)
- true
- case _ => false
- }
+ /**
+ * If the "else" part of a conditional branch is a simple GOTO, negates the conditional branch
+ * and eliminates the GOTO.
+ *
+ * CondJump l; [nops, no jump targets]; GOTO m; [nops]; l: [...]
+ * => NegatedCondJump m; [nops, no jump targets]; [nops]; l: [...]
+ *
+ * Note that no jump targets are allowed in the first [nops] section. Otherwise, there could
+ * be some other jump to the GOTO, and eliminating it would change behavior.
+ */
+ def simplifyBranchOverGoto(insn: AbstractInsnNode, inTryBlock: Boolean): Boolean = insn match {
+ case ConditionalJump(jump) =>
+ // don't skip over jump targets, see doc comment
+ nextExecutableInstruction(jump, alsoKeep = jumpTargets) match {
+ case Some(Goto(goto)) =>
+ if (nextExecutableInstruction(goto, alsoKeep = Set(jump.label)) contains jump.label) {
+ val newJump = new JumpInsnNode(negateJumpOpcode(jump.getOpcode), goto.label)
+ method.instructions.set(jump, newJump)
+ removeJumpFromMap(jump)
+ jumpInsns(newJump) = inTryBlock
+ replaceJumpByPop(goto)
+ true
+ } else false
+
+ case _ => false
+ }
+ case _ => false
+ }
- /**
- * If the "else" part of a conditional branch is a simple GOTO, negates the conditional branch
- * and eliminates the GOTO.
- *
- * CondJump l; [nops, no labels]; GOTO m; [nops]; l: [...]
- * => NegatedCondJump m; [nops, no labels]; [nops]; l: [...]
- *
- * Note that no label definitions are allowed in the first [nops] section. Otherwise, there could
- * be some other jump to the GOTO, and eliminating it would change behavior.
- *
- * For technical reasons, we cannot remove the GOTO here (*).Instead this method returns an Option
- * containing the GOTO that needs to be eliminated.
- *
- * (*) The ASM instruction iterator (used in the caller [[simplifyJumps]]) has an undefined
- * behavior if the successor of the current instruction is removed, which may be the case here
- */
- private def simplifyBranchOverGoto(method: MethodNode, instruction: AbstractInsnNode): Option[JumpInsnNode] = instruction match {
- case ConditionalJump(jump) =>
- // don't skip over labels, see doc comment
- nextExecutableInstructionOrLabel(jump) match {
- case Some(Goto(goto)) =>
- if (nextExecutableInstruction(goto, alsoKeep = Set(jump.label)) == Some(jump.label)) {
- val newJump = new JumpInsnNode(negateJumpOpcode(jump.getOpcode), goto.label)
- method.instructions.set(jump, newJump)
- Some(goto)
- } else None
-
- case _ => None
- }
- case _ => None
- }
+ /**
+ * Inlines xRETURN and ATHROW
+ *
+ * GOTO l; [any ops]; l: xRETURN/ATHROW
+ * => xRETURN/ATHROW; [any ops]; l: xRETURN/ATHROW
+ *
+ * inlining is only done if the GOTO instruction is not part of a try block, otherwise the
+ * rewrite might change the behavior. For xRETURN, the reason is that return instructions may throw
+ * an IllegalMonitorStateException, as described here:
+ * http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.return
+ */
+ def simplifyGotoReturn(instruction: AbstractInsnNode, inTryBlock: Boolean): Boolean = !inTryBlock && (instruction match {
+ case Goto(jump) =>
+ nextExecutableInstruction(jump.label) match {
+ case Some(target) =>
+ if (isReturn(target) || target.getOpcode == ATHROW) {
+ method.instructions.set(jump, target.clone(null))
+ removeJumpFromMap(jump)
+ true
+ } else false
+
+ case _ => false
+ }
+ case _ => false
+ })
- /**
- * Inlines xRETURN and ATHROW
- *
- * GOTO l; [any ops]; l: xRETURN/ATHROW
- * => xRETURN/ATHROW; [any ops]; l: xRETURN/ATHROW
- *
- * inlining is only done if the GOTO instruction is not part of a try block, otherwise the
- * rewrite might change the behavior. For xRETURN, the reason is that return instructions may throw
- * an IllegalMonitorStateException, as described here:
- * http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.return
- */
- private def simplifyGotoReturn(method: MethodNode, instruction: AbstractInsnNode, inTryBlock: Boolean): Boolean = !inTryBlock && (instruction match {
- case Goto(jump) =>
- nextExecutableInstruction(jump.label) match {
- case Some(target) =>
- if (isReturn(target) || target.getOpcode == ATHROW) {
- method.instructions.set(jump, target.clone(null))
- true
- } else false
+ def run(): Boolean = {
+ var changed = false
+
+ // `.toList` because we're modifying the map while iterating over it
+ for ((jumpInsn, inTryBlock) <- jumpInsns.toList if jumpInsns.contains(jumpInsn) && isJumpNonJsr(jumpInsn)) {
+ var jumpRemoved = simplifyThenElseSameTarget(jumpInsn)
- case _ => false
+ if (!jumpRemoved) {
+ changed = collapseJumpChains(jumpInsn) || changed
+ jumpRemoved = removeJumpToSuccessor(jumpInsn)
+
+ if (!jumpRemoved) {
+ changed = simplifyBranchOverGoto(jumpInsn, inTryBlock) || changed
+ changed = simplifyGotoReturn(jumpInsn, inTryBlock) || changed
+ }
+ }
+
+ changed ||= jumpRemoved
}
- case _ => false
- })
+
+ if (changed) run()
+ changed
+ }
+
+ run()
+ }
}
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 20e2c4346f..1446d22217 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -319,7 +319,7 @@ trait ScalaSettings extends AbsScalaSettings
def YoptWarningNoInlineMissingBytecode = YoptWarnings.contains(YoptWarningsChoices.noInlineMissingBytecode)
def YoptWarningNoInlineMissingScalaInlineInfoAttr = YoptWarnings.contains(YoptWarningsChoices.noInlineMissingScalaInlineInfoAttr)
- val YoptTrace = StringSetting("-YoptTrace", "package/Class.method", "Trace the optimizer progress for a specific method.", "")
+ val YoptTrace = StringSetting("-Yopt-trace", "package/Class.method", "Trace the optimizer progress for a specific method.", "")
private def removalIn212 = "This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug."
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index f7a1f462b7..7cd05b56c3 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -651,7 +651,7 @@ abstract class UnCurry extends InfoTransform
* This transformation erases the dependent method types by:
* - Widening the formal parameter type to existentially abstract
* over the prior parameters (using `packSymbols`). This transformation
- * is performed in the the `InfoTransform`er [[scala.reflect.internal.transform.UnCurry]].
+ * is performed in the `InfoTransform`er [[scala.reflect.internal.transform.UnCurry]].
* - Inserting casts in the method body to cast to the original,
* precise type.
*
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
index 8b2e09495f..4ae97ce281 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
@@ -542,7 +542,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
*
* (0) A or B must be in the domain to draw any conclusions.
*
- * For example, knowing the the scrutinee is *not* true does not
+ * For example, knowing the scrutinee is *not* true does not
* statically exclude it from being `X`, because that is an opaque
* Boolean.
*
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
index 96a20ea631..e12b8548a8 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
@@ -503,14 +503,26 @@ trait MatchTranslation {
*/
def treeMaker(binder: Symbol, binderKnownNonNull: Boolean, pos: Position): TreeMaker = {
val paramAccessors = binder.constrParamAccessors
+ val numParams = paramAccessors.length
+ def paramAccessorAt(subPatIndex: Int) = paramAccessors(math.min(subPatIndex, numParams - 1))
// binders corresponding to mutable fields should be stored (SI-5158, SI-6070)
// make an exception for classes under the scala package as they should be well-behaved,
// to optimize matching on List
+ val hasRepeated = paramAccessors.lastOption match {
+ case Some(x) => definitions.isRepeated(x)
+ case _ => false
+ }
val mutableBinders = (
if (!binder.info.typeSymbol.hasTransOwner(ScalaPackageClass) &&
- (paramAccessors exists (_.isMutable)))
- subPatBinders.zipWithIndex.collect{ case (binder, idx) if paramAccessors(idx).isMutable => binder }
- else Nil
+ (paramAccessors exists (x => x.isMutable || definitions.isRepeated(x)))) {
+
+ subPatBinders.zipWithIndex.flatMap {
+ case (binder, idx) =>
+ val param = paramAccessorAt(idx)
+ if (param.isMutable || (definitions.isRepeated(param) && !aligner.isStar)) binder :: Nil
+ else Nil
+ }
+ } else Nil
)
// checks binder ne null before chaining to the next extractor
diff --git a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
index 0574869714..9898cfd785 100644
--- a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
@@ -65,7 +65,7 @@ trait AnalyzerPlugins { self: Analyzer =>
* The hooks into `typeSig` allow analyzer plugins to add annotations to (or change the types
* of) definition symbols. This cannot not be achieved by using `pluginsTyped`: this method
* is only called during type checking, so changing the type of a symbol at this point is too
- * late: references to the symbol might already be typed and therefore obtain the the original
+ * late: references to the symbol might already be typed and therefore obtain the original
* type assigned during naming.
*
* @param defTree is the definition for which the type was computed. The different cases are
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
index a702b3cdf5..f90e61ff92 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
@@ -79,7 +79,7 @@ trait PatternTypers {
// do not update the symbol if the tree's symbol's type does not define an unapply member
// (e.g. since it's some method that returns an object with an unapply member)
val fun = inPlaceAdHocOverloadingResolution(fun0)(hasUnapplyMember)
- val caseClass = fun.tpe.typeSymbol.linkedClassOfClass
+ val caseClass = companionSymbolOf(fun.tpe.typeSymbol.sourceModule, context)
val member = unapplyMember(fun.tpe)
def resultType = (fun.tpe memberType member).finalResultType
def isEmptyType = resultOfMatchingMethod(resultType, nme.isEmpty)()
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 3860cc252d..cafea55b4d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -88,17 +88,19 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
if (sym.hasAccessBoundary) "" + sym.privateWithin.name else ""
)
- def overridesTypeInPrefix(tp1: Type, tp2: Type, prefix: Type): Boolean = (tp1.dealiasWiden, tp2.dealiasWiden) match {
+ def overridesTypeInPrefix(tp1: Type, tp2: Type, prefix: Type, isModuleOverride: Boolean): Boolean = (tp1.dealiasWiden, tp2.dealiasWiden) match {
case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) =>
rtp1 <:< rtp2
case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) =>
rtp1 <:< rtp2
case (TypeRef(_, sym, _), _) if sym.isModuleClass =>
- overridesTypeInPrefix(NullaryMethodType(tp1), tp2, prefix)
+ overridesTypeInPrefix(NullaryMethodType(tp1), tp2, prefix, isModuleOverride)
case _ =>
def classBoundAsSeen(tp: Type) = tp.typeSymbol.classBound.asSeenFrom(prefix, tp.typeSymbol.owner)
-
- (tp1 <:< tp2) || ( // object override check
+ (tp1 <:< tp2) || isModuleOverride && (
+ // Object override check. This requires that both the overridden and the overriding member are object
+ // definitions. The overriding module type is allowed to replace the original one with the same name
+ // as long as it conform to the original non-singleton type.
tp1.typeSymbol.isModuleClass && tp2.typeSymbol.isModuleClass && {
val cb1 = classBoundAsSeen(tp1)
val cb2 = classBoundAsSeen(tp2)
@@ -520,7 +522,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
}
def checkOverrideTerm() {
other.cookJavaRawInfo() // #2454
- if (!overridesTypeInPrefix(lowType, highType, rootType)) { // 8
+ if (!overridesTypeInPrefix(lowType, highType, rootType, low.isModuleOrModuleClass && high.isModuleOrModuleClass)) { // 8
overrideTypeError()
explainTypes(lowType, highType)
}
diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala
index d89e9d291d..7f3200b90a 100644
--- a/src/library/scala/Array.scala
+++ b/src/library/scala/Array.scala
@@ -486,6 +486,37 @@ object Array extends FallbackArrayBuilding {
* @see [[http://www.scala-lang.org/files/archive/spec/2.11/ Scala Language Specification]], for in-depth information on the transformations the Scala compiler makes on Arrays (Sections 6.6 and 6.15 respectively.)
* @see [[http://docs.scala-lang.org/sips/completed/scala-2-8-arrays.html "Scala 2.8 Arrays"]] the Scala Improvement Document detailing arrays since Scala 2.8.
* @see [[http://docs.scala-lang.org/overviews/collections/arrays.html "The Scala 2.8 Collections' API"]] section on `Array` by Martin Odersky for more information.
+ * @hideImplicitConversion scala.Predef.booleanArrayOps
+ * @hideImplicitConversion scala.Predef.byteArrayOps
+ * @hideImplicitConversion scala.Predef.charArrayOps
+ * @hideImplicitConversion scala.Predef.doubleArrayOps
+ * @hideImplicitConversion scala.Predef.floatArrayOps
+ * @hideImplicitConversion scala.Predef.intArrayOps
+ * @hideImplicitConversion scala.Predef.longArrayOps
+ * @hideImplicitConversion scala.Predef.refArrayOps
+ * @hideImplicitConversion scala.Predef.shortArrayOps
+ * @hideImplicitConversion scala.Predef.unitArrayOps
+ * @hideImplicitConversion scala.Predef._booleanArrayOps
+ * @hideImplicitConversion scala.Predef._byteArrayOps
+ * @hideImplicitConversion scala.Predef._charArrayOps
+ * @hideImplicitConversion scala.Predef._doubleArrayOps
+ * @hideImplicitConversion scala.Predef._floatArrayOps
+ * @hideImplicitConversion scala.Predef._intArrayOps
+ * @hideImplicitConversion scala.Predef._longArrayOps
+ * @hideImplicitConversion scala.Predef._refArrayOps
+ * @hideImplicitConversion scala.Predef._shortArrayOps
+ * @hideImplicitConversion scala.Predef._unitArrayOps
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapRefArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapIntArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapDoubleArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapLongArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapFloatArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapCharArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapByteArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapShortArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapBooleanArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapUnitArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.genericWrapArray
* @define coll array
* @define Coll `Array`
* @define orderDependent
diff --git a/src/library/scala/Byte.scala b/src/library/scala/Byte.scala
index 413231c0d1..fb662911b3 100644
--- a/src/library/scala/Byte.scala
+++ b/src/library/scala/Byte.scala
@@ -79,8 +79,8 @@ final abstract class Byte private extends AnyVal {
*/
def >>>(x: Long): Int
/**
- * Returns this value bit-shifted left by the specified number of bits,
- * filling in the right bits with the same value as the left-most bit of this.
+ * Returns this value bit-shifted right by the specified number of bits,
+ * filling in the left bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
* -21 >> 3 == -3
@@ -90,8 +90,8 @@ final abstract class Byte private extends AnyVal {
*/
def >>(x: Int): Int
/**
- * Returns this value bit-shifted left by the specified number of bits,
- * filling in the right bits with the same value as the left-most bit of this.
+ * Returns this value bit-shifted right by the specified number of bits,
+ * filling in the left bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
* -21 >> 3 == -3
diff --git a/src/library/scala/Char.scala b/src/library/scala/Char.scala
index ec2d48c181..9f06503569 100644
--- a/src/library/scala/Char.scala
+++ b/src/library/scala/Char.scala
@@ -79,8 +79,8 @@ final abstract class Char private extends AnyVal {
*/
def >>>(x: Long): Int
/**
- * Returns this value bit-shifted left by the specified number of bits,
- * filling in the right bits with the same value as the left-most bit of this.
+ * Returns this value bit-shifted right by the specified number of bits,
+ * filling in the left bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
* -21 >> 3 == -3
@@ -90,8 +90,8 @@ final abstract class Char private extends AnyVal {
*/
def >>(x: Int): Int
/**
- * Returns this value bit-shifted left by the specified number of bits,
- * filling in the right bits with the same value as the left-most bit of this.
+ * Returns this value bit-shifted right by the specified number of bits,
+ * filling in the left bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
* -21 >> 3 == -3
diff --git a/src/library/scala/Int.scala b/src/library/scala/Int.scala
index 72e5ebf81b..3bd3775eba 100644
--- a/src/library/scala/Int.scala
+++ b/src/library/scala/Int.scala
@@ -79,8 +79,8 @@ final abstract class Int private extends AnyVal {
*/
def >>>(x: Long): Int
/**
- * Returns this value bit-shifted left by the specified number of bits,
- * filling in the right bits with the same value as the left-most bit of this.
+ * Returns this value bit-shifted right by the specified number of bits,
+ * filling in the left bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
* -21 >> 3 == -3
@@ -90,8 +90,8 @@ final abstract class Int private extends AnyVal {
*/
def >>(x: Int): Int
/**
- * Returns this value bit-shifted left by the specified number of bits,
- * filling in the right bits with the same value as the left-most bit of this.
+ * Returns this value bit-shifted right by the specified number of bits,
+ * filling in the left bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
* -21 >> 3 == -3
diff --git a/src/library/scala/Long.scala b/src/library/scala/Long.scala
index 1bd0fe88b1..b27a66647f 100644
--- a/src/library/scala/Long.scala
+++ b/src/library/scala/Long.scala
@@ -79,8 +79,8 @@ final abstract class Long private extends AnyVal {
*/
def >>>(x: Long): Long
/**
- * Returns this value bit-shifted left by the specified number of bits,
- * filling in the right bits with the same value as the left-most bit of this.
+ * Returns this value bit-shifted right by the specified number of bits,
+ * filling in the left bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
* -21 >> 3 == -3
@@ -90,8 +90,8 @@ final abstract class Long private extends AnyVal {
*/
def >>(x: Int): Long
/**
- * Returns this value bit-shifted left by the specified number of bits,
- * filling in the right bits with the same value as the left-most bit of this.
+ * Returns this value bit-shifted right by the specified number of bits,
+ * filling in the left bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
* -21 >> 3 == -3
diff --git a/src/library/scala/Short.scala b/src/library/scala/Short.scala
index 36b9ec4df9..2cbbf3cc59 100644
--- a/src/library/scala/Short.scala
+++ b/src/library/scala/Short.scala
@@ -79,8 +79,8 @@ final abstract class Short private extends AnyVal {
*/
def >>>(x: Long): Int
/**
- * Returns this value bit-shifted left by the specified number of bits,
- * filling in the right bits with the same value as the left-most bit of this.
+ * Returns this value bit-shifted right by the specified number of bits,
+ * filling in the left bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
* -21 >> 3 == -3
@@ -90,8 +90,8 @@ final abstract class Short private extends AnyVal {
*/
def >>(x: Int): Int
/**
- * Returns this value bit-shifted left by the specified number of bits,
- * filling in the right bits with the same value as the left-most bit of this.
+ * Returns this value bit-shifted right by the specified number of bits,
+ * filling in the left bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
* -21 >> 3 == -3
diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala
index 875f6e1c02..86e86d4584 100644
--- a/src/library/scala/collection/JavaConverters.scala
+++ b/src/library/scala/collection/JavaConverters.scala
@@ -52,7 +52,10 @@ import convert._
* - `scala.collection.Set` => `java.util.Set`
* - `scala.collection.Map` => `java.util.Map`
*
- * @author Martin Odersky
+ * The following one way conversion is provided via `asScala`:
+ *
+ * - `java.util.Properties` => `scala.collection.mutable.Map`
+ *
* @since 2.8.1
*/
object JavaConverters extends DecorateAsJava with DecorateAsScala
diff --git a/src/library/scala/collection/Searching.scala b/src/library/scala/collection/Searching.scala
index b68124b3f8..25e8b5e253 100644
--- a/src/library/scala/collection/Searching.scala
+++ b/src/library/scala/collection/Searching.scala
@@ -36,12 +36,12 @@ object Searching {
class SearchImpl[A, Repr](val coll: SeqLike[A, Repr]) {
/** Search the sorted sequence for a specific element. If the sequence is an
- * `IndexedSeq`, a binary search is used. Otherwise, a linear search is used.
+ * `IndexedSeqLike`, a binary search is used. Otherwise, a linear search is used.
*
* The sequence should be sorted with the same `Ordering` before calling; otherwise,
* the results are undefined.
*
- * @see [[scala.collection.IndexedSeq]]
+ * @see [[scala.collection.IndexedSeqLike]]
* @see [[scala.math.Ordering]]
* @see [[scala.collection.SeqLike]], method `sorted`
*
@@ -54,18 +54,18 @@ object Searching {
*/
final def search[B >: A](elem: B)(implicit ord: Ordering[B]): SearchResult =
coll match {
- case _: IndexedSeq[A] => binarySearch(elem, 0, coll.length)(ord)
+ case _: IndexedSeqLike[A, Repr] => binarySearch(elem, 0, coll.length)(ord)
case _ => linearSearch(coll.view, elem, 0)(ord)
}
/** Search within an interval in the sorted sequence for a specific element. If the
- * sequence is an IndexedSeq, a binary search is used. Otherwise, a linear search
+ * sequence is an `IndexedSeqLike`, a binary search is used. Otherwise, a linear search
* is used.
*
* The sequence should be sorted with the same `Ordering` before calling; otherwise,
* the results are undefined.
*
- * @see [[scala.collection.IndexedSeq]]
+ * @see [[scala.collection.IndexedSeqLike]]
* @see [[scala.math.Ordering]]
* @see [[scala.collection.SeqLike]], method `sorted`
*
@@ -81,7 +81,7 @@ object Searching {
final def search[B >: A](elem: B, from: Int, to: Int)
(implicit ord: Ordering[B]): SearchResult =
coll match {
- case _: IndexedSeq[A] => binarySearch(elem, from, to)(ord)
+ case _: IndexedSeqLike[A, Repr] => binarySearch(elem, from, to)(ord)
case _ => linearSearch(coll.view(from, to), elem, from)(ord)
}
diff --git a/src/library/scala/collection/convert/DecorateAsJava.scala b/src/library/scala/collection/convert/DecorateAsJava.scala
index 6658b6feea..e6aa5da067 100644
--- a/src/library/scala/collection/convert/DecorateAsJava.scala
+++ b/src/library/scala/collection/convert/DecorateAsJava.scala
@@ -16,7 +16,7 @@ import WrapAsJava._
import scala.language.implicitConversions
-/** A collection of decorators that allow to convert between
+/** A collection of decorators that allow converting between
* Scala and Java collections using `asScala` and `asJava` methods.
*
* The following conversions are supported via `asJava`, `asScala`
@@ -38,8 +38,8 @@ import scala.language.implicitConversions
* val sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala
* assert(sl eq sl2)
* }}}
- * The following conversions also are supported, but the
- * direction Scala to Java is done my a more specifically named method:
+ * The following conversions are also supported, but the
+ * direction from Scala to Java is done by the more specifically named methods:
* `asJavaCollection`, `asJavaEnumeration`, `asJavaDictionary`.
*
* - `scala.collection.Iterable` <=> `java.util.Collection`
@@ -53,10 +53,12 @@ import scala.language.implicitConversions
* - `scala.collection.Set` => `java.util.Set`
* - `scala.collection.Map` => `java.util.Map`
*
- * @author Martin Odersky
+ * The following one way conversion is provided via `asScala`:
+ *
+ * - `java.util.Properties` => `scala.collection.mutable.Map`
+ *
* @since 2.8.1
*/
-
trait DecorateAsJava {
/**
* Adds an `asJava` method that implicitly converts a Scala `Iterator` to a
diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala
index a65e25ed6e..98b91f7c84 100644
--- a/src/library/scala/collection/immutable/ListSet.scala
+++ b/src/library/scala/collection/immutable/ListSet.scala
@@ -12,7 +12,7 @@ package immutable
import generic._
import scala.annotation.tailrec
-import mutable.Builder
+import mutable.{Builder, ReusableBuilder}
/** $factoryInfo
* @define Coll immutable.ListSet
@@ -32,8 +32,10 @@ object ListSet extends ImmutableSetFactory[ListSet] {
* a time to a list backed set puts the "squared" in N^2. There is a
* temporary space cost, but it's improbable a list backed set could
* become large enough for this to matter given its pricy element lookup.
+ *
+ * This builder is reusable.
*/
- class ListSetBuilder[Elem](initial: ListSet[Elem]) extends Builder[Elem, ListSet[Elem]] {
+ class ListSetBuilder[Elem](initial: ListSet[Elem]) extends ReusableBuilder[Elem, ListSet[Elem]] {
def this() = this(empty[Elem])
protected val elems = (new mutable.ListBuffer[Elem] ++= initial).reverse
protected val seen = new mutable.HashSet[Elem] ++= initial
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index cd2d3f843b..539ae9c387 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -13,7 +13,7 @@ package immutable
import scala.annotation.unchecked.uncheckedVariance
import scala.compat.Platform
import scala.collection.generic._
-import scala.collection.mutable.Builder
+import scala.collection.mutable.{Builder, ReusableBuilder}
import scala.collection.parallel.immutable.ParVector
/** Companion object to the Vector class
@@ -156,7 +156,7 @@ override def companion: GenericCompanion[Vector] = Vector
override def take(n: Int): Vector[A] = {
if (n <= 0)
Vector.empty
- else if (startIndex + n < endIndex)
+ else if (startIndex < endIndex - n)
dropBack0(startIndex + n)
else
this
@@ -165,7 +165,7 @@ override def companion: GenericCompanion[Vector] = Vector
override def drop(n: Int): Vector[A] = {
if (n <= 0)
this
- else if (startIndex + n < endIndex)
+ else if (startIndex < endIndex - n)
dropFront0(startIndex + n)
else
Vector.empty
@@ -704,8 +704,8 @@ extends AbstractIterator[A]
}
}
-
-final class VectorBuilder[A]() extends Builder[A,Vector[A]] with VectorPointer[A @uncheckedVariance] {
+/** A class to build instances of `Vector`. This builder is reusable. */
+final class VectorBuilder[A]() extends ReusableBuilder[A,Vector[A]] with VectorPointer[A @uncheckedVariance] {
// possible alternative: start with display0 = null, blockIndex = -32, lo = 32
// to avoid allocating initial array if the result will be empty anyways
diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala
index af7600ad3d..2ed5bbea60 100644
--- a/src/library/scala/collection/mutable/AnyRefMap.scala
+++ b/src/library/scala/collection/mutable/AnyRefMap.scala
@@ -427,7 +427,11 @@ object AnyRefMap {
def apply(): AnyRefMapBuilder[J, U] = new AnyRefMapBuilder[J, U]
}
- final class AnyRefMapBuilder[K <: AnyRef, V] extends Builder[(K, V), AnyRefMap[K, V]] {
+ /** A builder for instances of `AnyRefMap`.
+ *
+ * This builder can be reused to create multiple instances.
+ */
+ final class AnyRefMapBuilder[K <: AnyRef, V] extends ReusableBuilder[(K, V), AnyRefMap[K, V]] {
private[collection] var elems: AnyRefMap[K, V] = new AnyRefMap[K, V]
def +=(entry: (K, V)): this.type = {
elems += entry
diff --git a/src/library/scala/collection/mutable/ArrayBuilder.scala b/src/library/scala/collection/mutable/ArrayBuilder.scala
index ac78ab823b..549ffef565 100644
--- a/src/library/scala/collection/mutable/ArrayBuilder.scala
+++ b/src/library/scala/collection/mutable/ArrayBuilder.scala
@@ -18,7 +18,7 @@ import scala.reflect.ClassTag
*
* @tparam T the type of the elements for the builder.
*/
-abstract class ArrayBuilder[T] extends Builder[T, Array[T]] with Serializable
+abstract class ArrayBuilder[T] extends ReusableBuilder[T, Array[T]] with Serializable
/** A companion object for array builders.
*
@@ -49,6 +49,8 @@ object ArrayBuilder {
/** A class for array builders for arrays of reference types.
*
+ * This builder can be reused.
+ *
* @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ClassTag` context bound.
*/
@deprecatedInheritance("ArrayBuilder.ofRef is an internal implementation not intended for subclassing.", "2.11.0")
@@ -98,12 +100,13 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ elems
+ }
else mkArray(size)
}
@@ -115,7 +118,7 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofRef"
}
- /** A class for array builders for arrays of `byte`s. */
+ /** A class for array builders for arrays of `byte`s. It can be reused. */
@deprecatedInheritance("ArrayBuilder.ofByte is an internal implementation not intended for subclassing.", "2.11.0")
class ofByte extends ArrayBuilder[Byte] {
@@ -163,12 +166,13 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ elems
+ }
else mkArray(size)
}
@@ -180,7 +184,7 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofByte"
}
- /** A class for array builders for arrays of `short`s. */
+ /** A class for array builders for arrays of `short`s. It can be reused. */
@deprecatedInheritance("ArrayBuilder.ofShort is an internal implementation not intended for subclassing.", "2.11.0")
class ofShort extends ArrayBuilder[Short] {
@@ -228,12 +232,13 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ elems
+ }
else mkArray(size)
}
@@ -245,7 +250,7 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofShort"
}
- /** A class for array builders for arrays of `char`s. */
+ /** A class for array builders for arrays of `char`s. It can be reused. */
@deprecatedInheritance("ArrayBuilder.ofChar is an internal implementation not intended for subclassing.", "2.11.0")
class ofChar extends ArrayBuilder[Char] {
@@ -293,12 +298,13 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ elems
+ }
else mkArray(size)
}
@@ -310,7 +316,7 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofChar"
}
- /** A class for array builders for arrays of `int`s. */
+ /** A class for array builders for arrays of `int`s. It can be reused. */
@deprecatedInheritance("ArrayBuilder.ofInt is an internal implementation not intended for subclassing.", "2.11.0")
class ofInt extends ArrayBuilder[Int] {
@@ -358,12 +364,13 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ elems
+ }
else mkArray(size)
}
@@ -375,7 +382,7 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofInt"
}
- /** A class for array builders for arrays of `long`s. */
+ /** A class for array builders for arrays of `long`s. It can be reused. */
@deprecatedInheritance("ArrayBuilder.ofLong is an internal implementation not intended for subclassing.", "2.11.0")
class ofLong extends ArrayBuilder[Long] {
@@ -423,12 +430,13 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ elems
+ }
else mkArray(size)
}
@@ -440,7 +448,7 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofLong"
}
- /** A class for array builders for arrays of `float`s. */
+ /** A class for array builders for arrays of `float`s. It can be reused. */
@deprecatedInheritance("ArrayBuilder.ofFloat is an internal implementation not intended for subclassing.", "2.11.0")
class ofFloat extends ArrayBuilder[Float] {
@@ -488,12 +496,13 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ elems
+ }
else mkArray(size)
}
@@ -505,7 +514,7 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofFloat"
}
- /** A class for array builders for arrays of `double`s. */
+ /** A class for array builders for arrays of `double`s. It can be reused. */
@deprecatedInheritance("ArrayBuilder.ofDouble is an internal implementation not intended for subclassing.", "2.11.0")
class ofDouble extends ArrayBuilder[Double] {
@@ -553,12 +562,13 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ elems
+ }
else mkArray(size)
}
@@ -570,7 +580,7 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofDouble"
}
- /** A class for array builders for arrays of `boolean`s. */
+ /** A class for array builders for arrays of `boolean`s. It can be reused. */
class ofBoolean extends ArrayBuilder[Boolean] {
private var elems: Array[Boolean] = _
@@ -617,12 +627,13 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ elems
+ }
else mkArray(size)
}
@@ -634,65 +645,33 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofBoolean"
}
- /** A class for array builders for arrays of `Unit` type. */
+ /** A class for array builders for arrays of `Unit` type. It can be reused. */
@deprecatedInheritance("ArrayBuilder.ofUnit is an internal implementation not intended for subclassing.", "2.11.0")
class ofUnit extends ArrayBuilder[Unit] {
- private var elems: Array[Unit] = _
- private var capacity: Int = 0
private var size: Int = 0
- private def mkArray(size: Int): Array[Unit] = {
- val newelems = new Array[Unit](size)
- if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
- newelems
- }
-
- private def resize(size: Int) {
- elems = mkArray(size)
- capacity = size
- }
-
- override def sizeHint(size: Int) {
- if (capacity < size) resize(size)
- }
-
- private def ensureSize(size: Int) {
- if (capacity < size || capacity == 0) {
- var newsize = if (capacity == 0) 16 else capacity * 2
- while (newsize < size) newsize *= 2
- resize(newsize)
- }
- }
-
def +=(elem: Unit): this.type = {
- ensureSize(size + 1)
- elems(size) = elem
size += 1
this
}
- override def ++=(xs: TraversableOnce[Unit]): this.type = xs match {
- case xs: WrappedArray.ofUnit =>
- ensureSize(this.size + xs.length)
- Array.copy(xs.array, 0, elems, this.size, xs.length)
- size += xs.length
- this
- case _ =>
- super.++=(xs)
+ override def ++=(xs: TraversableOnce[Unit]): this.type = {
+ size += xs.size
+ this
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
- else mkArray(size)
+ val ans = new Array[Unit](size)
+ var i = 0
+ while (i < size) { ans(i) = (); i += 1 }
+ ans
}
override def equals(other: Any): Boolean = other match {
- case x: ofUnit => (size == x.size) && (elems == x.elems)
+ case x: ofUnit => (size == x.size)
case _ => false
}
diff --git a/src/library/scala/collection/mutable/Builder.scala b/src/library/scala/collection/mutable/Builder.scala
index 75560580cc..8d6a0ec69d 100644
--- a/src/library/scala/collection/mutable/Builder.scala
+++ b/src/library/scala/collection/mutable/Builder.scala
@@ -18,6 +18,14 @@ import generic._
* elements to the builder with `+=` and then converting to the required
* collection type with `result`.
*
+ * One cannot assume that a single `Builder` can build more than one
+ * instance of the desired collection. Particular subclasses may allow
+ * such behavior. Otherwise, `result` should be treated as a terminal
+ * operation: after it is called, no further methods should be called on
+ * the builder. Extend the [[collection.mutable.ReusableBuilder]] trait
+ * instead of `Builder` for builders that may be reused to build multiple
+ * instances.
+ *
* @tparam Elem the type of elements that get added to the builder.
* @tparam To the type of collection that it produced.
*
@@ -36,8 +44,10 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
*/
def clear()
- /** Produces a collection from the added elements.
- * The builder's contents are undefined after this operation.
+ /** Produces a collection from the added elements. This is a terminal operation:
+ * the builder's contents are undefined after this operation, and no further
+ * methods should be called.
+ *
* @return a collection containing the elements added to this builder.
*/
def result(): To
@@ -112,6 +122,8 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
* @tparam NewTo the type of collection returned by `f`.
* @return a new builder which is the same as the current builder except
* that a transformation function is applied to this builder's result.
+ *
+ * @note The original builder should no longer be used after `mapResult` is called.
*/
def mapResult[NewTo](f: To => NewTo): Builder[Elem, NewTo] =
new Builder[Elem, NewTo] with Proxy {
diff --git a/src/library/scala/collection/mutable/GrowingBuilder.scala b/src/library/scala/collection/mutable/GrowingBuilder.scala
index c4b5e546aa..27d554d98e 100644
--- a/src/library/scala/collection/mutable/GrowingBuilder.scala
+++ b/src/library/scala/collection/mutable/GrowingBuilder.scala
@@ -15,6 +15,8 @@ import generic._
/** The canonical builder for collections that are growable, i.e. that support an
* efficient `+=` method which adds an element to the collection.
*
+ * GrowableBuilders can produce only a single instance of the collection they are growing.
+ *
* @author Paul Phillips
* @version 2.8
* @since 2.8
@@ -25,6 +27,6 @@ import generic._
class GrowingBuilder[Elem, To <: Growable[Elem]](empty: To) extends Builder[Elem, To] {
protected var elems: To = empty
def +=(x: Elem): this.type = { elems += x; this }
- def clear() { elems = empty }
+ def clear() { empty.clear }
def result: To = elems
}
diff --git a/src/library/scala/collection/mutable/LazyBuilder.scala b/src/library/scala/collection/mutable/LazyBuilder.scala
index ebee38b77f..f0a5e6971a 100644
--- a/src/library/scala/collection/mutable/LazyBuilder.scala
+++ b/src/library/scala/collection/mutable/LazyBuilder.scala
@@ -13,12 +13,14 @@ package mutable
/** A builder that constructs its result lazily. Iterators or iterables to
* be added to this builder with `++=` are not evaluated until `result` is called.
*
+ * This builder can be reused.
+ *
* @since 2.8
*
* @tparam Elem type of the elements for this builder.
* @tparam To type of the collection this builder builds.
*/
-abstract class LazyBuilder[Elem, +To] extends Builder[Elem, To] {
+abstract class LazyBuilder[Elem, +To] extends ReusableBuilder[Elem, To] {
/** The different segments of elements to be added to the builder, represented as iterators */
protected var parts = new ListBuffer[TraversableOnce[Elem]]
def +=(x: Elem): this.type = { parts += List(x); this }
diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala
index 0a483ceb86..02fcced3ac 100644
--- a/src/library/scala/collection/mutable/ListBuffer.scala
+++ b/src/library/scala/collection/mutable/ListBuffer.scala
@@ -46,7 +46,7 @@ final class ListBuffer[A]
with Buffer[A]
with GenericTraversableTemplate[A, ListBuffer]
with BufferLike[A, ListBuffer[A]]
- with Builder[A, List[A]]
+ with ReusableBuilder[A, List[A]]
with SeqForwarder[A]
with Serializable
{
@@ -297,6 +297,10 @@ final class ListBuffer[A]
// Implementation of abstract method in Builder
+ /** Returns the accumulated `List`.
+ *
+ * This method may be called multiple times to obtain snapshots of the list in different stages of construction.
+ */
def result: List[A] = toList
/** Converts this buffer to a list. Takes constant time. The buffer is
diff --git a/src/library/scala/collection/mutable/LongMap.scala b/src/library/scala/collection/mutable/LongMap.scala
index f39a6ba634..ecbb1952af 100644
--- a/src/library/scala/collection/mutable/LongMap.scala
+++ b/src/library/scala/collection/mutable/LongMap.scala
@@ -519,7 +519,11 @@ object LongMap {
def apply(): LongMapBuilder[U] = new LongMapBuilder[U]
}
- final class LongMapBuilder[V] extends Builder[(Long, V), LongMap[V]] {
+ /** A builder for instances of `LongMap`.
+ *
+ * This builder can be reused to create multiple instances.
+ */
+ final class LongMapBuilder[V] extends ReusableBuilder[(Long, V), LongMap[V]] {
private[collection] var elems: LongMap[V] = new LongMap[V]
def +=(entry: (Long, V)): this.type = {
elems += entry
diff --git a/src/library/scala/collection/mutable/MapBuilder.scala b/src/library/scala/collection/mutable/MapBuilder.scala
index a5a6b12ea9..cfc3079f41 100644
--- a/src/library/scala/collection/mutable/MapBuilder.scala
+++ b/src/library/scala/collection/mutable/MapBuilder.scala
@@ -23,7 +23,7 @@ package mutable
* @since 2.8
*/
class MapBuilder[A, B, Coll <: scala.collection.GenMap[A, B] with scala.collection.GenMapLike[A, B, Coll]](empty: Coll)
-extends Builder[(A, B), Coll] {
+extends ReusableBuilder[(A, B), Coll] {
protected var elems: Coll = empty
def +=(x: (A, B)): this.type = {
elems = (elems + x).asInstanceOf[Coll]
diff --git a/src/library/scala/collection/mutable/ReusableBuilder.scala b/src/library/scala/collection/mutable/ReusableBuilder.scala
new file mode 100644
index 0000000000..caab3071b6
--- /dev/null
+++ b/src/library/scala/collection/mutable/ReusableBuilder.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2016, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+
+package scala
+package collection
+package mutable
+
+import generic._
+
+/** `ReusableBuilder` is a marker trait that indicates that a `Builder`
+ * can be reused to build more than one instance of a collection. In
+ * particular, calling `result` followed by `clear` will produce a
+ * collection and reset the builder to begin building a new collection
+ * of the same type.
+ *
+ * It is up to subclasses to implement this behavior, and to document any
+ * other behavior that varies from standard `ReusableBuilder` usage
+ * (e.g. operations being well-defined after a call to `result`, or allowing
+ * multiple calls to result to obtain different snapshots of a collection under
+ * construction).
+ *
+ * @tparam Elem the type of elements that get added to the builder.
+ * @tparam To the type of collection that it produced.
+ *
+ * @since 2.12
+ */
+trait ReusableBuilder[-Elem, +To] extends Builder[Elem, To] {
+ /** Clears the contents of this builder.
+ * After execution of this method, the builder will contain no elements.
+ *
+ * If executed immediately after a call to `result`, this allows a new
+ * instance of the same type of collection to be built.
+ */
+ override def clear(): Unit // Note: overriding for scaladoc only!
+
+ /** Produces a collection from the added elements.
+ *
+ * After a call to `result`, the behavior of all other methods is undefined
+ * save for `clear`. If `clear` is called, then the builder is reset and
+ * may be used to build another instance.
+ *
+ * @return a collection containing the elements added to this builder.
+ */
+ override def result(): To // Note: overriding for scaladoc only!
+}
diff --git a/src/library/scala/collection/mutable/SetBuilder.scala b/src/library/scala/collection/mutable/SetBuilder.scala
index 01bfdc96ed..5d1e9ffc3a 100644
--- a/src/library/scala/collection/mutable/SetBuilder.scala
+++ b/src/library/scala/collection/mutable/SetBuilder.scala
@@ -17,7 +17,9 @@ package mutable
* @param empty The empty element of the collection.
* @since 2.8
*/
-class SetBuilder[A, Coll <: scala.collection.Set[A] with scala.collection.SetLike[A, Coll]](empty: Coll) extends Builder[A, Coll] {
+class SetBuilder[A, Coll <: scala.collection.Set[A]
+with scala.collection.SetLike[A, Coll]](empty: Coll)
+extends ReusableBuilder[A, Coll] {
protected var elems: Coll = empty
def +=(x: A): this.type = { elems = elems + x; this }
def clear() { elems = empty }
diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala
index c56d40786e..b5b9498374 100644
--- a/src/library/scala/collection/mutable/StringBuilder.scala
+++ b/src/library/scala/collection/mutable/StringBuilder.scala
@@ -33,7 +33,7 @@ final class StringBuilder(private val underlying: JavaStringBuilder)
with java.lang.CharSequence
with IndexedSeq[Char]
with StringLike[StringBuilder]
- with Builder[Char, String]
+ with ReusableBuilder[Char, String]
with Serializable {
override protected[this] def thisCollection: StringBuilder = this
@@ -435,7 +435,11 @@ final class StringBuilder(private val underlying: JavaStringBuilder)
*/
override def mkString = toString
- /** Returns the result of this Builder (a String)
+ /** Returns the result of this Builder (a String).
+ *
+ * If this method is called multiple times, each call will result in a snapshot of the buffer at that point in time.
+ * In particular, a `StringBuilder` can be used to build multiple independent strings by emptying the buffer with `clear`
+ * after each call to `result`.
*
* @return the string assembled by this StringBuilder
*/
diff --git a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
index bfe95a11ab..c4781321d7 100644
--- a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
+++ b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
@@ -17,12 +17,14 @@ import scala.runtime.ScalaRunTime._
/** A builder class for arrays.
*
+ * This builder can be reused.
+ *
* @tparam A type of elements that can be added to this builder.
* @param tag class tag for objects of type `A`.
*
* @since 2.8
*/
-class WrappedArrayBuilder[A](tag: ClassTag[A]) extends Builder[A, WrappedArray[A]] {
+class WrappedArrayBuilder[A](tag: ClassTag[A]) extends ReusableBuilder[A, WrappedArray[A]] {
@deprecated("use tag instead", "2.10.0")
val manifest: ClassTag[A] = tag
@@ -73,12 +75,13 @@ class WrappedArrayBuilder[A](tag: ClassTag[A]) extends Builder[A, WrappedArray[A
this
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) elems
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ elems
+ }
else mkArray(size)
}
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index f49536d351..e67e698a5c 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -36,6 +36,8 @@ import scala.reflect.ClassTag
*
* @author Philipp Haller, Heather Miller, Aleksandar Prokopec, Viktor Klang
*
+ * @see [[http://docs.scala-lang.org/overviews/core/futures.html Futures and Promises]]
+ *
* @define multipleCallbacks
* Multiple callbacks may be registered; there is no guarantee that they will be
* executed in a particular order.
diff --git a/src/library/scala/concurrent/duration/Duration.scala b/src/library/scala/concurrent/duration/Duration.scala
index 8b7d81d1c4..a905ef345c 100644
--- a/src/library/scala/concurrent/duration/Duration.scala
+++ b/src/library/scala/concurrent/duration/Duration.scala
@@ -94,7 +94,7 @@ object Duration {
timeUnitLabels flatMap { case (unit, names) => expandLabels(names) map (_ -> unit) } toMap
/**
- * Extract length and time unit out of a string, where the format must match the description for [[Duration$.apply(String):Duration apply(String)]].
+ * Extract length and time unit out of a string, where the format must match the description for [[Duration$.apply(s:String)* apply(String)]].
* The extractor will not match for malformed strings or non-finite durations.
*/
def unapply(s: String): Option[(Long, TimeUnit)] =
@@ -355,7 +355,7 @@ object Duration {
* - isomorphic to `java.lang.Double` when it comes to infinite or undefined values
*
* The conversion between Duration and Double is done using [[Duration.toUnit]] (with unit NANOSECONDS)
- * and [[Duration$.fromNanos(Double):Duration Duration.fromNanos(Double)]].
+ * and [[Duration$.fromNanos(nanos:Double)* Duration.fromNanos(Double)]]
*
* <h2>Ordering</h2>
*
diff --git a/src/library/scala/math/package.scala b/src/library/scala/math/package.scala
index b6593d6661..54c81ed613 100644
--- a/src/library/scala/math/package.scala
+++ b/src/library/scala/math/package.scala
@@ -58,7 +58,19 @@ package object math {
* logarithms.
*/
def exp(x: Double): Double = java.lang.Math.exp(x)
+
+ /** Returns the natural logarithm of a `double` value.
+ *
+ * @param x the number to take the natural logarithm of
+ * @return the value `logâ‚‘(x)` where `e` is Eulers number
+ */
def log(x: Double): Double = java.lang.Math.log(x)
+
+ /** Returns the square root of a `double` value.
+ *
+ * @param x the number to take the square root of
+ * @return the value √x
+ */
def sqrt(x: Double): Double = java.lang.Math.sqrt(x)
def IEEEremainder(x: Double, y: Double): Double = java.lang.Math.IEEEremainder(x, y)
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
index 4ff49c44d0..e099853463 100644
--- a/src/library/scala/reflect/Manifest.scala
+++ b/src/library/scala/reflect/Manifest.scala
@@ -157,6 +157,9 @@ object ManifestFactory {
override def newArray(len: Int): Array[Unit] = new Array[Unit](len)
override def newWrappedArray(len: Int): WrappedArray[Unit] = new WrappedArray.ofUnit(new Array[Unit](len))
override def newArrayBuilder(): ArrayBuilder[Unit] = new ArrayBuilder.ofUnit()
+ override protected def arrayClass[T](tp: Class[_]): Class[Array[T]] =
+ if (tp eq runtimeClass) classOf[Array[scala.runtime.BoxedUnit]].asInstanceOf[Class[Array[T]]]
+ else super.arrayClass(tp)
private def readResolve(): Any = Manifest.Unit
}
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index ba6c363918..a025407672 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -428,13 +428,15 @@ trait Definitions extends api.StandardDefinitions {
def elementType(container: Symbol, tp: Type): Type = elementExtract(container, tp)
// collections classes
- lazy val ConsClass = requiredClass[scala.collection.immutable.::[_]]
- lazy val IteratorClass = requiredClass[scala.collection.Iterator[_]]
- lazy val IterableClass = requiredClass[scala.collection.Iterable[_]]
- lazy val ListClass = requiredClass[scala.collection.immutable.List[_]]
- lazy val SeqClass = requiredClass[scala.collection.Seq[_]]
- lazy val StringBuilderClass = requiredClass[scala.collection.mutable.StringBuilder]
- lazy val TraversableClass = requiredClass[scala.collection.Traversable[_]]
+ lazy val ConsClass = requiredClass[scala.collection.immutable.::[_]]
+ lazy val IteratorClass = requiredClass[scala.collection.Iterator[_]]
+ lazy val IterableClass = requiredClass[scala.collection.Iterable[_]]
+ lazy val ListClass = requiredClass[scala.collection.immutable.List[_]]
+ lazy val SeqClass = requiredClass[scala.collection.Seq[_]]
+ lazy val JavaStringBuilderClass = requiredClass[java.lang.StringBuilder]
+ lazy val JavaStringBufferClass = requiredClass[java.lang.StringBuffer]
+ lazy val JavaCharSequenceClass = requiredClass[java.lang.CharSequence]
+ lazy val TraversableClass = requiredClass[scala.collection.Traversable[_]]
lazy val ListModule = requiredModule[scala.collection.immutable.List.type]
def List_apply = getMemberMethod(ListModule, nme.apply)
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 65740e87f1..5b613316cc 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -56,7 +56,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
new FreeTypeSymbol(name, origin) initFlags flags
/**
- * This map stores the original owner the the first time the owner of a symbol is re-assigned.
+ * This map stores the original owner the first time the owner of a symbol is re-assigned.
* The original owner of a symbol is needed in some places in the backend. Ideally, owners should
* be versioned like the type history.
*/
@@ -503,7 +503,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
case _ => new StubTermSymbol(this, name.toTermName, missingMessage)
}
- /** Given a field, construct a term symbol that represents the source construct that gave rise the the field */
+ /** Given a field, construct a term symbol that represents the source construct that gave rise the field */
def sugaredSymbolOrSelf = {
val getter = getterIn(owner)
if (getter == NoSymbol) {
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index d6b611a3f4..e5f77c322d 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -266,7 +266,9 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
definitions.IterableClass
definitions.ListClass
definitions.SeqClass
- definitions.StringBuilderClass
+ definitions.JavaStringBuilderClass
+ definitions.JavaStringBufferClass
+ definitions.JavaCharSequenceClass
definitions.TraversableClass
definitions.ListModule
definitions.NilModule
diff --git a/src/scaladoc/scala/tools/nsc/doc/Settings.scala b/src/scaladoc/scala/tools/nsc/doc/Settings.scala
index a63ed1abe8..8a341a92d5 100644
--- a/src/scaladoc/scala/tools/nsc/doc/Settings.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/Settings.scala
@@ -316,30 +316,6 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
"scala.Predef.Ensuring",
"scala.collection.TraversableOnce.alternateImplicit")
- /** There's a reason all these are specialized by hand but documenting each of them is beyond the point */
- val arraySkipConversions = List(
- "scala.Predef.refArrayOps",
- "scala.Predef.intArrayOps",
- "scala.Predef.doubleArrayOps",
- "scala.Predef.longArrayOps",
- "scala.Predef.floatArrayOps",
- "scala.Predef.charArrayOps",
- "scala.Predef.byteArrayOps",
- "scala.Predef.shortArrayOps",
- "scala.Predef.booleanArrayOps",
- "scala.Predef.unitArrayOps",
- "scala.LowPriorityImplicits.wrapRefArray",
- "scala.LowPriorityImplicits.wrapIntArray",
- "scala.LowPriorityImplicits.wrapDoubleArray",
- "scala.LowPriorityImplicits.wrapLongArray",
- "scala.LowPriorityImplicits.wrapFloatArray",
- "scala.LowPriorityImplicits.wrapCharArray",
- "scala.LowPriorityImplicits.wrapByteArray",
- "scala.LowPriorityImplicits.wrapShortArray",
- "scala.LowPriorityImplicits.wrapBooleanArray",
- "scala.LowPriorityImplicits.wrapUnitArray",
- "scala.LowPriorityImplicits.genericWrapArray")
-
// included as names as here we don't have access to a Global with Definitions :(
def valueClassList = List("unit", "boolean", "byte", "short", "char", "int", "long", "float", "double")
def valueClassFilterPrefixes = List("scala.LowPriorityImplicits", "scala.Predef")
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
index fb4ed34571..707d0c469f 100644
--- a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
@@ -26,29 +26,30 @@ trait CommentFactoryBase { this: MemberLookupBase =>
/* Creates comments with necessary arguments */
def createComment (
- body0: Option[Body] = None,
- authors0: List[Body] = List.empty,
- see0: List[Body] = List.empty,
- result0: Option[Body] = None,
- throws0: Map[String,Body] = Map.empty,
- valueParams0: Map[String,Body] = Map.empty,
- typeParams0: Map[String,Body] = Map.empty,
- version0: Option[Body] = None,
- since0: Option[Body] = None,
- todo0: List[Body] = List.empty,
- deprecated0: Option[Body] = None,
- note0: List[Body] = List.empty,
- example0: List[Body] = List.empty,
- constructor0: Option[Body] = None,
- source0: Option[String] = None,
- inheritDiagram0: List[String] = List.empty,
- contentDiagram0: List[String] = List.empty,
- group0: Option[Body] = None,
- groupDesc0: Map[String,Body] = Map.empty,
- groupNames0: Map[String,Body] = Map.empty,
- groupPrio0: Map[String,Body] = Map.empty
- ) : Comment = new Comment{
- val body = if(body0 isDefined) body0.get else Body(Seq.empty)
+ body0: Option[Body] = None,
+ authors0: List[Body] = List.empty,
+ see0: List[Body] = List.empty,
+ result0: Option[Body] = None,
+ throws0: Map[String,Body] = Map.empty,
+ valueParams0: Map[String,Body] = Map.empty,
+ typeParams0: Map[String,Body] = Map.empty,
+ version0: Option[Body] = None,
+ since0: Option[Body] = None,
+ todo0: List[Body] = List.empty,
+ deprecated0: Option[Body] = None,
+ note0: List[Body] = List.empty,
+ example0: List[Body] = List.empty,
+ constructor0: Option[Body] = None,
+ source0: Option[String] = None,
+ inheritDiagram0: List[String] = List.empty,
+ contentDiagram0: List[String] = List.empty,
+ group0: Option[Body] = None,
+ groupDesc0: Map[String,Body] = Map.empty,
+ groupNames0: Map[String,Body] = Map.empty,
+ groupPrio0: Map[String,Body] = Map.empty,
+ hideImplicitConversions0: List[Body] = List.empty
+ ): Comment = new Comment {
+ val body = body0 getOrElse Body(Seq.empty)
val authors = authors0
val see = see0
val result = result0
@@ -83,18 +84,20 @@ trait CommentFactoryBase { this: MemberLookupBase =>
}
val groupNames = groupNames0 flatMap {
case (group, body) =>
- try {
- body match {
- case Body(List(Paragraph(Chain(List(Summary(Text(name))))))) if (!name.trim.contains("\n")) => List(group -> (name.trim))
- case _ => List()
- }
- } catch {
- case _: java.lang.NumberFormatException => List()
+ body match {
+ case Body(List(Paragraph(Chain(List(Summary(Text(name))))))) if (!name.trim.contains("\n")) => List(group -> (name.trim))
+ case _ => List()
}
}
+ override val hideImplicitConversions: List[String] =
+ hideImplicitConversions0 flatMap {
+ case Body(List(Paragraph(Chain(List(Summary(Text(e))))))) if (!e.trim.contains("\n")) => List(e)
+ case _ => List()
+ }
}
+
private val endOfText = '\u0003'
private val endOfLine = '\u000A'
@@ -165,11 +168,11 @@ trait CommentFactoryBase { this: MemberLookupBase =>
private val SymbolTagRegex =
new Regex("""\s*@(param|tparam|throws|groupdesc|groupname|groupprio)\s+(\S*)\s*(.*)""")
- /** The start of a scaladoc code block */
+ /** The start of a Scaladoc code block */
private val CodeBlockStartRegex =
new Regex("""(.*?)((?:\{\{\{)|(?:\u000E<pre(?: [^>]*)?>\u000E))(.*)""")
- /** The end of a scaladoc code block */
+ /** The end of a Scaladoc code block */
private val CodeBlockEndRegex =
new Regex("""(.*?)((?:\}\}\})|(?:\u000E</pre>\u000E))(.*)""")
@@ -183,6 +186,8 @@ trait CommentFactoryBase { this: MemberLookupBase =>
private final case class SimpleTagKey(name: String) extends TagKey
private final case class SymbolTagKey(name: String, symbol: String) extends TagKey
+ private val TrailingWhitespaceRegex = """\s+$""".r
+
/** Parses a raw comment string into a `Comment` object.
* @param comment The expanded comment string (including start and end markers) to be parsed.
* @param src The raw comment source string.
@@ -192,8 +197,8 @@ trait CommentFactoryBase { this: MemberLookupBase =>
* start and end markers, line start markers and unnecessary whitespace. */
def clean(comment: String): List[String] = {
def cleanLine(line: String): String = {
- //replaceAll removes trailing whitespaces
- line.replaceAll("""\s+$""", "") match {
+ // Remove trailing whitespaces
+ TrailingWhitespaceRegex.replaceAllIn(line, "") match {
case CleanCommentLine(ctl) => ctl
case tl => tl
}
@@ -246,7 +251,7 @@ trait CommentFactoryBase { this: MemberLookupBase =>
parse0(docBody append endOfLine append marker, tags, lastTagKey, ls, inCodeBlock = true)
}
- case CodeBlockEndRegex(before, marker, after) :: ls =>
+ case CodeBlockEndRegex(before, marker, after) :: ls => {
if (!before.trim.isEmpty && !after.trim.isEmpty)
parse0(docBody, tags, lastTagKey, before :: marker :: after :: ls, inCodeBlock = true)
if (!before.trim.isEmpty)
@@ -264,23 +269,27 @@ trait CommentFactoryBase { this: MemberLookupBase =>
case None =>
parse0(docBody append endOfLine append marker, tags, lastTagKey, ls, inCodeBlock = false)
}
+ }
- case SymbolTagRegex(name, sym, body) :: ls if (!inCodeBlock) =>
+ case SymbolTagRegex(name, sym, body) :: ls if (!inCodeBlock) => {
val key = SymbolTagKey(name, sym)
val value = body :: tags.getOrElse(key, Nil)
parse0(docBody, tags + (key -> value), Some(key), ls, inCodeBlock)
+ }
- case SimpleTagRegex(name, body) :: ls if (!inCodeBlock) =>
+ case SimpleTagRegex(name, body) :: ls if (!inCodeBlock) => {
val key = SimpleTagKey(name)
val value = body :: tags.getOrElse(key, Nil)
parse0(docBody, tags + (key -> value), Some(key), ls, inCodeBlock)
+ }
- case SingleTagRegex(name) :: ls if (!inCodeBlock) =>
+ case SingleTagRegex(name) :: ls if (!inCodeBlock) => {
val key = SimpleTagKey(name)
val value = "" :: tags.getOrElse(key, Nil)
parse0(docBody, tags + (key -> value), Some(key), ls, inCodeBlock)
+ }
- case line :: ls if (lastTagKey.isDefined) =>
+ case line :: ls if (lastTagKey.isDefined) => {
val newtags = if (!line.isEmpty) {
val key = lastTagKey.get
val value =
@@ -291,13 +300,15 @@ trait CommentFactoryBase { this: MemberLookupBase =>
tags + (key -> value)
} else tags
parse0(docBody, newtags, lastTagKey, ls, inCodeBlock)
+ }
- case line :: ls =>
+ case line :: ls => {
if (docBody.length > 0) docBody append endOfLine
docBody append line
parse0(docBody, tags, lastTagKey, ls, inCodeBlock)
+ }
- case Nil =>
+ case Nil => {
// Take the {inheritance, content} diagram keys aside, as it doesn't need any parsing
val inheritDiagramTag = SimpleTagKey("inheritanceDiagram")
val contentDiagramTag = SimpleTagKey("contentDiagram")
@@ -321,7 +332,7 @@ trait CommentFactoryBase { this: MemberLookupBase =>
def oneTag(key: SimpleTagKey, filterEmpty: Boolean = true): Option[Body] =
((bodyTags remove key): @unchecked) match {
case Some(r :: rs) if !(filterEmpty && r.blocks.isEmpty) =>
- if (!rs.isEmpty) reporter.warning(pos, "Only one '@" + key.name + "' tag is allowed")
+ if (!rs.isEmpty) reporter.warning(pos, s"Only one '@${key.name}' tag is allowed")
Some(r)
case _ => None
}
@@ -334,7 +345,7 @@ trait CommentFactoryBase { this: MemberLookupBase =>
bodyTags.keys.toSeq flatMap {
case stk: SymbolTagKey if (stk.name == key.name) => Some(stk)
case stk: SimpleTagKey if (stk.name == key.name) =>
- reporter.warning(pos, "Tag '@" + stk.name + "' must be followed by a symbol name")
+ reporter.warning(pos, s"Tag '@${stk.name}' must be followed by a symbol name")
None
case _ => None
}
@@ -342,7 +353,7 @@ trait CommentFactoryBase { this: MemberLookupBase =>
for (key <- keys) yield {
val bs = (bodyTags remove key).get
if (bs.length > 1)
- reporter.warning(pos, "Only one '@" + key.name + "' tag for symbol " + key.symbol + " is allowed")
+ reporter.warning(pos, s"Only one '@${key.name}' tag for symbol ${key.symbol} is allowed")
(key.symbol, bs.head)
}
Map.empty[String, Body] ++ (if (filterEmpty) pairs.filterNot(_._2.blocks.isEmpty) else pairs)
@@ -385,14 +396,15 @@ trait CommentFactoryBase { this: MemberLookupBase =>
group0 = oneTag(SimpleTagKey("group")),
groupDesc0 = allSymsOneTag(SimpleTagKey("groupdesc")),
groupNames0 = allSymsOneTag(SimpleTagKey("groupname")),
- groupPrio0 = allSymsOneTag(SimpleTagKey("groupprio"))
+ groupPrio0 = allSymsOneTag(SimpleTagKey("groupprio")),
+ hideImplicitConversions0 = allTags(SimpleTagKey("hideImplicitConversion"))
)
for ((key, _) <- bodyTags)
- reporter.warning(pos, "Tag '@" + key.name + "' is not recognised")
+ reporter.warning(pos, s"Tag '@${key.name}' is not recognised")
com
-
+ }
}
parse0(new StringBuilder(comment.size), Map.empty, None, clean(comment), inCodeBlock = false)
@@ -424,7 +436,7 @@ trait CommentFactoryBase { this: MemberLookupBase =>
/* BLOCKS */
- /** {{{ block ::= code | title | hrule | para }}} */
+ /** {{{ block ::= code | title | hrule | listBlock | para }}} */
def block(): Block = {
if (checkSkipInitWhitespace("{{{"))
code()
@@ -459,7 +471,7 @@ trait CommentFactoryBase { this: MemberLookupBase =>
* nLine ::= nSpc listStyle para '\n'
* }}}
* Where n and m stand for the number of spaces. When `m > n`, a new list is nested. */
- def listBlock: Block = {
+ def listBlock(): Block = {
/** Consumes one list item block and returns it, or None if the block is
* not a list or a different list. */
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/comment/Comment.scala b/src/scaladoc/scala/tools/nsc/doc/base/comment/Comment.scala
index e5eb68d65a..183297f2c3 100644
--- a/src/scaladoc/scala/tools/nsc/doc/base/comment/Comment.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/comment/Comment.scala
@@ -123,6 +123,9 @@ abstract class Comment {
/** Member group priorities */
def groupPrio: Map[String,Int]
+ /** A list of implicit conversions to hide */
+ def hideImplicitConversions: List[String]
+
override def toString =
body.toString + "\n" +
(authors map ("@author " + _.toString)).mkString("\n") +
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala
index 9086ee29c6..6076b1708c 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala
@@ -46,9 +46,14 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
"source-code-pro-v6-latin-regular.eot",
"source-code-pro-v6-latin-regular.ttf",
"source-code-pro-v6-latin-regular.woff",
+ "MaterialIcons-Regular.eot",
+ "MaterialIcons-Regular.ttf",
+ "MaterialIcons-Regular.woff",
"index.js",
"jquery.js",
+ "jquery.mousewheel.min.js",
+ "jquery.panzoom.min.js",
"scheduler.js",
"diagrams.js",
"template.js",
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala
index 05724a879a..d33b31d8ba 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala
@@ -40,6 +40,8 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
<link href={ relativeLinkTo{List("template.css", "lib")} } media="screen" type="text/css" rel="stylesheet"/>
<link href={ relativeLinkTo{List("diagrams.css", "lib")} } media="screen" type="text/css" rel="stylesheet" id="diagrams-css" />
<script type="text/javascript" src={ relativeLinkTo{List("jquery.js", "lib")} } id="jquery-js"></script>
+ <script type="text/javascript" src={ relativeLinkTo{List("jquery.panzoom.min.js", "lib")} }></script>
+ <script type="text/javascript" src={ relativeLinkTo{List("jquery.mousewheel.min.js", "lib")} }></script>
<script type="text/javascript" src={ relativeLinkTo{List("template.js", "lib")} }></script>
<script type="text/javascript" src={ relativeLinkTo{List("tools.tooltip.js", "lib")} }></script>
{ if (universe.settings.docDiagrams.value) {
@@ -140,7 +142,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty)
NodeSeq.Empty
else
- <li class="inherit out"><span>By inheritance</span></li>
+ <li class="inherit out"><span>By Inheritance</span></li>
}
</ol>
</div>
@@ -176,7 +178,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
<span class="filtertype"></span>
<ol>
<li class="hideall out"><span>Hide All</span></li>
- <li class="showall in"><span>Show all</span></li>
+ <li class="showall in"><span>Show All</span></li>
</ol>
</div>
}
@@ -682,9 +684,12 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
if (diagramSvg != NodeSeq.Empty) {
<div class="toggleContainer block diagram-container" id={ id + "-container"}>
<span class="toggle diagram-link">{ description }</span>
- <div class="diagram" id={ id }>{
- diagramSvg
- }</div>
+ <div class="diagram" id={ id }>{ diagramSvg }</div>
+ <div id="diagram-controls" class="hiddenContent">
+ <button id="diagram-zoom-out" class="diagram-btn"><i class="material-icons">&#xE15B;</i></button>
+ <button id="diagram-zoom-in" class="diagram-btn"><i class="material-icons">&#xE145;</i></button>
+ <button title="Toggle full-screen" id="diagram-fs" class="diagram-btn to-full"><i class="material-icons">&#xE5D0;</i></button>
+ </div>
</div>
} else NodeSeq.Empty
} else NodeSeq.Empty
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.eot b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.eot
new file mode 100644
index 0000000000..bf67d48bdb
--- /dev/null
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.eot
Binary files differ
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.ttf b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.ttf
new file mode 100644
index 0000000000..683dcd05ac
--- /dev/null
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.ttf
Binary files differ
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.woff b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.woff
new file mode 100644
index 0000000000..ddd6be3e3d
--- /dev/null
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/MaterialIcons-Regular.woff
Binary files differ
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.css b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.css
index 22736a04dd..8c20810784 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.css
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.css
@@ -1,3 +1,34 @@
+@font-face {
+ font-family: 'Material Icons';
+ font-style: normal;
+ font-weight: 400;
+ src: url(MaterialIcons-Regular.eot);
+ src: local('Material Icons'),
+ local('MaterialIcons-Regular'),
+ url(MaterialIcons-Regular.woff) format('woff'),
+ url(MaterialIcons-Regular.ttf) format('truetype');
+}
+
+.material-icons {
+ font-family: 'Material Icons';
+ font-weight: normal;
+ font-style: normal;
+ font-size: 24px;
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ line-height: 1;
+ text-transform: none;
+ letter-spacing: normal;
+ word-wrap: normal;
+ white-space: nowrap;
+ direction: ltr;
+ -webkit-font-smoothing: antialiased;
+ text-rendering: optimizeLegibility;
+ -moz-osx-font-smoothing: grayscale;
+ font-feature-settings: 'liga';
+}
+
.diagram-container {
display: none;
}
@@ -38,6 +69,61 @@
text-decoration: none;
}
+#inheritance-diagram-container > span.toggle {
+ z-index: 2;
+}
+
+#inheritance-diagram-container.full-screen {
+ position: fixed !important;
+ margin: 0;
+ border-radius: 0;
+ top: 0em;
+ bottom: 3em;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 10000;
+}
+
+#inheritance-diagram-container.full-screen > span.toggle {
+ display: none;
+}
+
+#inheritance-diagram-container.full-screen > div.diagram {
+ position: absolute;
+ top: 0; right: 0; bottom: 0; left: 0;
+ margin: auto;
+}
+
+#diagram-controls {
+ z-index: 2;
+ position: absolute;
+ bottom: 1em;
+ right: 1em;
+}
+
+#diagram-controls > button.diagram-btn {
+ border-radius: 1.25em;
+ height: 2.5em;
+ width: 2.5em;
+ background-color: #c2c2c2;
+ color: #fff;
+ border: 0;
+ float: left;
+ margin: 0 0.1em;
+ cursor: pointer;
+ line-height: 0.9;
+ outline: none;
+}
+
+#diagram-controls > button.diagram-btn:hover {
+ background-color: #e2e2e2;
+}
+
+#diagram-controls > button.diagram-btn > i.material-icons {
+ font-size: 1.5em;
+}
+
svg a {
cursor:pointer;
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.js
index 801680b687..5d139c1080 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.js
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.js
@@ -15,10 +15,6 @@ $(document).ready(function()
if(Modernizr && !Modernizr.inlinesvg)
return;
- // only execute this in the main window
- if(diagrams.isPopup)
- return;
-
if($("#content-diagram").length)
$("#inheritance-diagram").css("padding-bottom", "20px");
@@ -62,41 +58,16 @@ $(document).ready(function()
});
diagrams.initHighlighting();
-});
-
-/**
- * Initializes the diagrams in the popup.
- */
-diagrams.initPopup = function(id)
-{
- // copy diagram from main window
- if(!jQuery.browser.msie)
- $("body").append(opener.$("#" + id).data("svg"));
- // positioning
- $("svg").css("position", "absolute");
- $(window).resize(function()
- {
- var svg_w = $("svg").css("width").replace("px", "");
- var svg_h = $("svg").css("height").replace("px", "");
- var x = $(window).width() / 2 - svg_w / 2;
- if(x < 0) x = 0;
- var y = $(window).height() / 2 - svg_h / 2;
- if(y < 0) y = 0;
- $("svg").css("left", x + "px");
- $("svg").css("top", y + "px");
- });
- $(window).resize();
+ $("button#diagram-fs").click(function() {
+ $("#inheritance-diagram-container").toggleClass("full-screen");
+ $("#inheritance-diagram-container > div.diagram").css({
+ height: $("svg").height() + "pt"
+ });
- diagrams.initHighlighting();
- $("svg a").click(function(e) {
- opener.diagrams.redirectFromPopup(this.href.baseVal);
- window.close();
- });
- $(document).keyup(function(e) {
- if (e.keyCode == 27) window.close();
- });
-}
+ $panzoom.panzoom("reset", { animate: false, contain: false });
+ });
+});
/**
* Initializes highlighting for nodes and edges.
@@ -182,39 +153,29 @@ diagrams.initHighlighting = function()
/**
* Resizes the diagrams according to the available width.
*/
-diagrams.resize = function()
-{
- // available width
- var availableWidth = $("body").width() - 100;
-
- $(".diagram-container").each(function() {
- // unregister click event on whole div
- $(".diagram", this).unbind("click");
- var diagramWidth = $(".diagram", this).data("width");
- var diagramHeight = $(".diagram", this).data("height");
-
- if(diagramWidth > availableWidth)
- {
- // resize diagram
- var height = diagramHeight / diagramWidth * availableWidth;
- $(".diagram svg", this).width(availableWidth);
- $(".diagram svg", this).height(height);
-
- // register click event on whole div
- $(".diagram", this).click(function() {
- diagrams.popup($(this));
- });
- $(".diagram", this).addClass("magnifying");
- }
- else
- {
- // restore full size of diagram
- $(".diagram svg", this).width(diagramWidth);
- $(".diagram svg", this).height(diagramHeight);
- // don't show custom cursor any more
- $(".diagram", this).removeClass("magnifying");
- }
- });
+diagrams.resize = function() {
+ // available width
+ var availableWidth = $("body").width() - 100;
+
+ $(".diagram-container").each(function() {
+ // unregister click event on whole div
+ $(".diagram", this).unbind("click");
+ var diagramWidth = $(".diagram", this).data("width");
+ var diagramHeight = $(".diagram", this).data("height");
+
+ if(diagramWidth > availableWidth) {
+ // resize diagram
+ var height = diagramHeight / diagramWidth * availableWidth;
+ $(".diagram svg", this).width(availableWidth);
+ $(".diagram svg", this).height(height);
+ } else {
+ // restore full size of diagram
+ $(".diagram svg", this).width(diagramWidth);
+ $(".diagram svg", this).height(diagramHeight);
+ // don't show custom cursor any more
+ $(".diagram", this).removeClass("magnifying");
+ }
+ });
};
/**
@@ -222,82 +183,38 @@ diagrams.resize = function()
*/
diagrams.toggle = function(container, dontAnimate)
{
- // change class of link
- $(".diagram-link", container).toggleClass("open");
- // get element to show / hide
- var div = $(".diagram", container);
- if (div.is(':visible'))
- {
- $(".diagram-help", container).hide();
- div.unbind("click");
- div.removeClass("magnifying");
- div.slideUp(100);
- }
- else
- {
- diagrams.resize();
- if(dontAnimate)
- div.show();
- else
- div.slideDown(100);
- $(".diagram-help", container).show();
- }
-};
-
-/**
- * Opens a popup containing a copy of a diagram.
- */
-diagrams.windows = {};
-diagrams.popup = function(diagram)
-{
- var id = diagram.attr("id");
- if(!diagrams.windows[id] || diagrams.windows[id].closed) {
- var title = $(".symbol .name", $("#signature")).text();
- // cloning from parent window to popup somehow doesn't work in IE
- // therefore include the SVG as a string into the HTML
- var svgIE = jQuery.browser.msie ? $("<div />").append(diagram.data("svg")).html() : "";
- var html = '' +
- '<?xml version="1.0" encoding="UTF-8"?>\n' +
- '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n' +
- '<html>\n' +
- ' <head>\n' +
- ' <title>' + title + '</title>\n' +
- ' <link href="' + $("#diagrams-css").attr("href") + '" media="screen" type="text/css" rel="stylesheet" />\n' +
- ' <script type="text/javascript" src="' + $("#jquery-js").attr("src") + '"></script>\n' +
- ' <script type="text/javascript" src="' + $("#diagrams-js").attr("src") + '"></script>\n' +
- ' <script type="text/javascript">\n' +
- ' diagrams.isPopup = true;\n' +
- ' </script>\n' +
- ' </head>\n' +
- ' <body onload="diagrams.initPopup(\'' + id + '\');">\n' +
- ' <a href="#" onclick="window.close();" id="close-link">Close this window</a>\n' +
- ' ' + svgIE + '\n' +
- ' </body>\n' +
- '</html>';
-
- var padding = 30;
- var screenHeight = screen.availHeight;
- var screenWidth = screen.availWidth;
- var w = Math.min(screenWidth, diagram.data("width") + 2 * padding);
- var h = Math.min(screenHeight, diagram.data("height") + 2 * padding);
- var left = (screenWidth - w) / 2;
- var top = (screenHeight - h) / 2;
- var parameters = "height=" + h + ", width=" + w + ", left=" + left + ", top=" + top + ", scrollbars=yes, location=no, resizable=yes";
- var win = window.open("about:blank", "_blank", parameters);
- win.document.open();
- win.document.write(html);
- win.document.close();
- diagrams.windows[id] = win;
- }
- win.focus();
-};
-
-/**
- * This method is called from within the popup when a node is clicked.
- */
-diagrams.redirectFromPopup = function(url)
-{
- window.location = url;
+ // change class of link
+ $(".diagram-link", container).toggleClass("open");
+ // get element to show / hide
+ var div = $(".diagram", container);
+ if (div.is(':visible')) {
+ $(".diagram-help", container).hide();
+ div.unbind("click");
+ div.slideUp(100);
+
+ $("#diagram-controls", container).hide();
+ $("#inheritance-diagram-container").unbind('mousewheel.focal');
+ } else {
+ diagrams.resize();
+ if(dontAnimate)
+ div.show();
+ else
+ div.slideDown(100);
+ $(".diagram-help", container).show();
+
+ $("#diagram-controls", container).show();
+
+ $("#inheritance-diagram-container").on('mousewheel.focal', function(e) {
+ e.preventDefault();
+ var delta = e.delta || e.originalEvent.wheelDelta;
+ var zoomOut = delta ? delta < 0 : e.originalEvent.deltaY > 0;
+ $panzoom.panzoom('zoom', zoomOut, {
+ increment: 0.1,
+ animate: true,
+ focal: e
+ });
+ });
+ }
};
/**
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.mousewheel.min.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.mousewheel.min.js
new file mode 100644
index 0000000000..03bfd60c5e
--- /dev/null
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.mousewheel.min.js
@@ -0,0 +1,8 @@
+/*!
+ * jQuery Mousewheel 3.1.13
+ *
+ * Copyright 2015 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})}); \ No newline at end of file
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.panzoom.min.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.panzoom.min.js
new file mode 100644
index 0000000000..7c3be68b7e
--- /dev/null
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.panzoom.min.js
@@ -0,0 +1,9 @@
+/**
+ * @license jquery.panzoom.js v2.0.5
+ * Updated: Thu Jul 03 2014
+ * Add pan and zoom functionality to any element
+ * Copyright (c) 2014 timmy willison
+ * Released under the MIT license
+ * https://github.com/timmywil/jquery.panzoom/blob/master/MIT-License.txt
+ */
+!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(c){return b(a,c)}):"object"==typeof exports?b(a,require("jquery")):b(a,a.jQuery)}("undefined"!=typeof window?window:this,function(a,b){"use strict";function c(a,b){for(var c=a.length;--c;)if(+a[c]!==+b[c])return!1;return!0}function d(a){var c={range:!0,animate:!0};return"boolean"==typeof a?c.animate=a:b.extend(c,a),c}function e(a,c,d,e,f,g,h,i,j){this.elements="array"===b.type(a)?[+a[0],+a[2],+a[4],+a[1],+a[3],+a[5],0,0,1]:[a,c,d,e,f,g,h||0,i||0,j||1]}function f(a,b,c){this.elements=[a,b,c]}function g(a,c){if(!(this instanceof g))return new g(a,c);1!==a.nodeType&&b.error("Panzoom called on non-Element node"),b.contains(l,a)||b.error("Panzoom element must be attached to the document");var d=b.data(a,m);if(d)return d;this.options=c=b.extend({},g.defaults,c),this.elem=a;var e=this.$elem=b(a);this.$set=c.$set&&c.$set.length?c.$set:e,this.$doc=b(a.ownerDocument||l),this.$parent=e.parent(),this.isSVG=r.test(a.namespaceURI)&&"svg"!==a.nodeName.toLowerCase(),this.panning=!1,this._buildTransform(),this._transform=!this.isSVG&&b.cssProps.transform.replace(q,"-$1").toLowerCase(),this._buildTransition(),this.resetDimensions();var f=b(),h=this;b.each(["$zoomIn","$zoomOut","$zoomRange","$reset"],function(a,b){h[b]=c[b]||f}),this.enable(),b.data(a,m,this)}var h="over out down up move enter leave cancel".split(" "),i=b.extend({},b.event.mouseHooks),j={};if(a.PointerEvent)b.each(h,function(a,c){b.event.fixHooks[j[c]="pointer"+c]=i});else{var k=i.props;i.props=k.concat(["touches","changedTouches","targetTouches","altKey","ctrlKey","metaKey","shiftKey"]),i.filter=function(a,b){var c,d=k.length;if(!b.pageX&&b.touches&&(c=b.touches[0]))for(;d--;)a[k[d]]=c[k[d]];return a},b.each(h,function(a,c){if(2>a)j[c]="mouse"+c;else{var d="touch"+("down"===c?"start":"up"===c?"end":c);b.event.fixHooks[d]=i,j[c]=d+" mouse"+c}})}b.pointertouch=j;var l=a.document,m="__pz__",n=Array.prototype.slice,o=!!a.PointerEvent,p=function(){var a=l.createElement("input");return a.setAttribute("oninput","return"),"function"==typeof a.oninput}(),q=/([A-Z])/g,r=/^http:[\w\.\/]+svg$/,s=/^inline/,t="(\\-?[\\d\\.e]+)",u="\\,?\\s*",v=new RegExp("^matrix\\("+t+u+t+u+t+u+t+u+t+u+t+"\\)$");return e.prototype={x:function(a){var b=a instanceof f,c=this.elements,d=a.elements;return b&&3===d.length?new f(c[0]*d[0]+c[1]*d[1]+c[2]*d[2],c[3]*d[0]+c[4]*d[1]+c[5]*d[2],c[6]*d[0]+c[7]*d[1]+c[8]*d[2]):d.length===c.length?new e(c[0]*d[0]+c[1]*d[3]+c[2]*d[6],c[0]*d[1]+c[1]*d[4]+c[2]*d[7],c[0]*d[2]+c[1]*d[5]+c[2]*d[8],c[3]*d[0]+c[4]*d[3]+c[5]*d[6],c[3]*d[1]+c[4]*d[4]+c[5]*d[7],c[3]*d[2]+c[4]*d[5]+c[5]*d[8],c[6]*d[0]+c[7]*d[3]+c[8]*d[6],c[6]*d[1]+c[7]*d[4]+c[8]*d[7],c[6]*d[2]+c[7]*d[5]+c[8]*d[8]):!1},inverse:function(){var a=1/this.determinant(),b=this.elements;return new e(a*(b[8]*b[4]-b[7]*b[5]),a*-(b[8]*b[1]-b[7]*b[2]),a*(b[5]*b[1]-b[4]*b[2]),a*-(b[8]*b[3]-b[6]*b[5]),a*(b[8]*b[0]-b[6]*b[2]),a*-(b[5]*b[0]-b[3]*b[2]),a*(b[7]*b[3]-b[6]*b[4]),a*-(b[7]*b[0]-b[6]*b[1]),a*(b[4]*b[0]-b[3]*b[1]))},determinant:function(){var a=this.elements;return a[0]*(a[8]*a[4]-a[7]*a[5])-a[3]*(a[8]*a[1]-a[7]*a[2])+a[6]*(a[5]*a[1]-a[4]*a[2])}},f.prototype.e=e.prototype.e=function(a){return this.elements[a]},g.rmatrix=v,g.events=b.pointertouch,g.defaults={eventNamespace:".panzoom",transition:!0,cursor:"move",disablePan:!1,disableZoom:!1,increment:.3,minScale:.4,maxScale:5,rangeStep:.05,duration:200,easing:"ease-in-out",contain:!1},g.prototype={constructor:g,instance:function(){return this},enable:function(){this._initStyle(),this._bind(),this.disabled=!1},disable:function(){this.disabled=!0,this._resetStyle(),this._unbind()},isDisabled:function(){return this.disabled},destroy:function(){this.disable(),b.removeData(this.elem,m)},resetDimensions:function(){var a=this.$parent;this.container={width:a.innerWidth(),height:a.innerHeight()};var c,d=a.offset(),e=this.elem,f=this.$elem;this.isSVG?(c=e.getBoundingClientRect(),c={left:c.left-d.left,top:c.top-d.top,width:c.width,height:c.height,margin:{left:0,top:0}}):c={left:b.css(e,"left",!0)||0,top:b.css(e,"top",!0)||0,width:f.innerWidth(),height:f.innerHeight(),margin:{top:b.css(e,"marginTop",!0)||0,left:b.css(e,"marginLeft",!0)||0}},c.widthBorder=b.css(e,"borderLeftWidth",!0)+b.css(e,"borderRightWidth",!0)||0,c.heightBorder=b.css(e,"borderTopWidth",!0)+b.css(e,"borderBottomWidth",!0)||0,this.dimensions=c},reset:function(a){a=d(a);var b=this.setMatrix(this._origTransform,a);a.silent||this._trigger("reset",b)},resetZoom:function(a){a=d(a);var b=this.getMatrix(this._origTransform);a.dValue=b[3],this.zoom(b[0],a)},resetPan:function(a){var b=this.getMatrix(this._origTransform);this.pan(b[4],b[5],d(a))},setTransform:function(a){for(var c=this.isSVG?"attr":"style",d=this.$set,e=d.length;e--;)b[c](d[e],"transform",a)},getTransform:function(a){var c=this.$set,d=c[0];return a?this.setTransform(a):a=b[this.isSVG?"attr":"style"](d,"transform"),"none"===a||v.test(a)||this.setTransform(a=b.css(d,"transform")),a||"none"},getMatrix:function(a){var b=v.exec(a||this.getTransform());return b&&b.shift(),b||[1,0,0,1,0,0]},setMatrix:function(a,c){if(!this.disabled){c||(c={}),"string"==typeof a&&(a=this.getMatrix(a));var d,e,f,g,h,i,j,k,l,m,n=+a[0],o=this.$parent,p="undefined"!=typeof c.contain?c.contain:this.options.contain;return p&&(d=this._checkDims(),e=this.container,l=d.width+d.widthBorder,m=d.height+d.heightBorder,f=(l*Math.abs(n)-e.width)/2,g=(m*Math.abs(n)-e.height)/2,j=d.left+d.margin.left,k=d.top+d.margin.top,"invert"===p?(h=l>e.width?l-e.width:0,i=m>e.height?m-e.height:0,f+=(e.width-l)/2,g+=(e.height-m)/2,a[4]=Math.max(Math.min(a[4],f-j),-f-j-h),a[5]=Math.max(Math.min(a[5],g-k),-g-k-i+d.heightBorder)):(g+=d.heightBorder/2,h=e.width>l?e.width-l:0,i=e.height>m?e.height-m:0,"center"===o.css("textAlign")&&s.test(b.css(this.elem,"display"))?h=0:f=g=0,a[4]=Math.min(Math.max(a[4],f-j),-f-j+h),a[5]=Math.min(Math.max(a[5],g-k),-g-k+i))),"skip"!==c.animate&&this.transition(!c.animate),c.range&&this.$zoomRange.val(n),this.setTransform("matrix("+a.join(",")+")"),c.silent||this._trigger("change",a),a}},isPanning:function(){return this.panning},transition:function(a){if(this._transition)for(var c=a||!this.options.transition?"none":this._transition,d=this.$set,e=d.length;e--;)b.style(d[e],"transition")!==c&&b.style(d[e],"transition",c)},pan:function(a,b,c){if(!this.options.disablePan){c||(c={});var d=c.matrix;d||(d=this.getMatrix()),c.relative&&(a+=+d[4],b+=+d[5]),d[4]=a,d[5]=b,this.setMatrix(d,c),c.silent||this._trigger("pan",d[4],d[5])}},zoom:function(a,c){"object"==typeof a?(c=a,a=null):c||(c={});var d=b.extend({},this.options,c);if(!d.disableZoom){var g=!1,h=d.matrix||this.getMatrix();"number"!=typeof a&&(a=+h[0]+d.increment*(a?-1:1),g=!0),a>d.maxScale?a=d.maxScale:a<d.minScale&&(a=d.minScale);var i=d.focal;if(i&&!d.disablePan){var j=this._checkDims(),k=i.clientX,l=i.clientY;this.isSVG||(k-=(j.width+j.widthBorder)/2,l-=(j.height+j.heightBorder)/2);var m=new f(k,l,1),n=new e(h),o=this.parentOffset||this.$parent.offset(),p=new e(1,0,o.left-this.$doc.scrollLeft(),0,1,o.top-this.$doc.scrollTop()),q=n.inverse().x(p.inverse().x(m)),r=a/h[0];n=n.x(new e([r,0,0,r,0,0])),m=p.x(n.x(q)),h[4]=+h[4]+(k-m.e(0)),h[5]=+h[5]+(l-m.e(1))}h[0]=a,h[3]="number"==typeof d.dValue?d.dValue:a,this.setMatrix(h,{animate:"boolean"==typeof d.animate?d.animate:g,range:!d.noSetRange}),d.silent||this._trigger("zoom",h[0],d)}},option:function(a,c){var d;if(!a)return b.extend({},this.options);if("string"==typeof a){if(1===arguments.length)return void 0!==this.options[a]?this.options[a]:null;d={},d[a]=c}else d=a;this._setOptions(d)},_setOptions:function(a){b.each(a,b.proxy(function(a,c){switch(a){case"disablePan":this._resetStyle();case"$zoomIn":case"$zoomOut":case"$zoomRange":case"$reset":case"disableZoom":case"onStart":case"onChange":case"onZoom":case"onPan":case"onEnd":case"onReset":case"eventNamespace":this._unbind()}switch(this.options[a]=c,a){case"disablePan":this._initStyle();case"$zoomIn":case"$zoomOut":case"$zoomRange":case"$reset":this[a]=c;case"disableZoom":case"onStart":case"onChange":case"onZoom":case"onPan":case"onEnd":case"onReset":case"eventNamespace":this._bind();break;case"cursor":b.style(this.elem,"cursor",c);break;case"minScale":this.$zoomRange.attr("min",c);break;case"maxScale":this.$zoomRange.attr("max",c);break;case"rangeStep":this.$zoomRange.attr("step",c);break;case"startTransform":this._buildTransform();break;case"duration":case"easing":this._buildTransition();case"transition":this.transition();break;case"$set":c instanceof b&&c.length&&(this.$set=c,this._initStyle(),this._buildTransform())}},this))},_initStyle:function(){var a={"backface-visibility":"hidden","transform-origin":this.isSVG?"0 0":"50% 50%"};this.options.disablePan||(a.cursor=this.options.cursor),this.$set.css(a);var c=this.$parent;c.length&&!b.nodeName(c[0],"body")&&(a={overflow:"hidden"},"static"===c.css("position")&&(a.position="relative"),c.css(a))},_resetStyle:function(){this.$elem.css({cursor:"",transition:""}),this.$parent.css({overflow:"",position:""})},_bind:function(){var a=this,c=this.options,d=c.eventNamespace,e=o?"pointerdown"+d:"touchstart"+d+" mousedown"+d,f=o?"pointerup"+d:"touchend"+d+" click"+d,h={},i=this.$reset,j=this.$zoomRange;if(b.each(["Start","Change","Zoom","Pan","End","Reset"],function(){var a=c["on"+this];b.isFunction(a)&&(h["panzoom"+this.toLowerCase()+d]=a)}),c.disablePan&&c.disableZoom||(h[e]=function(b){var d;("touchstart"===b.type?!(d=b.touches)||(1!==d.length||c.disablePan)&&2!==d.length:c.disablePan||1!==b.which)||(b.preventDefault(),b.stopPropagation(),a._startMove(b,d))}),this.$elem.on(h),i.length&&i.on(f,function(b){b.preventDefault(),a.reset()}),j.length&&j.attr({step:c.rangeStep===g.defaults.rangeStep&&j.attr("step")||c.rangeStep,min:c.minScale,max:c.maxScale}).prop({value:this.getMatrix()[0]}),!c.disableZoom){var k=this.$zoomIn,l=this.$zoomOut;k.length&&l.length&&(k.on(f,function(b){b.preventDefault(),a.zoom()}),l.on(f,function(b){b.preventDefault(),a.zoom(!0)})),j.length&&(h={},h[(o?"pointerdown":"mousedown")+d]=function(){a.transition(!0)},h[(p?"input":"change")+d]=function(){a.zoom(+this.value,{noSetRange:!0})},j.on(h))}},_unbind:function(){this.$elem.add(this.$zoomIn).add(this.$zoomOut).add(this.$reset).off(this.options.eventNamespace)},_buildTransform:function(){return this._origTransform=this.getTransform(this.options.startTransform)},_buildTransition:function(){if(this._transform){var a=this.options;this._transition=this._transform+" "+a.duration+"ms "+a.easing}},_checkDims:function(){var a=this.dimensions;return a.width&&a.height||this.resetDimensions(),this.dimensions},_getDistance:function(a){var b=a[0],c=a[1];return Math.sqrt(Math.pow(Math.abs(c.clientX-b.clientX),2)+Math.pow(Math.abs(c.clientY-b.clientY),2))},_getMiddle:function(a){var b=a[0],c=a[1];return{clientX:(c.clientX-b.clientX)/2+b.clientX,clientY:(c.clientY-b.clientY)/2+b.clientY}},_trigger:function(a){"string"==typeof a&&(a="panzoom"+a),this.$elem.triggerHandler(a,[this].concat(n.call(arguments,1)))},_startMove:function(a,d){var e,f,g,h,i,j,k,m,n=this,p=this.options,q=p.eventNamespace,r=this.getMatrix(),s=r.slice(0),t=+s[4],u=+s[5],v={matrix:r,animate:"skip"};o?(f="pointermove",g="pointerup"):"touchstart"===a.type?(f="touchmove",g="touchend"):(f="mousemove",g="mouseup"),f+=q,g+=q,this.transition(!0),this.panning=!0,this._trigger("start",a,d),d&&2===d.length?(h=this._getDistance(d),i=+r[0],j=this._getMiddle(d),e=function(a){a.preventDefault();var b=n._getMiddle(d=a.touches),c=n._getDistance(d)-h;n.zoom(c*(p.increment/100)+i,{focal:b,matrix:r,animate:!1}),n.pan(+r[4]+b.clientX-j.clientX,+r[5]+b.clientY-j.clientY,v),j=b}):(k=a.pageX,m=a.pageY,e=function(a){a.preventDefault(),n.pan(t+a.pageX-k,u+a.pageY-m,v)}),b(l).off(q).on(f,e).on(g,function(a){a.preventDefault(),b(this).off(q),n.panning=!1,a.type="panzoomend",n._trigger(a,r,!c(r,s))})}},b.Panzoom=g,b.fn.panzoom=function(a){var c,d,e,f;return"string"==typeof a?(f=[],d=n.call(arguments,1),this.each(function(){c=b.data(this,m),c?"_"!==a.charAt(0)&&"function"==typeof(e=c[a])&&void 0!==(e=e.apply(c,d))&&f.push(e):f.push(void 0)}),f.length?1===f.length?f[0]:f:this):this.each(function(){new g(this,a)})},g}); \ No newline at end of file
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css
index 662ae48944..43e59076ca 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css
@@ -769,6 +769,10 @@ div#footer {
box-shadow: none;
}
+#comment > dl > div > ol {
+ list-style-type: none;
+}
+
div.fullcomment div.block ol li p,
div.fullcomment div.block ol li {
display:inline
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js
index 9d9d7bdfff..3baf0d9db7 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js
@@ -1,7 +1,20 @@
// © 2009–2010 EPFL/LAMP
// code by Gilles Dubochet with contributions by Pedro Furlanetto, Marcin Kubala and Felix Mulder
+var $panzoom = undefined;
$(document).ready(function() {
+ // Add zoom functionality to type inheritance diagram
+ $panzoom = $("#inheritance-diagram").panzoom({
+ increment: 0.1,
+ minScale: 1,
+ maxScale: 3,
+ transition: true,
+ duration: 200,
+ contain: 'invert',
+ easing: "ease-in-out",
+ $zoomIn: $('#diagram-zoom-in'),
+ $zoomOut: $('#diagram-zoom-out'),
+ });
$("#template > div > div > ol > li > span > a").click(function(e) {
$("#template > div > div > ol > li").removeClass("selected");
@@ -275,12 +288,7 @@ $(document).ready(function() {
function toggleShowContentFct(e){
e.toggleClass("open");
var content = $(".hiddenContent", e.parent().get(0));
- if (content.is(':visible')) {
- content.slideUp(100);
- }
- else {
- content.slideDown(100);
- }
+ (content.is(':visible') ? content.slideUp : content.slideDown)(100);
};
$(".toggle:not(.diagram-link)").click(function() {
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
index 0264f2f99f..830d902b68 100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
@@ -98,10 +98,15 @@ trait ModelFactoryImplicitSupport {
// also keep empty conversions, so they appear in diagrams
// conversions = conversions.filter(!_.members.isEmpty)
- // Filter out specialized conversions from array
- if (sym == ArrayClass)
- conversions = conversions.filterNot((conv: ImplicitConversionImpl) =>
- hardcoded.arraySkipConversions.contains(conv.conversionQualifiedName))
+ val hiddenConversions: Seq[String] = thisFactory
+ .comment(sym, inTpl.linkTarget, inTpl)
+ .map(_.hideImplicitConversions)
+ .getOrElse(Nil)
+
+ conversions = conversions filterNot { conv: ImplicitConversionImpl =>
+ hiddenConversions.contains(conv.conversionShortName) ||
+ hiddenConversions.contains(conv.conversionQualifiedName)
+ }
// Filter out non-sensical conversions from value types
if (isPrimitiveValueType(sym.tpe_*))
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala
index 093899231e..86900f26c9 100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala
@@ -248,7 +248,7 @@ trait DiagramFactory extends DiagramDirectiveParser {
case _ => Nil
})
- // Only show the the non-isolated nodes
+ // Only show the non-isolated nodes
// TODO: Decide if we really want to hide package members, I'm not sure that's a good idea (!!!)
// TODO: Does .distinct cause any stability issues?
val sourceNodes = edges.map(_._1)
diff --git a/test/files/jvm/future-spec/FutureTests.scala b/test/files/jvm/future-spec/FutureTests.scala
index abcf1b4cbc..d0de2f5542 100644
--- a/test/files/jvm/future-spec/FutureTests.scala
+++ b/test/files/jvm/future-spec/FutureTests.scala
@@ -238,7 +238,7 @@ class FutureTests extends MinimalScalaTest {
"support pattern matching within a for-comprehension" in {
case class Req[T](req: T)
case class Res[T](res: T)
- def async[T](req: Req[T]) = req match {
+ def async[T](req: Req[T]) = (req: @unchecked) match {
case Req(s: String) => Future { Res(s.length) }
case Req(i: Int) => Future { Res((i * 2).toString) }
}
diff --git a/test/files/jvm/innerClassEnclMethodJavaReflection.scala b/test/files/jvm/innerClassEnclMethodJavaReflection.scala
index a4d64d0b67..a60b5cac8e 100644
--- a/test/files/jvm/innerClassEnclMethodJavaReflection.scala
+++ b/test/files/jvm/innerClassEnclMethodJavaReflection.scala
@@ -25,12 +25,13 @@ object Test extends App {
def testClasses(jarOrDirectory: String): Unit = {
val classPath = AbstractFile.getDirectory(new java.io.File(jarOrDirectory))
+ val basePath = classPath.path + "/"
- def flatten(f: AbstractFile): Iterator[AbstractFile] =
- if (f.isClassContainer) f.iterator.flatMap(flatten)
- else Iterator(f)
+ def flatten(f: AbstractFile, s: String): Iterator[(AbstractFile, String)] =
+ if (f.isClassContainer) f.iterator.map(ch => (ch, (if(s.isEmpty) "" else s + "/") + ch.name)).flatMap((flatten _).tupled)
+ else Iterator((f, s))
- val classFullNames = flatten(classPath).filter(_.hasExtension("class")).map(_.path.replace("/", ".").replaceAll(".class$", ""))
+ val classFullNames = flatten(classPath, "").filter(_._1.hasExtension("class")).map(_._2.replace("/", ".").replaceAll(".class$", ""))
// it seems that Class objects can only be GC'd together with their class loader
// (http://stackoverflow.com/questions/2433261/when-and-how-are-classes-garbage-collected-in-java)
diff --git a/test/files/jvm/t6941.check b/test/files/jvm/t6941.check
deleted file mode 100644
index 43f53aba12..0000000000
--- a/test/files/jvm/t6941.check
+++ /dev/null
@@ -1 +0,0 @@
-bytecode identical
diff --git a/test/files/jvm/t6941.flags b/test/files/jvm/t6941.flags
deleted file mode 100644
index 49d036a887..0000000000
--- a/test/files/jvm/t6941.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimize
diff --git a/test/files/jvm/t6941/Analyzed_1.flags b/test/files/jvm/t6941/Analyzed_1.flags
deleted file mode 100644
index ad51758c39..0000000000
--- a/test/files/jvm/t6941/Analyzed_1.flags
+++ /dev/null
@@ -1 +0,0 @@
--nowarn
diff --git a/test/files/jvm/t6941/Analyzed_1.scala b/test/files/jvm/t6941/Analyzed_1.scala
deleted file mode 100644
index b6951f71ee..0000000000
--- a/test/files/jvm/t6941/Analyzed_1.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-// this class's bytecode, compiled under -optimize is analyzed by the test
-// method a's bytecode should be identical to method b's bytecode
-class SameBytecode {
- def a(xs: List[Int]) = xs match {
- case x :: _ => x
- }
-
- def b(xs: List[Int]) = xs match {
- case xs: ::[Int] => xs.head
- }
-} \ No newline at end of file
diff --git a/test/files/jvm/t6941/test.scala b/test/files/jvm/t6941/test.scala
deleted file mode 100644
index fceb54487f..0000000000
--- a/test/files/jvm/t6941/test.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-import scala.tools.partest.{BytecodeTest, ASMConverters}
-
-import scala.tools.nsc.util.JavaClassPath
-import java.io.InputStream
-import scala.tools.asm
-import asm.ClassReader
-import asm.tree.{ClassNode, InsnList}
-import scala.collection.JavaConverters._
-
-object Test extends BytecodeTest {
- def show: Unit = {
- val classNode = loadClassNode("SameBytecode")
- similarBytecode(getMethod(classNode, "a"), getMethod(classNode, "b"), ASMConverters.equivalentBytecode(_, _))
- }
-}
diff --git a/test/files/neg/choices.check b/test/files/neg/choices.check
index b114394e96..df4f23461f 100644
--- a/test/files/neg/choices.check
+++ b/test/files/neg/choices.check
@@ -1,2 +1,6 @@
+error: Usage: -Yresolve-term-conflict:<strategy>
+ where <strategy> choices are package, object, error (default: error)
+error: bad option: '-Yresolve-term-conflict'
error: bad options: -Yresolve-term-conflict
-one error found
+error: flags file may only contain compiler options, found: -Yresolve-term-conflict
+four errors found
diff --git a/test/files/neg/override-object-no.check b/test/files/neg/override-object-no.check
index 9cfda80fc3..972a719b3b 100644
--- a/test/files/neg/override-object-no.check
+++ b/test/files/neg/override-object-no.check
@@ -20,4 +20,12 @@ an overriding object must conform to the overridden object's class bound;
required: case2.Bar[Traversable[String]]
override object A extends Bar[List[String]] // err
^
-four errors found
+override-object-no.scala:52: error: overriding method x in trait A of type => SI9574.Foo.type;
+ method x has incompatible type
+ trait B extends A { def x: Bar.type } // should not compile (SI-9574)
+ ^
+override-object-no.scala:53: error: overriding method x in trait A of type => SI9574.Foo.type;
+ object x has incompatible type
+ trait C extends A { override object x }
+ ^
+6 errors found
diff --git a/test/files/neg/override-object-no.scala b/test/files/neg/override-object-no.scala
index 745cdb2332..517408886d 100644
--- a/test/files/neg/override-object-no.scala
+++ b/test/files/neg/override-object-no.scala
@@ -43,3 +43,14 @@ package case2 {
override object A extends Bar[List[String]] // err
}
}
+
+// Both overridden and overriding members must be objects, not vals with a module type
+object SI9574 {
+ object Foo
+ object Bar
+ trait A { def x: Foo.type }
+ trait B extends A { def x: Bar.type } // should not compile (SI-9574)
+ trait C extends A { override object x }
+ trait D { object x; def y = x }
+ trait E extends D { override val x: super.x.type = y } // OK but doesn't need object subtyping exception
+}
diff --git a/test/files/neg/partestInvalidFlag.check b/test/files/neg/partestInvalidFlag.check
new file mode 100644
index 0000000000..812191dc22
--- /dev/null
+++ b/test/files/neg/partestInvalidFlag.check
@@ -0,0 +1,4 @@
+error: bad option: '-badCompilerFlag'
+error: bad options: -badCompilerFlag notAFlag -Yopt:badChoice
+error: flags file may only contain compiler options, found: -badCompilerFlag notAFlag -Yopt:badChoice
+three errors found
diff --git a/test/files/neg/partestInvalidFlag.flags b/test/files/neg/partestInvalidFlag.flags
new file mode 100644
index 0000000000..68884532b9
--- /dev/null
+++ b/test/files/neg/partestInvalidFlag.flags
@@ -0,0 +1 @@
+-badCompilerFlag notAFlag -Yopt:badChoice
diff --git a/test/files/neg/partestInvalidFlag.scala b/test/files/neg/partestInvalidFlag.scala
new file mode 100644
index 0000000000..826a1a5bc2
--- /dev/null
+++ b/test/files/neg/partestInvalidFlag.scala
@@ -0,0 +1 @@
+class C
diff --git a/test/files/neg/t9572.check b/test/files/neg/t9572.check
new file mode 100644
index 0000000000..b95bd015cf
--- /dev/null
+++ b/test/files/neg/t9572.check
@@ -0,0 +1,7 @@
+t9572.scala:3: error: too many elements for tuple: 23, allowed: 22
+ val term23 = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)
+ ^
+t9572.scala:5: error: too many elements for tuple: 23, allowed: 22
+ val type23: (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int) = null
+ ^
+two errors found
diff --git a/test/files/neg/t9572.scala b/test/files/neg/t9572.scala
new file mode 100644
index 0000000000..32b2db320e
--- /dev/null
+++ b/test/files/neg/t9572.scala
@@ -0,0 +1,6 @@
+class T9572 {
+ val term22 = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)
+ val term23 = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)
+ val type22: (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int) = null
+ val type23: (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int) = null
+}
diff --git a/test/files/pos/t2171.flags b/test/files/pos/t2171.flags
deleted file mode 100644
index eb4d19bcb9..0000000000
--- a/test/files/pos/t2171.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimise \ No newline at end of file
diff --git a/test/files/pos/t2171.scala b/test/files/pos/t2171.scala
deleted file mode 100644
index 6c754c76a6..0000000000
--- a/test/files/pos/t2171.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-final object test {
- def logIgnoredException(msg: => String) =
- try 0 catch { case ex => println(msg) }
-
- def main (args: Array[String]): Unit =
- while (true) logIgnoredException ("...")
-}
diff --git a/test/files/pos/t3252.flags b/test/files/pos/t3252.flags
deleted file mode 100644
index eb4d19bcb9..0000000000
--- a/test/files/pos/t3252.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimise \ No newline at end of file
diff --git a/test/files/pos/t3252.scala b/test/files/pos/t3252.scala
deleted file mode 100644
index 3ecc1e7cef..0000000000
--- a/test/files/pos/t3252.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-class A {
- def f(x : Boolean) : Thread = {
- g {
- x match {
- case false =>
- B.h { }
- }
- }
- }
-
- private def g[T](block : => T) = sys.error("")
-}
-object B {
- def h(block : => Unit) : Nothing = sys.error("")
-}
diff --git a/test/files/pos/t3420.flags b/test/files/pos/t3420.flags
index 4fbafb7e80..397969bb1d 100644
--- a/test/files/pos/t3420.flags
+++ b/test/files/pos/t3420.flags
@@ -1 +1 @@
--Yopt-warnings Yopt:l:project -Xfatal-warnings \ No newline at end of file
+-Yopt-warnings -Yopt:l:classpath -Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t3430.flags b/test/files/pos/t3430.flags
deleted file mode 100644
index eb4d19bcb9..0000000000
--- a/test/files/pos/t3430.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimise \ No newline at end of file
diff --git a/test/files/pos/t3430.scala b/test/files/pos/t3430.scala
deleted file mode 100644
index 3129c6276a..0000000000
--- a/test/files/pos/t3430.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-// package com.example
-
-object A {
- def f1(f: String => Boolean) = f("a")
-
- def f2(): Boolean =
- f1 { s1 =>
- f1 { s2 =>
- while (true) { }
- true
- }
- }
-} \ No newline at end of file
diff --git a/test/files/pos/t4579.flags b/test/files/pos/t4579.flags
deleted file mode 100644
index 1182725e86..0000000000
--- a/test/files/pos/t4579.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimize \ No newline at end of file
diff --git a/test/files/pos/t4840.flags b/test/files/pos/t4840.flags
index eb4d19bcb9..422d6be431 100644
--- a/test/files/pos/t4840.flags
+++ b/test/files/pos/t4840.flags
@@ -1 +1 @@
--optimise \ No newline at end of file
+-Yopt:l:classpath \ No newline at end of file
diff --git a/test/files/pos/t6157.flags b/test/files/pos/t6157.flags
deleted file mode 100644
index 0ebca3e7af..0000000000
--- a/test/files/pos/t6157.flags
+++ /dev/null
@@ -1 +0,0 @@
- -optimize
diff --git a/test/files/pos/t6157.scala b/test/files/pos/t6157.scala
deleted file mode 100644
index 7463989b14..0000000000
--- a/test/files/pos/t6157.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-// SI-6157 - Compiler crash on inlined function and -optimize option
-
-object Test {
- def main(args: Array[String]) {
- Console.println(
- ErrorHandler.defaultIfIOException("String")("String")
- )
- }
-}
-
-import java.io.IOException
-
-object ErrorHandler {
-
- @inline
- def defaultIfIOException[T](default: => T)(closure: => T): T = {
- try {
- closure
- } catch {
- case e: IOException =>
- default
- }
- }
-}
-
diff --git a/test/files/pos/t6547.flags b/test/files/pos/t6547.flags
deleted file mode 100644
index c9b68d70dc..0000000000
--- a/test/files/pos/t6547.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimise
diff --git a/test/files/pos/t6547.scala b/test/files/pos/t6547.scala
deleted file mode 100644
index 53bd798219..0000000000
--- a/test/files/pos/t6547.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-trait ConfigurableDefault[@specialized V] {
- def fillArray(arr: Array[V], v: V) = (arr: Any) match {
- case x: Array[Int] => null
- case x: Array[Long] => v.asInstanceOf[Long]
- }
-}
diff --git a/test/files/pos/t8062.flags b/test/files/pos/t8062.flags
deleted file mode 100644
index 49d036a887..0000000000
--- a/test/files/pos/t8062.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimize
diff --git a/test/files/pos/t8062/A_1.scala b/test/files/pos/t8062/A_1.scala
deleted file mode 100644
index ca0411dae8..0000000000
--- a/test/files/pos/t8062/A_1.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package warmup
-
-object Warmup {
- def filter[A](p: Any => Boolean): Any = filter[Any](p)
-}
diff --git a/test/files/pos/t8062/B_2.scala b/test/files/pos/t8062/B_2.scala
deleted file mode 100644
index f0a6761488..0000000000
--- a/test/files/pos/t8062/B_2.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-object Test {
- warmup.Warmup.filter[Any](x => false)
-}
diff --git a/test/files/pos/t8306.flags b/test/files/pos/t8306.flags
deleted file mode 100644
index 49d036a887..0000000000
--- a/test/files/pos/t8306.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimize
diff --git a/test/files/pos/t8306.scala b/test/files/pos/t8306.scala
deleted file mode 100644
index e04b054eb9..0000000000
--- a/test/files/pos/t8306.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-class Si8306 {
- def foo: Int = 123
- lazy val extension: Int =
- foo match {
- case idx if idx != -1 => 15
- case _ => 17
- }
-}
diff --git a/test/files/pos/t8359-closelim-crash.flags b/test/files/pos/t8359-closelim-crash.flags
deleted file mode 100644
index 49d036a887..0000000000
--- a/test/files/pos/t8359-closelim-crash.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimize
diff --git a/test/files/pos/t8359-closelim-crash.scala b/test/files/pos/t8359-closelim-crash.scala
deleted file mode 100644
index 1413694d10..0000000000
--- a/test/files/pos/t8359-closelim-crash.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package test
-
-// This is a minimization of code that crashed the compiler during bootstrapping
-// in the first iteration of https://github.com/scala/scala/pull/4373, the PR
-// that adjusted the order of free and declared params in LambdaLift.
-
-// Was:
-// java.lang.AssertionError: assertion failed:
-// Record Record(<$anon: Function1>,Map(value a$1 -> Deref(LocalVar(value b)))) does not contain a field value b$1
-// at scala.tools.nsc.Global.assert(Global.scala:262)
-// at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:113)
-// at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:122)
-// at scala.tools.nsc.backend.opt.ClosureElimination$ClosureElim$$anonfun$analyzeMethod$1$$anonfun$apply$2.replaceFieldAccess$1(ClosureElimination.scala:124)
-class Typer {
- def bar(a: Boolean, b: Boolean): Unit = {
- @inline
- def baz(): Unit = {
- ((_: Any) => (Typer.this, a, b)).apply("")
- }
- ((_: Any) => baz()).apply("")
- }
-}
-
diff --git a/test/files/pos/t9123.flags b/test/files/pos/t9123.flags
deleted file mode 100644
index c16e2f71dc..0000000000
--- a/test/files/pos/t9123.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimize -Ydelambdafy:method
diff --git a/test/files/pos/t9123.scala b/test/files/pos/t9123.scala
deleted file mode 100644
index 22d55b4351..0000000000
--- a/test/files/pos/t9123.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-trait Setting {
- type T
- def value: T
-}
-
-object Test {
- def test(x: Some[Setting]) = x match {
- case Some(dep) => Some(dep.value) map (_ => true)
- }
-}
diff --git a/test/files/pos/trait-force-info.flags b/test/files/pos/trait-force-info.flags
deleted file mode 100644
index eb4d19bcb9..0000000000
--- a/test/files/pos/trait-force-info.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimise \ No newline at end of file
diff --git a/test/files/pos/trait-force-info.scala b/test/files/pos/trait-force-info.scala
deleted file mode 100644
index c2b33869c3..0000000000
--- a/test/files/pos/trait-force-info.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-/** This does NOT crash unless it's in the interactive package.
- */
-
-package scala.tools.nsc
-package interactive
-
-trait MyContextTrees {
- val self: Global
- val NoContext = self.analyzer.NoContext
-}
-//
-// error: java.lang.AssertionError: assertion failed: trait Contexts.NoContext$ linkedModule: <none>List()
-// at scala.Predef$.assert(Predef.scala:160)
-// at scala.tools.nsc.symtab.classfile.ClassfileParser$innerClasses$.innerSymbol$1(ClassfileParser.scala:1211)
-// at scala.tools.nsc.symtab.classfile.ClassfileParser$innerClasses$.classSymbol(ClassfileParser.scala:1223)
-// at scala.tools.nsc.symtab.classfile.ClassfileParser.classNameToSymbol(ClassfileParser.scala:489)
-// at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$1(ClassfileParser.scala:757)
-// at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$1(ClassfileParser.scala:789)
diff --git a/test/files/presentation/doc/doc.scala b/test/files/presentation/doc/doc.scala
index f2233f1828..ce431910ee 100644
--- a/test/files/presentation/doc/doc.scala
+++ b/test/files/presentation/doc/doc.scala
@@ -118,6 +118,12 @@ object Test extends InteractiveTest {
}
}
+ // The remainder of this test has been found to fail intermittently on Windows
+ // only. The problem is difficult to isolate and reproduce; see
+ // https://github.com/scala/scala-dev/issues/72 for details.
+ // So if we're on Windows, let's just bail out here.
+ if (scala.util.Properties.isWin) return
+
// Check inter-classes documentation one-time retrieved ok.
val baseSource = findSource("Base.scala")
val derivedSource = findSource("Derived.scala")
diff --git a/test/files/run/elidable-opt.scala b/test/files/run/elidable-opt.scala
index ebada46de8..a2f29d2caf 100644
--- a/test/files/run/elidable-opt.scala
+++ b/test/files/run/elidable-opt.scala
@@ -1,6 +1,3 @@
-/*
- * filter: inliner warnings; re-run with
- */
import annotation._
import elidable._
diff --git a/test/files/run/lisp.check b/test/files/run/lisp.check
new file mode 100644
index 0000000000..64053f26d0
--- /dev/null
+++ b/test/files/run/lisp.check
@@ -0,0 +1,26 @@
+(lambda (x) (+ (* x x) 1))
+(lambda (x) (+ (* x x) 1))
+
+( '(1 2 3)) = (1 2 3)
+(car '(1 2 3)) = 1
+(cdr '(1 2 3)) = (2 3)
+(null? '(2 3)) = 0
+(null? '()) = 1
+
+faculty(10) = 3628800
+faculty(10) = 3628800
+foobar = ("a" "bc" "def" "z")
+
+List('lambda, List('x), List('+, List('*, 'x, 'x), 1))
+(lambda (x) (+ (* x x) 1))
+
+( '(1 2 3)) = (1 2 3)
+(car '(1 2 3)) = 1
+(cdr '(1 2 3)) = (2 3)
+(null? '(2 3)) = 0
+(null? '()) = 1
+
+faculty(10) = 3628800
+faculty(10) = 3628800
+foobar = ("a" "bc" "def" "z")
+
diff --git a/test/files/pos/t4579.scala b/test/files/run/lisp.scala
index cd1553f02a..162c7d2599 100644
--- a/test/files/pos/t4579.scala
+++ b/test/files/run/lisp.scala
@@ -1,5 +1,5 @@
//############################################################################
-// Lisp interpreter (revived as an optimizer test.)
+// Lisp interpreter
//############################################################################
//############################################################################
diff --git a/test/files/run/t7008-scala-defined.flags b/test/files/run/t7008-scala-defined.flags
deleted file mode 100644
index e69de29bb2..0000000000
--- a/test/files/run/t7008-scala-defined.flags
+++ /dev/null
diff --git a/test/files/run/t7008-scala-defined/Test_3.scala b/test/files/run/t7008-scala-defined/Test_3.scala
index 26178142ab..ee7b9d9cde 100644
--- a/test/files/run/t7008-scala-defined/Test_3.scala
+++ b/test/files/run/t7008-scala-defined/Test_3.scala
@@ -1,6 +1,3 @@
-/*
- * filter: inliner warning; re-run with
- */
import scala.reflect.runtime.universe._
object Test extends App {
diff --git a/test/files/run/t7582.check b/test/files/run/t7582.check
index 0cfbf08886..58d0f19f5d 100644
--- a/test/files/run/t7582.check
+++ b/test/files/run/t7582.check
@@ -1 +1,6 @@
+InlineHolder.scala:9: warning: p1/InlineHolder$::inlinable()I is annotated @inline but could not be inlined:
+The callee p1/InlineHolder$::inlinable()I contains the instruction INVOKESTATIC p1/PackageProtectedJava.protectedMethod ()I
+that would cause an IllegalAccessError when inlined into class O$.
+ def x = p1.InlineHolder.inlinable
+ ^
2
diff --git a/test/files/run/t7582.flags b/test/files/run/t7582.flags
index 422d6be431..1f45833eff 100644
--- a/test/files/run/t7582.flags
+++ b/test/files/run/t7582.flags
@@ -1 +1 @@
--Yopt:l:classpath \ No newline at end of file
+-Yopt:l:classpath -Yopt-warnings \ No newline at end of file
diff --git a/test/files/run/t7582/InlineHolder.scala b/test/files/run/t7582/InlineHolder.scala
index 3cbf233ce1..a18b9effaa 100644
--- a/test/files/run/t7582/InlineHolder.scala
+++ b/test/files/run/t7582/InlineHolder.scala
@@ -1,6 +1,3 @@
-/*
- * filter: inliner warning; re-run with
- */
package p1 {
object InlineHolder {
@inline def inlinable = p1.PackageProtectedJava.protectedMethod() + 1
diff --git a/test/files/run/t7582b.check b/test/files/run/t7582b.check
index 0cfbf08886..58d0f19f5d 100644
--- a/test/files/run/t7582b.check
+++ b/test/files/run/t7582b.check
@@ -1 +1,6 @@
+InlineHolder.scala:9: warning: p1/InlineHolder$::inlinable()I is annotated @inline but could not be inlined:
+The callee p1/InlineHolder$::inlinable()I contains the instruction INVOKESTATIC p1/PackageProtectedJava.protectedMethod ()I
+that would cause an IllegalAccessError when inlined into class O$.
+ def x = p1.InlineHolder.inlinable
+ ^
2
diff --git a/test/files/run/t7582b.flags b/test/files/run/t7582b.flags
index 422d6be431..1f45833eff 100644
--- a/test/files/run/t7582b.flags
+++ b/test/files/run/t7582b.flags
@@ -1 +1 @@
--Yopt:l:classpath \ No newline at end of file
+-Yopt:l:classpath -Yopt-warnings \ No newline at end of file
diff --git a/test/files/run/t7582b/InlineHolder.scala b/test/files/run/t7582b/InlineHolder.scala
index 3cbf233ce1..a18b9effaa 100644
--- a/test/files/run/t7582b/InlineHolder.scala
+++ b/test/files/run/t7582b/InlineHolder.scala
@@ -1,6 +1,3 @@
-/*
- * filter: inliner warning; re-run with
- */
package p1 {
object InlineHolder {
@inline def inlinable = p1.PackageProtectedJava.protectedMethod() + 1
diff --git a/test/files/run/t7807.check b/test/files/run/t7807.check
new file mode 100644
index 0000000000..fd22077f2e
--- /dev/null
+++ b/test/files/run/t7807.check
@@ -0,0 +1,3 @@
+...
+...
+...
diff --git a/test/files/run/t7807.scala b/test/files/run/t7807.scala
new file mode 100644
index 0000000000..8e3099ec14
--- /dev/null
+++ b/test/files/run/t7807.scala
@@ -0,0 +1,21 @@
+object Test {
+ def main(args: Array[String]) {
+ try {
+ println("...")
+ }
+ finally {
+ try {
+ println("...")
+ }
+ finally {
+ try {
+ println("...")
+ }
+ catch {
+ case ct: scala.util.control.ControlThrowable => throw(ct)
+ case t: Throwable => t.printStackTrace()
+ }
+ }
+ }
+ }
+}
diff --git a/test/files/run/t9567.scala b/test/files/run/t9567.scala
new file mode 100644
index 0000000000..69896b8650
--- /dev/null
+++ b/test/files/run/t9567.scala
@@ -0,0 +1,18 @@
+object Test {
+ def testMethodLocalCaseClass {
+ case class MethodLocalWide(
+ f01: Int, f02: Int, f03: Int, f04: Int, f05: Int, f06: Int, f07: Int, f08: Int, f09: Int, f10: Int,
+ f11: Int, f12: Int, f13: Int, f14: Int, f15: Int, f16: Int, f17: Int, f18: Int, f19: Int, f20: Int,
+ f21: Int, f22: Int, f23: Int)
+
+ val instance = MethodLocalWide(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ val result = instance match {
+ case MethodLocalWide(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) => true
+ case _ => false
+ }
+ assert(result)
+ }
+ def main(args: Array[String]) {
+ testMethodLocalCaseClass
+ }
+}
diff --git a/test/files/run/t9567b.scala b/test/files/run/t9567b.scala
new file mode 100644
index 0000000000..88cef0a60e
--- /dev/null
+++ b/test/files/run/t9567b.scala
@@ -0,0 +1,19 @@
+object Test {
+ def testMethodLocalCaseClass {
+ object MethodLocalWide
+ case class MethodLocalWide(
+ f01: Int, f02: Int, f03: Int, f04: Int, f05: Int, f06: Int, f07: Int, f08: Int, f09: Int, f10: Int,
+ f11: Int, f12: Int, f13: Int, f14: Int, f15: Int, f16: Int, f17: Int, f18: Int, f19: Int, f20: Int,
+ f21: Int, f22: Int, f23: Int)
+
+ val instance = MethodLocalWide(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ val result = instance match {
+ case MethodLocalWide(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) => true
+ case _ => false
+ }
+ assert(result)
+ }
+ def main(args: Array[String]) {
+ testMethodLocalCaseClass
+ }
+}
diff --git a/test/files/run/t9567c.scala b/test/files/run/t9567c.scala
new file mode 100644
index 0000000000..560bea8821
--- /dev/null
+++ b/test/files/run/t9567c.scala
@@ -0,0 +1,29 @@
+case class CaseSequenceTopLevel(as: Int*)
+
+object Test {
+ def main(args: Array[String]): Unit = {
+
+ val buffer1 = collection.mutable.Buffer(0, 0)
+ CaseSequenceTopLevel(buffer1: _*) match {
+ case CaseSequenceTopLevel(_, i) =>
+ buffer1(1) = 1
+ assert(i == 0, i) // fails in 2.11.7 -optimize
+ }
+
+ case class CaseSequence(as: Int*)
+ val buffer2 = collection.mutable.Buffer(0, 0)
+ CaseSequence(buffer2: _*) match {
+ case CaseSequence(_, i) =>
+ buffer2(1) = 1
+ assert(i == 0, i)
+ }
+
+ case class CaseSequenceWithVar(var x: Any, as: Int*)
+ val buffer3 = collection.mutable.Buffer(0, 0)
+ CaseSequenceWithVar("", buffer3: _*) match {
+ case CaseSequenceWithVar(_, _, i) => // crashes in 2.11.7
+ buffer2(1) = 1
+ assert(i == 0, i)
+ }
+ }
+}
diff --git a/test/junit/scala/collection/ReusableBuildersTest.scala b/test/junit/scala/collection/ReusableBuildersTest.scala
new file mode 100644
index 0000000000..8dd1a37adf
--- /dev/null
+++ b/test/junit/scala/collection/ReusableBuildersTest.scala
@@ -0,0 +1,48 @@
+package scala.collection
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+
+/* Tests various maps by making sure they all agree on the same answers. */
+@RunWith(classOf[JUnit4])
+class ReusableBuildersTest {
+ // GrowingBuilders are NOT reusable but can clear themselves
+ @Test
+ def test_SI8648() {
+ val b = collection.mutable.HashSet.newBuilder[Int]
+ b += 3
+ b.clear
+ assert(!b.isInstanceOf[collection.mutable.ReusableBuilder[_,_]])
+ assert(b.isInstanceOf[collection.mutable.GrowingBuilder[_,_]])
+ assert(b.result == Set[Int]())
+ }
+
+ // ArrayBuilders ARE reusable, regardless of whether they returned their internal array or not
+ @Test
+ def test_SI9564() {
+ val b = Array.newBuilder[Float]
+ b += 3f
+ val three = b.result
+ b.clear
+ b ++= (1 to 16).map(_.toFloat)
+ val sixteen = b.result
+ b.clear
+ b += 0f
+ val zero = b.result
+ assert(b.isInstanceOf[collection.mutable.ReusableBuilder[_,_]])
+ assert(three.toList == 3 :: Nil)
+ assert(sixteen.toList == (1 to 16))
+ assert(zero.toList == 0 :: Nil)
+ }
+
+ @Test
+ def test_reusability() {
+ val bl = List.newBuilder[String]
+ val bv = Vector.newBuilder[String]
+ val ba = collection.mutable.ArrayBuffer.newBuilder[String]
+ assert(bl.isInstanceOf[collection.mutable.ReusableBuilder[_, _]])
+ assert(bv.isInstanceOf[collection.mutable.ReusableBuilder[_, _]])
+ assert(!ba.isInstanceOf[collection.mutable.ReusableBuilder[_, _]])
+ }
+}
diff --git a/test/junit/scala/collection/SearchingTest.scala b/test/junit/scala/collection/SearchingTest.scala
new file mode 100644
index 0000000000..2f939d625e
--- /dev/null
+++ b/test/junit/scala/collection/SearchingTest.scala
@@ -0,0 +1,48 @@
+package scala.collection
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Assert._
+import org.junit.Test
+import scala.collection.Searching._
+
+@RunWith(classOf[JUnit4])
+class SearchingTest {
+
+ @Test
+ def doesLinearSearchOnLinearSeqs() {
+
+ class TestSeq[A](list: List[A]) extends SeqLike[A, TestSeq[A]] {
+ var elementsAccessed = Set.empty[Int]
+
+ protected[this] def newBuilder = ??? // not needed for this test
+ def seq = list
+ def iterator = list.iterator
+ def length = list.length
+ def apply(idx: Int) = { elementsAccessed += idx; list(idx) }
+ }
+
+ val coll = new TestSeq((0 to 6).toList)
+
+ assertEquals(Found(5), coll.search(5))
+ assertEquals(Set.empty, coll.elementsAccessed) // linear search should not access elements via apply()
+ }
+
+ @Test
+ def doesBinarySearchOnIndexedSeqs() {
+
+ class TestIndexedSeq[A](vec: Vector[A]) extends IndexedSeqLike[A, TestIndexedSeq[A]] {
+ var elementsAccessed = Set.empty[Int]
+
+ protected[this] def newBuilder = ??? // not needed for this test
+ def seq = vec
+ def length = vec.length
+ def apply(idx: Int) = { elementsAccessed += idx; vec(idx) }
+ }
+
+ val coll = new TestIndexedSeq((0 to 6).toVector)
+
+ assertEquals(Found(5), coll.search(5))
+ assertEquals(Set(3, 5), coll.elementsAccessed)
+ }
+}
diff --git a/test/junit/scala/collection/immutable/VectorTest.scala b/test/junit/scala/collection/immutable/VectorTest.scala
new file mode 100644
index 0000000000..69f74872d0
--- /dev/null
+++ b/test/junit/scala/collection/immutable/VectorTest.scala
@@ -0,0 +1,30 @@
+package scala.collection.immutable
+
+import org.junit.Assert._
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+
+@RunWith(classOf[JUnit4])
+class VectorTest {
+
+ @Test
+ def hasCorrectDropAndTakeMethods() {
+ val v = Vector(0) ++ Vector(1 to 64: _*)
+
+ assertEquals(Vector(0, 1), v take 2)
+ assertEquals(Vector(63, 64), v takeRight 2)
+ assertEquals(Vector(2 to 64: _*), v drop 2)
+ assertEquals(Vector(0 to 62: _*), v dropRight 2)
+
+ assertEquals(v, v take Int.MaxValue)
+ assertEquals(v, v takeRight Int.MaxValue)
+ assertEquals(Vector.empty[Int], v drop Int.MaxValue)
+ assertEquals(Vector.empty[Int], v dropRight Int.MaxValue)
+
+ assertEquals(Vector.empty[Int], v take Int.MinValue)
+ assertEquals(Vector.empty[Int], v takeRight Int.MinValue)
+ assertEquals(v, v drop Int.MinValue)
+ assertEquals(v, v dropRight Int.MinValue)
+ }
+}
diff --git a/test/junit/scala/issues/OptimizedBytecodeTest.scala b/test/junit/scala/issues/OptimizedBytecodeTest.scala
new file mode 100644
index 0000000000..3c6f1ff25e
--- /dev/null
+++ b/test/junit/scala/issues/OptimizedBytecodeTest.scala
@@ -0,0 +1,331 @@
+package scala.issues
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import scala.tools.asm.Opcodes._
+import org.junit.Assert._
+
+import scala.tools.nsc.backend.jvm.{AsmUtils, CodeGenTools}
+
+import CodeGenTools._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+import AsmUtils._
+
+import scala.tools.testing.ClearAfterClass
+
+object OptimizedBytecodeTest extends ClearAfterClass.Clearable {
+ val args = "-Yopt:l:classpath -Yopt-warnings"
+ var compiler = newCompiler(extraArgs = args)
+ def clear(): Unit = { compiler = null }
+}
+
+@RunWith(classOf[JUnit4])
+class OptimizedBytecodeTest extends ClearAfterClass {
+ ClearAfterClass.stateToClear = OptimizedBytecodeTest
+
+ val compiler = OptimizedBytecodeTest.compiler
+
+ @Test
+ def t2171(): Unit = {
+ val code =
+ """class C {
+ | final def m(msg: => String) = try 0 catch { case ex: Throwable => println(msg) }
+ | def t(): Unit = while (true) m("...")
+ |}
+ """.stripMargin
+ val List(c) = compileClasses(compiler)(code)
+ assertSameCode(getSingleMethod(c, "t").instructions.dropNonOp, List(Label(0), Jump(GOTO, Label(0))))
+ }
+
+ @Test
+ def t3430(): Unit = {
+ val code =
+ """class C {
+ | final def m(f: String => Boolean) = f("a")
+ | def t(): Boolean =
+ | m { s1 =>
+ | m { s2 =>
+ | while (true) { }
+ | true
+ | }
+ | }
+ |}
+ """.stripMargin
+ val List(c) = compileClasses(compiler)(code)
+
+ assertEquals(
+ getSingleMethod(c, "t").instructions.summary,
+ List(LDC, ASTORE, ALOAD /*0*/, ALOAD /*1*/, "C$$$anonfun$1", IRETURN))
+
+ assertEquals(
+ getSingleMethod(c, "C$$$anonfun$1").instructions.summary,
+ List(LDC, "C$$$anonfun$2", IRETURN))
+
+ assertEquals(
+ getSingleMethod(c, "C$$$anonfun$2").instructions.summary,
+ List(-1 /*A*/, GOTO /*A*/))
+ }
+
+ @Test
+ def t3252(): Unit = {
+ val code =
+ """class C {
+ | def t(x: Boolean): Thread = {
+ | g {
+ | x match {
+ | case false => Tat.h { }
+ | }
+ | }
+ | }
+ |
+ | private def g[T](block: => T) = ???
+ |}
+ |object Tat {
+ | def h(block: => Unit): Nothing = ???
+ |}
+ """.stripMargin
+ val List(c, t, tMod) = compileClasses(compiler)(code, allowMessage = _.msg.contains("not be exhaustive"))
+ assertEquals(
+ getSingleMethod(c, "t").instructions.summary,
+ List(GETSTATIC, "$qmark$qmark$qmark", ATHROW))
+ }
+
+ @Test
+ def t6157(): Unit = {
+ val code =
+ """class C {
+ | def t = println(ErrorHandler.defaultIfIOException("String")("String"))
+ |}
+ |object ErrorHandler {
+ | import java.io.IOException
+ | @inline
+ | def defaultIfIOException[T](default: => T)(closure: => T): T = try closure catch {
+ | case e: IOException => default
+ | }
+ |}
+ """.stripMargin
+
+ val msg =
+ """ErrorHandler$::defaultIfIOException(Lscala/Function0;Lscala/Function0;)Ljava/lang/Object; is annotated @inline but could not be inlined:
+ |The operand stack at the callsite in C::t()V contains more values than the
+ |arguments expected by the callee ErrorHandler$::defaultIfIOException(Lscala/Function0;Lscala/Function0;)Ljava/lang/Object;. These values would be discarded
+ |when entering an exception handler declared in the inlined method.""".stripMargin
+
+ compileClasses(compiler)(code, allowMessage = _.msg == msg)
+ }
+
+ @Test
+ def t6547(): Unit = { // "pos" test -- check that it compiles
+ val code =
+ """trait ConfigurableDefault[@specialized V] {
+ | def fillArray(arr: Array[V], v: V) = (arr: Any) match {
+ | case x: Array[Int] => null
+ | case x: Array[Long] => v.asInstanceOf[Long]
+ | }
+ |}
+ """.stripMargin
+ compileClasses(compiler)(code)
+ }
+
+ @Test
+ def t8062(): Unit = {
+ val c1 =
+ """package warmup
+ |object Warmup { def filter[A](p: Any => Boolean): Any = filter[Any](p) }
+ """.stripMargin
+ val c2 = "class C { def t = warmup.Warmup.filter[Any](x => false) }"
+ val List(c, _, _) = compileClassesSeparately(List(c1, c2), extraArgs = OptimizedBytecodeTest.args)
+ assertInvoke(getSingleMethod(c, "t"), "warmup/Warmup$", "filter")
+ }
+
+ @Test
+ def t8306(): Unit = { // "pos" test
+ val code =
+ """class C {
+ | def foo: Int = 123
+ | lazy val extension: Int = foo match {
+ | case idx if idx != -1 => 15
+ | case _ => 17
+ | }
+ |}
+ """.stripMargin
+ compileClasses(compiler)(code)
+ }
+
+ @Test
+ def t8359(): Unit = { // "pos" test
+ // This is a minimization of code that crashed the compiler during bootstrapping
+ // in the first iteration of https://github.com/scala/scala/pull/4373, the PR
+ // that adjusted the order of free and declared params in LambdaLift.
+
+ // Was:
+ // java.lang.AssertionError: assertion failed:
+ // Record Record(<$anon: Function1>,Map(value a$1 -> Deref(LocalVar(value b)))) does not contain a field value b$1
+ // at scala.tools.nsc.Global.assert(Global.scala:262)
+ // at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:113)
+ // at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:122)
+ // at scala.tools.nsc.backend.opt.ClosureElimination$ClosureElim$$anonfun$analyzeMethod$1$$anonfun$apply$2.replaceFieldAccess$1(ClosureElimination.scala:124)
+ val code =
+ """package test
+ |class Typer {
+ | def bar(a: Boolean, b: Boolean): Unit = {
+ | @inline
+ | def baz(): Unit = {
+ | ((_: Any) => (Typer.this, a, b)).apply("")
+ | }
+ | ((_: Any) => baz()).apply("")
+ | }
+ |}
+ """.stripMargin
+ compileClasses(compiler)(code)
+ }
+
+ @Test
+ def t9123(): Unit = { // "pos" test
+ val code =
+ """trait Setting {
+ | type T
+ | def value: T
+ |}
+ |object Test {
+ | def test(x: Some[Setting]) = x match {
+ | case Some(dep) => Some(dep.value) map (_ => true)
+ | }
+ |}
+ """.stripMargin
+ compileClasses(compiler)(code)
+ }
+
+ @Test
+ def traitForceInfo(): Unit = {
+ // This did NOT crash unless it's in the interactive package.
+ // error: java.lang.AssertionError: assertion failed: trait Contexts.NoContext$ linkedModule: <none>List()
+ // at scala.Predef$.assert(Predef.scala:160)
+ // at scala.tools.nsc.symtab.classfile.ClassfileParser$innerClasses$.innerSymbol$1(ClassfileParser.scala:1211)
+ // at scala.tools.nsc.symtab.classfile.ClassfileParser$innerClasses$.classSymbol(ClassfileParser.scala:1223)
+ // at scala.tools.nsc.symtab.classfile.ClassfileParser.classNameToSymbol(ClassfileParser.scala:489)
+ // at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$1(ClassfileParser.scala:757)
+ // at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$1(ClassfileParser.scala:789)
+ val code =
+ """package scala.tools.nsc
+ |package interactive
+ |
+ |trait MyContextTrees {
+ | val self: Global
+ | val NoContext = self.analyzer.NoContext
+ |}
+ """.stripMargin
+ compileClasses(compiler)(code)
+ }
+
+ @Test
+ def t9160(): Unit = {
+ val code =
+ """class C {
+ | def getInt: Int = 0
+ | def t(trees: Object): Int = {
+ | trees match {
+ | case Some(elems) =>
+ | case tree => getInt
+ | }
+ | 55
+ | }
+ |}
+ """.stripMargin
+ val List(c) = compileClasses(compiler)(code)
+ assertEquals(
+ getSingleMethod(c, "t").instructions.summary,
+ List(
+ ALOAD /*1*/, INSTANCEOF /*Some*/, IFNE /*A*/,
+ ALOAD /*0*/, "getInt", POP,
+ -1 /*A*/, BIPUSH, IRETURN))
+ }
+
+ @Test
+ def t8796(): Unit = {
+ val code =
+ """final class C {
+ | def pr(): Unit = ()
+ | def t(index: Int): Unit = index match {
+ | case 0 => pr()
+ | case 1 => pr()
+ | case _ => t(index - 2)
+ | }
+ |}
+ """.stripMargin
+ val List(c) = compileClasses(compiler)(code)
+ assertEquals(
+ getSingleMethod(c, "t").instructions.summary,
+ List(
+ -1 /*A*/, ILOAD /*1*/, TABLESWITCH,
+ -1, ALOAD, "pr", RETURN,
+ -1, ALOAD, "pr", RETURN,
+ -1, ILOAD, ICONST_2, ISUB, ISTORE, GOTO /*A*/))
+ }
+
+ @Test
+ def t8524(): Unit = {
+ val c1 =
+ """package library
+ |object Library {
+ | @inline def pleaseInlineMe() = 1
+ | object Nested { @inline def pleaseInlineMe() = 2 }
+ |}
+ """.stripMargin
+
+ val c2 =
+ """class C {
+ | def t = library.Library.pleaseInlineMe() + library.Library.Nested.pleaseInlineMe()
+ |}
+ """.stripMargin
+
+ val cls = compileClassesSeparately(List(c1, c2), extraArgs = OptimizedBytecodeTest.args)
+ val c = cls.find(_.name == "C").get
+ assertEquals(
+ getSingleMethod(c, "t").instructions.summary,
+ List(
+ GETSTATIC, IFNONNULL, ACONST_NULL, ATHROW, // module load and null checks not yet eliminated
+ -1, ICONST_1, GETSTATIC, IFNONNULL, ACONST_NULL, ATHROW,
+ -1, ICONST_2, IADD, IRETURN))
+ }
+
+ @Test
+ def privateInline(): Unit = {
+ val code =
+ """final class C {
+ | private var x1 = false
+ | var x2 = false
+ |
+ | @inline private def wrapper1[T](body: => T): T = {
+ | val saved = x1
+ | x1 = true
+ | try body
+ | finally x1 = saved
+ | }
+ |
+ | @inline private def wrapper2[T](body: => T): T = {
+ | val saved = x2
+ | x2 = true
+ | try body
+ | finally x2 = saved
+ | }
+ | // inlined
+ | def f1a() = wrapper1(5)
+ | // not inlined: even after inlining `identity`, the Predef module is already on the stack for the
+ | // subsequent null check (the receiver of an inlined method, in this case Predef, is checked for
+ | // nullness, to ensure an NPE is thrown)
+ | def f1b() = identity(wrapper1(5))
+ |
+ | def f2a() = wrapper2(5) // inlined
+ | def f2b() = identity(wrapper2(5)) // not inlined
+ |}
+ """.stripMargin
+ val List(c) = compileClasses(compiler)(code, allowMessage = _.msg.contains("exception handler declared in the inlined method"))
+ assertInvoke(getSingleMethod(c, "f1a"), "C", "C$$$anonfun$1")
+ assertInvoke(getSingleMethod(c, "f1b"), "C", "wrapper1")
+ assertInvoke(getSingleMethod(c, "f2a"), "C", "C$$$anonfun$3")
+ assertInvoke(getSingleMethod(c, "f2b"), "C", "wrapper2")
+ }
+}
diff --git a/test/junit/scala/reflect/ClassTagTest.scala b/test/junit/scala/reflect/ClassTagTest.scala
index 90cc981fc1..49022dccda 100644
--- a/test/junit/scala/reflect/ClassTagTest.scala
+++ b/test/junit/scala/reflect/ClassTagTest.scala
@@ -26,4 +26,14 @@ class ClassTagTest {
@Test def checkDouble = assertTrue(checkNotInt[Double] (0.toDouble))
@Test def checkBoolean = assertTrue(checkNotInt[Boolean](false))
@Test def checkUnit = assertTrue(checkNotInt[Unit] ({}))
-} \ No newline at end of file
+
+ @Test def t9534: Unit = {
+ val ct = implicitly[scala.reflect.ClassTag[Unit]]
+ val a1 = ct.newArray(1)
+ a1(0) = ()
+ val a2 = ct.wrap.newArray(1)
+ a2(0) = a1
+ val a3 = ct.newArray2(1)
+ a3(0) = a1
+ }
+}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
index 342f403426..0d353e930e 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
@@ -50,9 +50,11 @@ object CodeGenTools {
}
def newCompilerWithoutVirtualOutdir(defaultArgs: String = "-usejavacp", extraArgs: String = ""): Global = {
- val settings = new Settings()
+ def showError(s: String) = throw new Exception(s)
+ val settings = new Settings(showError)
val args = (CommandLineParser tokenize defaultArgs) ++ (CommandLineParser tokenize extraArgs)
- settings.processArguments(args, processAll = true)
+ val (_, nonSettingsArgs) = settings.processArguments(args, processAll = true)
+ if (nonSettingsArgs.nonEmpty) showError("invalid compiler flags: " + nonSettingsArgs.mkString(" "))
new Global(settings, new StoreReporter)
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala b/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala
new file mode 100644
index 0000000000..80cde6c9a9
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala
@@ -0,0 +1,70 @@
+package scala.tools.nsc
+package backend.jvm
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import scala.tools.asm.Opcodes._
+import org.junit.Assert._
+
+import scala.tools.testing.AssertUtil._
+
+import CodeGenTools._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+import scala.tools.testing.ClearAfterClass
+
+object StringConcatTest extends ClearAfterClass.Clearable {
+ var compiler = newCompiler()
+ def clear(): Unit = { compiler = null }
+}
+
+@RunWith(classOf[JUnit4])
+class StringConcatTest extends ClearAfterClass {
+ ClearAfterClass.stateToClear = StringConcatTest
+ val compiler = StringConcatTest.compiler
+
+ val commonPreInstructions = List(Label(0), LineNumber(1, Label(0)), TypeOp(NEW, "java/lang/StringBuilder"), Op(DUP), Invoke(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false), Ldc(LDC, "abc"), Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false), VarOp(ALOAD, 0))
+
+ val commonPostInstructions = List(Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false), Op(ARETURN), Label(12))
+
+ def instructionsWithCommonParts(instructions: List[Instruction]) = commonPreInstructions ++ instructions ++ commonPostInstructions
+
+ def instructionsForResultMethod(code: String): List[Instruction] = {
+ val methods = compileMethods(compiler)(code)
+ val resultMethod = methods.find(_.name == "result").get
+ instructionsFromMethod(resultMethod)
+ }
+
+ @Test
+ def concatStringToStringBuilder: Unit = {
+ val code = """ def string = "def"; def result = "abc" + string """
+ val actualInstructions = instructionsForResultMethod(code)
+ val expectedInstructions = instructionsWithCommonParts(List(Invoke(INVOKEVIRTUAL, "C", "string", "()Ljava/lang/String;", false), Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false)))
+ assertSameCode(actualInstructions, expectedInstructions)
+ }
+
+ @Test
+ def concatStringBufferToStringBuilder: Unit = {
+ val code = """ def stringBuffer = new java.lang.StringBuffer("def"); def result = "abc" + stringBuffer """
+ val actualInstructions = instructionsForResultMethod(code)
+ val expectedInstructions = instructionsWithCommonParts(List(Invoke(INVOKEVIRTUAL, "C", "stringBuffer", "()Ljava/lang/StringBuffer;", false), Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/StringBuffer;)Ljava/lang/StringBuilder;", false)))
+ assertSameCode(actualInstructions, expectedInstructions)
+ }
+
+ @Test
+ def concatCharSequenceToStringBuilder: Unit = {
+ val code = """ def charSequence: CharSequence = "def"; def result = "abc" + charSequence """
+ val actualInstructions = instructionsForResultMethod(code)
+ val expectedInstructions = instructionsWithCommonParts(List(Invoke(INVOKEVIRTUAL, "C", "charSequence", "()Ljava/lang/CharSequence;", false), Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/CharSequence;)Ljava/lang/StringBuilder;", false)))
+ assertSameCode(actualInstructions, expectedInstructions)
+ }
+
+ @Test
+ def concatIntToStringBuilder: Unit = {
+ val code = """ def int = 123; def result = "abc" + int """
+ val actualInstructions = instructionsForResultMethod(code)
+ val expectedInstructions = instructionsWithCommonParts(List(Invoke(INVOKEVIRTUAL, "C", "int", "()I", false), Invoke(INVOKESTATIC, "scala/runtime/BoxesRunTime", "boxToInteger", "(I)Ljava/lang/Integer;", false), Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/Object;)Ljava/lang/StringBuilder;", false)))
+ assertSameCode(actualInstructions, expectedInstructions)
+ }
+}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala
index a685ae7dd5..99acb318de 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala
@@ -96,10 +96,22 @@ class SimplifyJumpsTest {
instructionsFromMethod(method),
List(VarOp(ILOAD, 1), Jump(IFLT, Label(3))) ::: rest.tail )
- // no label allowed between begin and rest. if there's another label, then there could be a
- // branch that label. eliminating the GOTO would change the behavior.
- val nonOptMethod = genMethod()(begin ::: Label(22) :: rest: _*)
- assertFalse(LocalOptImpls.simplifyJumps(nonOptMethod))
+ // branch over goto is OK even if there's a label in between, if that label is not a jump target
+ val withNonJumpTargetLabel = genMethod()(begin ::: Label(22) :: rest: _*)
+ assertTrue(LocalOptImpls.simplifyJumps(withNonJumpTargetLabel))
+ assertSameCode(
+ instructionsFromMethod(withNonJumpTargetLabel),
+ List(VarOp(ILOAD, 1), Jump(IFLT, Label(3)), Label(22)) ::: rest.tail )
+
+ // if the Label(22) between IFGE and GOTO is the target of some jump, we cannot rewrite the IFGE
+ // and remove the GOTO: removing the GOTO would change semantics. However, the jump that targets
+ // Label(22) will be re-written (jump-chain collapsing), so in a second round, the IFGE is still
+ // rewritten to IFLT
+ val twoRounds = genMethod()(List(VarOp(ILOAD, 1), Jump(IFLE, Label(22))) ::: begin ::: Label(22) :: rest: _*)
+ assertTrue(LocalOptImpls.simplifyJumps(twoRounds))
+ assertSameCode(
+ instructionsFromMethod(twoRounds),
+ List(VarOp(ILOAD, 1), Jump(IFLE, Label(3)), VarOp(ILOAD, 1), Jump(IFLT, Label(3)), Label(22)) ::: rest.tail )
}
@Test
@@ -167,6 +179,9 @@ class SimplifyJumpsTest {
VarOp(ILOAD, 1),
Jump(IFGE, Label(target)),
+ VarOp(ILOAD, 1), // some code to prevent rewriting the conditional jump
+ Op(IRETURN),
+
Label(4),
Jump(GOTO, Label(3)),
diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala
index ec4621b230..3fc3144eb2 100644
--- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala
+++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala
@@ -134,4 +134,29 @@ class PatmatBytecodeTest extends ClearAfterClass {
NEW, DUP, ALOAD /*1*/, "<init>", ATHROW,
/*R*/ -1, ALOAD /*2*/, ARETURN))
}
+
+ @Test
+ def t6941(): Unit = {
+ val code =
+ """class C {
+ | def a(xs: List[Int]) = xs match {
+ | case x :: _ => x
+ | }
+ | def b(xs: List[Int]) = xs match {
+ | case xs: ::[Int] => xs.head
+ | }
+ |}
+ """.stripMargin
+ val c = compileClasses(optCompiler)(code, allowMessage = _.msg.contains("may not be exhaustive")).head
+
+ val expected = List(
+ ALOAD /*1*/ , INSTANCEOF /*::*/ , IFEQ /*A*/ ,
+ ALOAD, CHECKCAST /*::*/ , "head", "unboxToInt",
+ ISTORE, GOTO /*B*/ ,
+ -1 /*A*/ , NEW /*MatchError*/ , DUP, ALOAD /*1*/ , "<init>", ATHROW,
+ -1 /*B*/ , ILOAD, IRETURN)
+
+ assertEquals(textify(findAsmMethod(c, "a")), getSingleMethod(c, "a").instructions.summary, expected)
+ assertEquals(textify(findAsmMethod(c, "b")), getSingleMethod(c, "b").instructions.summary, expected)
+ }
}
diff --git a/test/pending/run/private-inline.check b/test/pending/run/private-inline.check
deleted file mode 100644
index e71aec2fcf..0000000000
--- a/test/pending/run/private-inline.check
+++ /dev/null
@@ -1,13 +0,0 @@
-private-inline.scala:24: warning: Could not inline required method wrapper1 because callee contains exception handlers / finally clause, and is invoked with non-empty operand stack.
- def f1b() = identity(wrapper1(5))
- ^
-private-inline.scala:24: warning: At the end of the day, could not inline @inline-marked method wrapper1
- def f1b() = identity(wrapper1(5))
- ^
-private-inline.scala:29: warning: Could not inline required method wrapper2 because callee contains exception handlers / finally clause, and is invoked with non-empty operand stack.
- def f2b() = identity(wrapper2(5))
- ^
-private-inline.scala:29: warning: At the end of the day, could not inline @inline-marked method wrapper2
- def f2b() = identity(wrapper2(5))
- ^
-20
diff --git a/test/pending/run/private-inline.flags b/test/pending/run/private-inline.flags
deleted file mode 100644
index c550fdce16..0000000000
--- a/test/pending/run/private-inline.flags
+++ /dev/null
@@ -1 +0,0 @@
--optimise -Yinline-warnings -Ybackend:GenASM
diff --git a/test/pending/run/private-inline.scala b/test/pending/run/private-inline.scala
deleted file mode 100644
index 60fef9efca..0000000000
--- a/test/pending/run/private-inline.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-
-final class A {
- private var x1 = false
- var x2 = false
-
- // manipulates private var
- @inline private def wrapper1[T](body: => T): T = {
- val saved = x1
- x1 = true
- try body
- finally x1 = saved
- }
- // manipulates public var
- @inline private def wrapper2[T](body: => T): T = {
- val saved = x2
- x2 = true
- try body
- finally x2 = saved
- }
-
- // not inlined
- def f1a() = wrapper1(5)
- // inlined!
- def f1b() = identity(wrapper1(5))
-
- // not inlined
- def f2a() = wrapper2(5)
- // inlined!
- def f2b() = identity(wrapper2(5))
-}
-
-object Test {
- def methodClasses = List("f1a", "f2a") map ("A$$anonfun$" + _ + "$1")
-
- def main(args: Array[String]): Unit = {
- val a = new A
- import a._
- println(f1a() + f1b() + f2a() + f2b())
-
- // Don't know how else to test this: all these should have been
- // inlined, so all should fail.
- methodClasses foreach { clazz =>
-
- val foundClass = (
- try Class.forName(clazz)
- catch { case _: Throwable => null }
- )
-
- assert(foundClass == null, foundClass)
- }
- }
-}
diff --git a/test/scaladoc/run/SI-9620.check b/test/scaladoc/run/SI-9620.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-9620.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-9620.scala b/test/scaladoc/run/SI-9620.scala
new file mode 100644
index 0000000000..96260aad9a
--- /dev/null
+++ b/test/scaladoc/run/SI-9620.scala
@@ -0,0 +1,43 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+ override def code = """
+ package a
+
+ trait Foo[S] {
+ def foo(t: S): Int = 123
+ }
+
+ /** Boo with only one foo method, hopefully!
+ * @hideImplicitConversion BooShouldNotAppearIsFoo
+ */
+ trait Boo[T]
+
+ object Boo {
+ sealed trait ShouldNotAppear
+ implicit class BooShouldNotAppearIsFoo(boo: Boo[ShouldNotAppear]) extends Foo[ShouldNotAppear]
+ implicit class BooLongIsFoo(boo: Boo[Long]) extends Foo[Long]
+ }
+ """
+
+ // no need for special settings
+ def scaladocSettings = "-implicits"
+
+ def testModel(rootPackage: Package) = {
+ import access._
+
+ // Assert Boo only has one implicit conversion
+ val boo = rootPackage._package("a")._trait("Boo")
+ val conversions = boo._conversions("a.Boo.BooShouldNotAppearIsFoo") ++ boo._conversions("a.Boo.BooLongIsFoo")
+ assert(conversions.length == 1, conversions.length + " == 1")
+
+ // Assert that the implicit conversion is not "BooShouldNotAppearIsFoo"
+ assert(conversions.head.conversionShortName == "BooLongIsFoo",
+ conversions.head.conversionShortName + " == BooLongIsFoo")
+
+ // Assert that the same for full path
+ assert(conversions.head.conversionQualifiedName == "a.Boo.BooLongIsFoo",
+ conversions.head.conversionQualifiedName + " == a.Boo.BooLongIsFoo")
+ }
+}
diff --git a/test/scaladoc/run/tag-requirements.check b/test/scaladoc/run/tag-requirements.check
new file mode 100644
index 0000000000..184273b883
--- /dev/null
+++ b/test/scaladoc/run/tag-requirements.check
@@ -0,0 +1,16 @@
+newSource:3: warning: Only one '@version' tag is allowed
+ /**
+ ^
+newSource:9: warning: Tag '@param' must be followed by a symbol name
+ /**
+ ^
+newSource:9: warning: Tag '@param' is not recognised
+ /**
+ ^
+newSource:14: warning: Only one '@param' tag for symbol b is allowed
+ /**
+ ^
+newSource:20: warning: Tag '@unrecognised' is not recognised
+ /**
+ ^
+Done.
diff --git a/test/scaladoc/run/tag-requirements.scala b/test/scaladoc/run/tag-requirements.scala
new file mode 100644
index 0000000000..24f1fab761
--- /dev/null
+++ b/test/scaladoc/run/tag-requirements.scala
@@ -0,0 +1,53 @@
+import scala.tools.nsc.doc.base._
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code =
+ """
+ package scala.test.scaladoc.tagrequirements
+ /**
+ * object comment
+ * @version 1.0
+ * @version 2.0
+ */
+ object Test {
+ /**
+ * foo comment
+ * @param
+ */
+ def foo(b: Any) = ???
+ /**
+ * bar comment
+ * @param b A value
+ * @param b A value
+ */
+ def bar(b: Any) = ???
+ /**
+ * baz comment
+ * @unrecognised
+ */
+ def baz() = ???
+ }
+ """
+
+ def scaladocSettings = ""
+
+ def testModel(root: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ val base = root._package("scala")._package("test")._package("scaladoc")._package("tagrequirements")
+
+ val test = base._object("Test")
+ /*
+ * We only care about the warnings which are side effects but we assert on the comment to
+ * avoid static code analysis noise about unused values.
+ */
+ assert(extractCommentText(test.comment.get) == "object comment")
+ assert(extractCommentText(test._method("foo").comment.get) == "foo comment")
+ assert(extractCommentText(test._method("bar").comment.get) == "bar comment")
+ assert(extractCommentText(test._method("baz").comment.get) == "baz comment")
+ }
+}
diff --git a/tools/scaladoc-diff b/tools/scaladoc-diff
new file mode 100755
index 0000000000..df0d1f3335
--- /dev/null
+++ b/tools/scaladoc-diff
@@ -0,0 +1,117 @@
+#!/usr/bin/env bash
+#
+# Script to compare the scaladoc of the current commit with the scaladoc
+# of the parent commit. No arguments.
+#
+
+set -e
+
+# opendiff for Mac OS X, meld for Ubuntu then default to other commands.
+displaydiff() {
+ case "$(uname -s)" in
+
+ Darwin)
+ if hash opendiff 2>/dev/null; then
+ echo opendiff "$@"
+ opendiff "$@"
+ else
+ echo diff "$@"
+ diff -y "$@" | less -N
+ fi
+ ;;
+
+ *)
+ if hash meld 2>/dev/null; then
+ echo meld "$@"
+ meld "$@"
+ elif hash gvimdiff 2>/dev/null; then
+ echo gvimdiff "$@"
+ gvimdiff "$@"
+ else
+ echo diff "$@"
+ diff -y "$@" | less -N
+ fi
+ ;;
+ esac
+}
+
+oldsha=$(git rev-parse --short HEAD^)
+
+# Use branch name defaulting to SHA1 when not available for example when in
+# detached HEAD state.
+sha=$(git symbolic-ref -q --short HEAD || git rev-parse --short HEAD)
+
+echo "parent commit sha : $oldsha"
+echo "current commit sha : $sha"
+
+# create scaladoc for parent commit if not done already
+if [ ! -f "build/scaladoc-output-$oldsha.txt" ]
+then
+ echo "making scaladoc for parent commit ($oldsha)"
+ git checkout -q $oldsha
+ ant docs.lib -Dscaladoc.raw.output='yes' > build/scaladoc-output-$oldsha.txt
+ rm -rf build/scaladoc-${oldsha}
+ mv build/scaladoc build/scaladoc-${oldsha}
+ git checkout -q $sha
+fi
+
+# create scaladoc for current commit
+echo "making scaladoc for current commit ($sha)"
+ant docs.lib -Dscaladoc.raw.output='yes' > build/scaladoc-output-$sha.txt
+rm -rf build/scaladoc-${sha}
+mv build/scaladoc build/scaladoc-${sha}
+
+# Allow script to continue when diff results in -1
+set +e
+
+displaydiff build/scaladoc-output-$oldsha.txt build/scaladoc-output-$sha.txt
+
+# Adapted from tools/scaladoc-compare
+echo "Comparing versions with diff: build/scaladoc-${sha}/ build/scaladoc-$oldsha/"
+NEW_PATH=build/scaladoc-${sha}/
+OLD_PATH=build/scaladoc-$oldsha/
+
+
+NEWFILES=$(find $NEW_PATH -name '*.html.raw')
+if [ "$NEWFILES" == "" ]
+then
+ echo "No .html.raw files found in $NEW_PATH!"
+ exit 1
+fi
+
+for NEW_FILE in $NEWFILES
+do
+ OLD_FILE=${NEW_FILE/$NEW_PATH/$OLD_PATH}
+ if [ -f $OLD_FILE ]
+ then
+ DIFF=$(diff -q -w $NEW_FILE $OLD_FILE 2>&1)
+ if [ "$DIFF" != "" ]
+ then
+ displaydiff $OLD_FILE $NEW_FILE > /dev/null
+
+ echo "next [y\N]? "
+ read -n 1 -s input
+ if [ "$input" == "N" ]; then exit 0; fi
+ fi
+ else
+ echo
+ echo "New file: : $NEW_FILE"
+ echo "No corresponding old file : $OLD_FILE"
+
+ echo "next [y\N]? "
+ read -n 1 -s input
+ if [ "$input" == "N" ]; then exit 0; fi
+ fi
+done
+
+OLDFILES=$(find $OLD_PATH -name '*.html.raw')
+for OLD_FILE in $OLDFILES
+do
+ NEW_FILE=${OLD_FILE/$OLD_PATH/$NEW_PATH}
+ if [ ! -f $NEW_FILE ]
+ then
+ echo
+ echo "Old file: : $OLD_FILE"
+ echo "No corresponding new file : $NEW_FILE"
+ fi
+done
diff --git a/versions.properties b/versions.properties
index e4c2a5b8e8..7cdafc975a 100644
--- a/versions.properties
+++ b/versions.properties
@@ -30,7 +30,7 @@ jline.version=2.12.1
scala-asm.version=5.0.4-scala-3
# external modules, used internally (not shipped)
-partest.version.number=1.0.9
+partest.version.number=1.0.12
scalacheck.version.number=1.11.6
# TODO: modularize the compiler