diff options
449 files changed, 16464 insertions, 34980 deletions
diff --git a/.gitignore b/.gitignore index 20d700dd12..d6571a377f 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,9 @@ # Standard symbolic link to build/quick/bin /qbin + +# Sbt's target directories +/target/ +/project/target/ +/project/project/target +/build-sbt/ diff --git a/.travis.yml b/.travis.yml index e90fc35267..6a7ac45e3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ # based on http://www.paperplanes.de/2013/8/13/deploying-your-jekyll-blog-to-s3-with-travis-ci.html language: ruby rvm: - - 1.9.3 + - 2.2 script: bundle exec jekyll build -s spec/ -d build/spec install: bundle install @@ -1,7 +1,7 @@ # To build the spec on Travis CI source "https://rubygems.org" -gem "jekyll", "2.0.0.alpha.2" +gem "jekyll", "2.5.3" gem "rouge" # gem 's3_website' # gem 'redcarpet' @@ -13,15 +13,15 @@ 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) | anything (type checker, pattern matcher, CI,...) | - <img src="https://avatars.githubusercontent.com/gkossakowski" height="50px" title="Grzegorz Kossakowski"/> | [`@gkossakowski`](https://github.com/gkossakowski) | infrastructure, incremental compilation, back-end | + <img src="https://avatars.githubusercontent.com/adriaanm" height="50px" title="Adriaan Moors"/> | [`@adriaanm`](https://github.com/adriaanm) | how we can help // type checker, pattern matcher, infrastructure | + <img src="https://avatars.githubusercontent.com/SethTisue" height="50px" title="Seth Tisue"/> | [`@SethTisue`](https://github.com/SethTisue) | back-end, library, improving the *welcome to Scala* experience | <img src="https://avatars.githubusercontent.com/retronym" height="50px" title="Jason Zaugg"/> | [`@retronym`](https://github.com/retronym) | Java 8 lambdas, tricky bug detective work | <img src="https://avatars.githubusercontent.com/Ichoran" height="50px" title="Rex Kerr"/> | [`@Ichoran`](https://github.com/Ichoran) | the collections library, performance | <img src="https://avatars.githubusercontent.com/lrytz" height="50px" title="Lukas Rytz"/> | [`@lrytz`](https://github.com/lrytz) | optimizer, named & default arguments | - <img src="https://avatars.githubusercontent.com/dickwall" height="50px" title="Dick Wall"/> | [`@dickwall`](https://github.com/dickwall) | process & documentation | <img src="https://avatars.githubusercontent.com/VladUreche" height="50px" title="Vlad Ureche"/> | [`@VladUreche`](https://github.com/VladUreche) | specialization & the scaladoc tool | <img src="https://avatars.githubusercontent.com/densh" height="50px" title="Denys Shabalin"/> | [`@densh`](https://github.com/densh) | quasiquotes, parser, string interpolators, macros in standard library | <img src="https://avatars.githubusercontent.com/xeno-by" height="50px" title="Eugene Burmako"/> | [`@xeno-by`](https://github.com/xeno-by) | macros and reflection | + <img src="https://avatars.githubusercontent.com/dickwall" height="50px" title="Dick Wall"/> | [`@dickwall`](https://github.com/dickwall) | process & community | PS: If you have some spare time to help out around here, we would be delighted to add your name to this list! @@ -29,8 +29,8 @@ PS: If you have some spare time to help out around here, we would be delighted t # Handy Links - [A wealth of documentation](http://docs.scala-lang.org) - [Scala CI](https://scala-ci.typesafe.com/) - - [Scala CI at EPFL](https://scala-webapps.epfl.ch/jenkins/) - [Download the latest nightly](http://www.scala-lang.org/files/archive/nightly/2.11.x/); + - [(Deprecated) Scala CI at EPFL](https://scala-webapps.epfl.ch/jenkins/) - Scala mailing lists: - [Compiler and standard library development](https://groups.google.com/group/scala-internals) - [Users of Scala](https://groups.google.com/group/scala-user) @@ -51,7 +51,7 @@ scala/ +---/reflect Scala Reflection. +---/compiler Scala Compiler. +---/eclipse Eclipse project files. - +---/intellij-14 IntelliJ project templates. + +---/intellij IntelliJ project templates. +--scripts/ Scripts for the CI jobs (including building releases) +--test/ The Scala test suite. +--build/ [Generated] Build products output directory for ant. @@ -66,7 +66,7 @@ You'll need a Java SDK (6 or newer), Apache Ant (version 1.8.0 or above), and cu ## Git Hygiene -As git history is forever, we take great pride in the quality of the commits we merge into the repository. The title of your commit will be read hundreds (of thousands? :-)) of times, so it pays off to spend just a little bit more time to polish it, making it descriptive and concise. Please take a minute to read the advice [most projects agree on](https://github.com/erlang/otp/wiki/Writing-good-commit-messages), and stick to 50-60 characters for the first line, wrapping subsequent ones at 80 (at most). +As git history is forever, we take great pride in the quality of the commits we merge into the repository. The title of your commit will be read hundreds (of thousands? :-)) of times, so it pays off to spend just a little bit more time to polish it, making it descriptive and concise. Please take a minute to read the advice [most projects agree on](https://github.com/erlang/otp/wiki/Writing-good-commit-messages), and stick to 72 or fewer characters for the first line, wrapping subsequent ones at 80 (at most). When not sure how to formulate your commit message, imagine you're writing a bullet item for the next release notes, or describing what the commit does to the code base (use active verbs in the present tense). When your commit title is featured in the next release notes, it will be read by a lot of curious Scala users, looking for the latest improvements. Satisfy their thirst for information with as few words as possible! Also, a commit should convey clearly to your (future) fellow contributors what it does to the code base. @@ -91,13 +91,19 @@ To help you plan your contributions, we communicate our plans on a regular basis Once you've gained some experience with the code base and the process, the logical next step is to offers reviews for others's contributions. The main goal of this whole process, in the end, is to ensure the health of the Scala project by improving the quality of the code base, the documentation, as well as this process itself. Thank you for doing your part! +## [Labels](https://github.com/scala/scala/labels) + - `reviewed` automatically added by scabot when a comment prefixed with LGTM is posted + - `welcome` reviewer / queue curator adds to welcome someone's first PR (for highlighting in the release notes) + - `release-notes` reviewer / queue curator adds to make sure this PR is highlighted in the release notes + - `on-hold` added when this PR should not yet be merged, even though CI is green + ### Tips & Tricks Once the `publish-core` task has completed on a commit, you can try it out in sbt as follows: ``` $ sbt -> set resolvers += "pr" at "http://private-repo.typesafe.com/typesafe/scala-pr-validation-snapshots/" +> set resolvers += "pr" at "https://scala-ci.typesafe.com/artifactory/scala-pr-validation-snapshots/" > set scalaVersion := "<milestone>-<sha7>-SNAPSHOT" > console ``` @@ -118,8 +124,8 @@ Use the latest IntelliJ IDEA release and install the Scala plugin from within th The following steps are required to use IntelliJ IDEA on Scala trunk - Run `ant init`. This will download some JARs to `./build/deps`, which are included in IntelliJ's classpath. - - Run src/intellij-14/setup.sh - - Open ./src/intellij-14/scala.ipr in IntelliJ + - Run src/intellij/setup.sh + - Open ./src/intellij/scala.ipr in IntelliJ - File, Project Settings, Project, SDK. Create an SDK entry named "1.6" containing the Java 1.6 SDK. (You may use a later SDK for local development, but the CI will verify against Java 6.) @@ -138,6 +144,15 @@ The Scala build system is based on Apache Ant. Most required pre-compiled libraries are part of the repository (in 'lib/'). The following however is assumed to be installed on the build machine: +## Building with Sbt (EXPERIMENTAL) + +The experimental sbt-based build definition has arrived! Run `sbt package` +to build the compiler. You can run `sbt test` to run unit (JUnit) tests. +Use `sbt test/it:test` to run integration (partest) tests. + +We would like to migrate to sbt build as quickly as possible. If you would +like to help please contact scala-internals@ mailing list to discuss your +ideas and coordinate your effort with others. ### Tips and tricks diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 3808083dd3..8fadb65f39 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -319,6 +319,59 @@ filter { { matchName="scala.util.Random.scala$util$Random$$nextAlphaNum$1" problemName=MissingMethodProblem + }, + // Nominally private but in practice JVM-visible methods for reworked scala.util.Sorting + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSort$default$5" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSort$mBc$sp" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSort$mFc$sp" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSort$mJc$sp" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSort" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSort$mCc$sp" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSort$mSc$sp" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$insertionSort" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSort$mZc$sp" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSort$mDc$sp" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSort$mIc$sp" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$mergeSorted" + problemName=MissingMethodProblem + }, + { + matchName="scala.util.Sorting.scala$util$Sorting$$booleanSort" + problemName=MissingMethodProblem } ] } diff --git a/build-ant-macros.xml b/build-ant-macros.xml index 259d6a6eb6..ace86cac49 100644 --- a/build-ant-macros.xml +++ b/build-ant-macros.xml @@ -91,7 +91,7 @@ <macrodef name="simple-javac"> <attribute name="project"/> - <!-- project: asm/forkjoin --> + <!-- project: forkjoin --> <attribute name="args" default=""/> <attribute name="jar" default="yes"/> <sequential> @@ -371,6 +371,10 @@ <then> <mkdir dir="${build-pack.dir}/${@{project}.targetdir}"/> <pre/> + <!-- can't check if a fileset is defined, so we have an additional property --> + <if><not><isset property="pack.@{project}.include-jars.defined"/></not><then> + <fileset id="pack.@{project}.include-jars" dir="." excludes="**" /> + </then></if> <if> <not> <equals arg1="@{manifest}" arg2=""/> @@ -380,6 +384,7 @@ <!-- update="true" makes no difference on my machine, so starting from scratch--> <jar-opts/> <path refid="pack.@{project}.files"/> + <zipgroupfileset refid="pack.@{project}.include-jars"/> </jar> </then> <else> diff --git a/build.number b/build.number index 27d2d23041..f5c5adfc0f 100644 --- a/build.number +++ b/build.number @@ -1,9 +1,13 @@ -#Tue Sep 11 19:21:09 CEST 2007 +# The version number in this file should be the next un-released minor version, +# e.g., 2.11.7, 2.12.0, 2.12.1. It's used to determine version numbers for +# SNAPSHOT / nightly builds and local builds of source checkouts. + version.major=2 version.minor=11 version.patch=7 -# This is the -N part of a version. if it's 0, it's dropped from maven versions. + +# This is the -N part of a version (2.9.1-1). If it's 0, it's dropped from maven versions. It should not be used again. version.bnum=0 # To build a release, see scripts/jobs/scala-release-2.11.x-build -# (normally run by the eponymous job on scala-ci.typesafe.com).
\ No newline at end of file +# (normally run by the eponymous job on scala-ci.typesafe.com). diff --git a/build.sbt b/build.sbt new file mode 100644 index 0000000000..553c217d4a --- /dev/null +++ b/build.sbt @@ -0,0 +1,491 @@ +/* + * The new, sbt-based build definition for Scala. + * + * What you see below is very much work-in-progress. Basics like compiling and packaging jars + * (into right location) work. Everything else is missing: + * building docs, placing shell scripts in right locations (so you can run compiler easily), + * running partest test, compiling and running JUnit test, and many, many other things. + * + * You'll notice that this build definition is much more complicated than your typical sbt build. + * The main reason is that we are not benefiting from sbt's conventions when it comes project + * layout. For that reason we have to configure a lot more explicitly. I've tried explain in + * comments the less obvious settings. + * + * This nicely leads me to explaining goal and non-goals of this build definition. Goals are: + * + * - to be easy to tweak it in case a bug or small inconsistency is found + * - to mimic Ant's behavior as closely as possible + * - to be super explicit about any departure from standard sbt settings + * - to achieve functional parity with Ant build as quickly as possible + * - to be readable and not necessarily succinct + * - to provide the nicest development experience for people hacking on Scala + * + * Non-goals are: + * + * - to have the shortest sbt build definition possible; we'll beat Ant definition + * easily and that will thrill us already + * - to remove irregularities from our build process right away + * - to modularize the Scala compiler or library further + * + * It boils down to simple rules: + * + * - project layout is set in stone for now + * - if you need to work on convincing sbt to follow non-standard layout then + * explain everything you did in comments + * - constantly check where Ant build produces class files, artifacts, what kind of other + * files generates and port all of that to here + * + * Note on bootstrapping: + * + * Let's start with reminder what bootstrapping means in our context. It's an answer + * to this question: which version of Scala are using to compile Scala? The fact that + * the question sounds circular suggests trickiness. Indeed, bootstrapping Scala + * compiler is a tricky process. + * + * Ant build used to have involved system of bootstrapping Scala. It would consist of + * three layers: starr, locker and quick. The sbt build for Scala ditches layering + * and strives to be as standard sbt project as possible. This means that we are simply + * building Scala with latest stable release of Scala. + * See this discussion for more details behind this decision: + * https://groups.google.com/d/topic/scala-internals/gp5JsM1E0Fo/discussion + */ + +val bootstrapScalaVersion = "2.11.5" + +def withoutScalaLang(moduleId: ModuleID): ModuleID = moduleId exclude("org.scala-lang", "*") + +// exclusion of the scala-library transitive dependency avoids eviction warnings during `update`. +val scalaParserCombinatorsDep = withoutScalaLang("org.scala-lang.modules" %% "scala-parser-combinators" % versionNumber("scala-parser-combinators")) +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 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") +val jlineDep = "jline" % "jline" % versionProps("jline.version") +val antDep = "org.apache.ant" % "ant" % "1.9.4" +val scalacheckDep = withoutScalaLang("org.scalacheck" %% "scalacheck" % "1.11.4") + +lazy val commonSettings = clearSourceAndResourceDirectories ++ Seq[Setting[_]]( + organization := "org.scala-lang", + version := "2.11.6-SNAPSHOT", + scalaVersion := bootstrapScalaVersion, + // we don't cross build Scala itself + crossPaths := false, + // do not add Scala library jar as a dependency automatically + autoScalaLibrary := false, + // we also do not add scala instance automatically because it introduces + // a circular instance, see: https://github.com/sbt/sbt/issues/1872 + managedScalaInstance := false, + // this is a way to workaround issue described in https://github.com/sbt/sbt/issues/1872 + // check it out for more details + scalaInstance := ScalaInstance(scalaVersion.value, appConfiguration.value.provider.scalaProvider.launcher getScala scalaVersion.value), + // we always assume that Java classes are standalone and do not have any dependency + // on Scala classes + compileOrder := CompileOrder.JavaThenScala, + javacOptions in Compile ++= Seq("-g", "-source", "1.5", "-target", "1.6"), + // we don't want any unmanaged jars; as a reminder: unmanaged jar is a jar stored + // directly on the file system and it's not resolved through Ivy + // Ant's build stored unmanaged jars in `lib/` directory + unmanagedJars in Compile := Seq.empty, + sourceDirectory in Compile := baseDirectory.value, + unmanagedSourceDirectories in Compile := List(baseDirectory.value), + scalaSource in Compile := (sourceDirectory in Compile).value, + javaSource in Compile := (sourceDirectory in Compile).value, + // resources are stored along source files in our current layout + resourceDirectory in Compile := (sourceDirectory in Compile).value, + // each subproject has to ask specifically for files they want to include + includeFilter in unmanagedResources in Compile := NothingFilter, + target := (baseDirectory in ThisBuild).value / "target" / thisProject.value.id, + target in Compile in doc := buildDirectory.value / "scaladoc" / thisProject.value.id, + classDirectory in Compile := buildDirectory.value / "quick/classes" / thisProject.value.id, + // given that classDirectory is overriden to be _outside_ of target directory, we have + // to make sure its being cleaned properly + cleanFiles += (classDirectory in Compile).value, + fork in run := true +) + +// disable various tasks that are not needed for projects that are used +// only for compiling code and not publishing it as a standalone artifact +// we disable those tasks by overriding them and returning bogus files when +// needed. This is a bit sketchy but I haven't found any better way. +val disableDocsAndPublishingTasks = Seq[Setting[_]]( + doc := file("!!! NO DOCS !!!"), + publishLocal := {}, + publish := {}, + packageBin in Compile := file("!!! NO PACKAGING !!!") +) + +lazy val setJarLocation: Setting[_] = + artifactPath in packageBin in Compile := { + // two lines below are copied over from sbt's sources: + // https://github.com/sbt/sbt/blob/0.13/main/src/main/scala/sbt/Defaults.scala#L628 + //val resolvedScalaVersion = ScalaVersion((scalaVersion in artifactName).value, (scalaBinaryVersion in artifactName).value) + //val resolvedArtifactName = artifactName.value(resolvedScalaVersion, projectID.value, artifact.value) + // if you would like to get a jar with version number embedded in it (as normally sbt does) + // uncomment the other definition of the `resolvedArtifactName` + val resolvedArtifact = artifact.value + val resolvedArtifactName = s"${resolvedArtifact.name}.${resolvedArtifact.extension}" + buildDirectory.value / "pack/lib" / resolvedArtifactName + } +lazy val scalaSubprojectSettings: Seq[Setting[_]] = commonSettings :+ setJarLocation + +lazy val generatePropertiesFileSettings = Seq[Setting[_]]( + copyrightString := "Copyright 2002-2013, LAMP/EPFL", + resourceGenerators in Compile += generateVersionPropertiesFile.map(file => Seq(file)).taskValue, + generateVersionPropertiesFile := generateVersionPropertiesFileImpl.value +) + +val libIncludes: FileFilter = "*.tmpl" | "*.xml" | "*.js" | "*.css" | "rootdoc.txt" + +lazy val library = configureAsSubproject(project) + .settings(generatePropertiesFileSettings: _*) + .settings( + name := "scala-library", + scalacOptions in Compile ++= Seq[String]("-sourcepath", (scalaSource in Compile).value.toString), + // Workaround for a bug in `scaladoc` that it seems to not respect the `-sourcepath` option + // as a result of this bug, the compiler cannot even initialize Definitions without + // binaries of the library on the classpath. Specifically, we get this error: + // (library/compile:doc) scala.reflect.internal.FatalError: package class scala does not have a member Int + // Ant build does the same thing always: it puts binaries for documented classes on the classpath + // sbt never does this by default (which seems like a good default) + dependencyClasspath in Compile in doc += (classDirectory in Compile).value, + scalacOptions in Compile in doc ++= { + val libraryAuxDir = (baseDirectory in ThisBuild).value / "src/library-aux" + Seq("-doc-no-compile", libraryAuxDir.toString) + }, + includeFilter in unmanagedResources in Compile := libIncludes) + .dependsOn (forkjoin) + +lazy val reflect = configureAsSubproject(project) + .settings(generatePropertiesFileSettings: _*) + .settings(name := "scala-reflect") + .dependsOn(library) + +val compilerIncludes: FileFilter = + "*.tmpl" | "*.xml" | "*.js" | "*.css" | "*.html" | "*.properties" | "*.swf" | + "*.png" | "*.gif" | "*.gif" | "*.txt" + +lazy val compiler = configureAsSubproject(project) + .settings(generatePropertiesFileSettings: _*) + .settings( + name := "scala-compiler", + libraryDependencies ++= Seq(antDep, asmDep), + // this a way to make sure that classes from interactive and scaladoc projects + // end up in compiler jar (that's what Ant build does) + // we need to use LocalProject references (with strings) to deal with mutual recursion + mappings in Compile in packageBin := + (mappings in Compile in packageBin).value ++ + dependencyClasses( + (externalDependencyClasspath in Compile).value, + modules = Set(asmDep), + keep = "*.class" || "scala-asm.properties", + streams.value.cacheDirectory) ++ + (mappings in Compile in packageBin in LocalProject("interactive")).value ++ + (mappings in Compile in packageBin in LocalProject("scaladoc")).value ++ + (mappings in Compile in packageBin in LocalProject("repl")).value, + includeFilter in unmanagedResources in Compile := compilerIncludes) + .dependsOn(library, reflect) + +lazy val interactive = configureAsSubproject(project) + .settings(disableDocsAndPublishingTasks: _*) + .dependsOn(compiler) + +lazy val repl = configureAsSubproject(project) + .settings(libraryDependencies += jlineDep) + .settings(disableDocsAndPublishingTasks: _*) + .dependsOn(compiler) + +lazy val scaladoc = configureAsSubproject(project) + .settings( + libraryDependencies ++= Seq(scalaXmlDep, scalaParserCombinatorsDep, partestDep) + ) + .settings(disableDocsAndPublishingTasks: _*) + .dependsOn(compiler) + +lazy val scalap = configureAsSubproject(project). + dependsOn(compiler) + +// deprecated Scala Actors project +// TODO: it packages into actors.jar but it should be scala-actors.jar +lazy val actors = configureAsSubproject(project) + .settings(generatePropertiesFileSettings: _*) + .settings(name := "scala-actors") + .dependsOn(library) + +lazy val forkjoin = configureAsForkOfJavaProject(project) + +lazy val partestExtras = configureAsSubproject(Project("partest-extras", file(".") / "src" / "partest-extras")) + .dependsOn(repl) + .settings(clearSourceAndResourceDirectories: _*) + .settings( + libraryDependencies += partestDep, + unmanagedSourceDirectories in Compile := List(baseDirectory.value) + ) + +lazy val junit = project.in(file("test") / "junit") + .dependsOn(library, reflect, compiler, partestExtras, scaladoc) + .settings(clearSourceAndResourceDirectories: _*) + .settings(commonSettings: _*) + .settings( + fork in Test := true, + libraryDependencies ++= Seq(junitDep, junitIntefaceDep), + testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v"), + unmanagedSourceDirectories in Test := List(baseDirectory.value) + ) + +lazy val partestJavaAgent = (project in file(".") / "src" / "partest-javaagent"). + settings(commonSettings: _*). + settings( + libraryDependencies += asmDep, + doc := file("!!! NO DOCS !!!"), + publishLocal := {}, + publish := {}, + // Setting name to "scala-partest-javaagent" so that the jar file gets that name, which the Runner relies on + name := "scala-partest-javaagent", + // writing jar file to $buildDirectory/pack/lib because that's where it's expected to be found + setJarLocation, + // add required manifest entry - previously included from file + packageOptions in (Compile, packageBin) += + Package.ManifestAttributes( "Premain-Class" -> "scala.tools.partest.javaagent.ProfilingAgent" ), + // we need to build this to a JAR + exportJars := true + ) + +lazy val test = project. + dependsOn(compiler, interactive, actors, repl, scalap, partestExtras, partestJavaAgent, scaladoc). + configs(IntegrationTest). + settings(disableDocsAndPublishingTasks: _*). + settings(commonSettings: _*). + settings(Defaults.itSettings: _*). + settings( + libraryDependencies ++= Seq(asmDep, partestDep, scalaXmlDep, partestInterfaceDep, scalacheckDep), + unmanagedBase in Test := baseDirectory.value / "files" / "lib", + unmanagedJars in Test <+= (unmanagedBase) (j => Attributed.blank(j)) map(identity), + // no main sources + sources in Compile := Seq.empty, + // test sources are compiled in partest run, not here + sources in IntegrationTest := Seq.empty, + fork in IntegrationTest := true, + javaOptions in IntegrationTest += "-Xmx1G", + testFrameworks += new TestFramework("scala.tools.partest.Framework"), + testOptions in IntegrationTest += Tests.Setup( () => root.base.getAbsolutePath + "/pull-binary-libs.sh" ! ), + definedTests in IntegrationTest += ( + new sbt.TestDefinition( + "partest", + // marker fingerprint since there are no test classes + // to be discovered by sbt: + new sbt.testing.AnnotatedFingerprint { + def isModule = true + def annotationName = "partest" + }, true, Array()) + ) + ) + +lazy val root = (project in file(".")). + aggregate(library, forkjoin, reflect, compiler, interactive, repl, + scaladoc, scalap, actors, partestExtras, junit).settings( + sources in Compile := Seq.empty, + onLoadMessage := """|*** Welcome to the sbt build definition for Scala! *** + |This build definition has an EXPERIMENTAL status. If you are not + |interested in testing or working on the build itself, please use + |the Ant build definition for now. Check README.md for more information.""".stripMargin + ) + +lazy val dist = (project in file("dist")).settings( + mkBin := mkBinImpl.value +) + +/** + * Configures passed project as a subproject (e.g. compiler or repl) + * with common settings attached to it. + * + * Typical usage is: + * + * lazy val mySubproject = configureAsSubproject(project) + * + * We pass `project` as an argument which is in fact a macro call. This macro determines + * project.id based on the name of the lazy val on the left-hand side. + */ +def configureAsSubproject(project: Project): Project = { + val base = file(".") / "src" / project.id + (project in base).settings(scalaSubprojectSettings: _*) +} + +/** + * Configuration for subprojects that are forks of some Java projects + * we depend on. At the moment there's just forkjoin. + * + * We do not publish artifacts for those projects but we package their + * binaries in a jar of other project (compiler or library). + * + * For that reason we disable docs generation, packaging and publishing. + */ +def configureAsForkOfJavaProject(project: Project): Project = { + val base = file(".") / "src" / project.id + (project in base). + settings(commonSettings: _*). + settings(disableDocsAndPublishingTasks: _*). + settings( + sourceDirectory in Compile := baseDirectory.value, + javaSource in Compile := (sourceDirectory in Compile).value, + sources in Compile in doc := Seq.empty, + classDirectory in Compile := buildDirectory.value / "libs/classes" / thisProject.value.id + ) +} + +lazy val buildDirectory = settingKey[File]("The directory where all build products go. By default ./build") +lazy val copyrightString = settingKey[String]("Copyright string.") +lazy val generateVersionPropertiesFile = taskKey[File]("Generating version properties file.") +lazy val mkBin = taskKey[Seq[File]]("Generate shell script (bash or Windows batch).") + +lazy val generateVersionPropertiesFileImpl: Def.Initialize[Task[File]] = Def.task { + val propFile = (resourceManaged in Compile).value / s"${thisProject.value.id}.properties" + val props = new java.util.Properties + + /** + * 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 + } + + def executeTool(tool: String) = { + val cmd = + if (System.getProperty("os.name").toLowerCase.contains("windows")) + s"cmd.exe /c tools\\$tool.bat -p" + else s"tools/$tool" + Process(cmd).lines.head + } + + val commitDate = executeTool("get-scala-commit-date") + val commitSha = executeTool("get-scala-commit-sha") + + props.put("version.number", s"${version.value}-$commitDate-$commitSha") + props.put("maven.version.number", s"${version.value}") + props.put("osgi.version.number", s"$ver.v$commitDate$osgiSuffix-$commitSha") + props.put("copyright.string", copyrightString.value) + + // 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 + // instead of java.util.Properties + IO.write(props, null, propFile) + + propFile +} + +/** + * Extract selected dependencies to the `cacheDirectory` and return a mapping for the content. + * Heavily inspired by sbt-assembly (https://github.com/sbt/sbt-assembly/blob/0.13.0/src/main/scala/sbtassembly/Assembly.scala#L157) + */ +def dependencyClasses(dependencies: Classpath, modules: Set[ModuleID], keep: FileFilter, cacheDirectory: File): Seq[(File, String)] = { + val dependencyFiles: Seq[File] = dependencies.map(_.data).toSeq + val toInclude = dependencyFiles.filter(f => { + val p = f.getCanonicalPath + modules.exists(m => { + // works for both .m2 (org/scala-lang/modules/scala-asm/5.0.3-scala-3/scala-asm-5.0.3-scala-3.jar) + // and .ivy2 (org.scala-lang.modules/scala-asm/5.0.3-scala-3/bundles/scala-asm.jar) + val nameParts = m.organization.split('.').toSet + m.name + m.revision + nameParts.forall(p.contains) + }) + }) + assert(toInclude.forall(sbt.classpath.ClasspathUtilities.isArchive), s"Expected JAR files as dependencies: $toInclude") + + val tempDir = cacheDirectory / "unpackedDependencies" + + def sha1name(f: File): String = bytesToSha1String(f.getCanonicalPath.getBytes("UTF-8")) + def sha1content(f: File): String = bytesToSha1String(IO.readBytes(f)) + def bytesToSha1String(bytes: Array[Byte]): String = { + val sha1 = java.security.MessageDigest.getInstance("SHA-1") + val hash = sha1.digest(bytes) + hash map {"%02x".format(_)} mkString + } + + val jarDirs: Seq[File] = for (jar <- toInclude) yield { + val jarName = jar.getName + val hash = sha1name(jar) + "_" + sha1content(jar) + val jarNamePath = tempDir / (hash + ".jarName") + val dest = tempDir / hash + if (!jarNamePath.exists || IO.read(jarNamePath) != jar.getCanonicalPath) { + IO.delete(dest) + dest.mkdir() + IO.unzip(jar, dest) + IO.write(jarNamePath, jar.getCanonicalPath, IO.utf8, append = false) + } + dest + } + + jarDirs.flatMap(dir => dir ** keep --- dir pair relativeTo(dir)) +} + +// Defining these settings is somewhat redundant as we also redefine settings that depend on them. +// However, IntelliJ's project import works better when these are set correctly. +def clearSourceAndResourceDirectories = Seq(Compile, Test).flatMap(config => inConfig(config)(Seq( + unmanagedSourceDirectories := Nil, + managedSourceDirectories := Nil, + unmanagedResourceDirectories := Nil, + managedResourceDirectories := Nil +))) + +lazy val mkBinImpl: Def.Initialize[Task[Seq[File]]] = Def.task { + def mkScalaTool(mainCls: String, classpath: Seq[Attributed[File]]): ScalaTool = + ScalaTool(mainClass = mainCls, + classpath = classpath.toList.map(_.data.getAbsolutePath), + properties = Map.empty, + javaOpts = "-Xmx256M -Xms32M", + toolFlags = "") + val rootDir = (classDirectory in Compile in compiler).value + def writeScripts(scalaTool: ScalaTool, file: String, outDir: File): Seq[File] = + Seq( + scalaTool.writeScript(file, "unix", rootDir, outDir), + scalaTool.writeScript(file, "windows", rootDir, outDir) + ) + def mkQuickBin(file: String, mainCls: String, classpath: Seq[Attributed[File]]): Seq[File] = { + val scalaTool = mkScalaTool(mainCls, classpath) + val outDir = buildDirectory.value / "quick/bin" + writeScripts(scalaTool, file, outDir) + } + + def mkPackBin(file: String, mainCls: String): Seq[File] = { + val scalaTool = mkScalaTool(mainCls, classpath = Nil) + val outDir = buildDirectory.value / "pack/bin" + writeScripts(scalaTool, file, outDir) + } + + def mkBin(file: String, mainCls: String, classpath: Seq[Attributed[File]]): Seq[File] = + mkQuickBin(file, mainCls, classpath) ++ mkPackBin(file, mainCls) + + mkBin("scala" , "scala.tools.nsc.MainGenericRunner", (fullClasspath in Compile in repl).value) ++ + mkBin("scalac" , "scala.tools.nsc.Main", (fullClasspath in Compile in compiler).value) ++ + mkBin("fsc" , "scala.tools.nsc.CompileClient", (fullClasspath in Compile in compiler).value) ++ + mkBin("scaladoc" , "scala.tools.nsc.ScalaDoc", (fullClasspath in Compile in scaladoc).value) ++ + mkBin("scalap" , "scala.tools.scalap.Main", (fullClasspath in Compile in scalap).value) +} + +buildDirectory in ThisBuild := (baseDirectory in ThisBuild).value / "build-sbt" + +lazy val versionProps: Map[String, String] = { + import java.io.FileInputStream + import java.util.Properties + val props = new Properties() + val in = new FileInputStream(file("versions.properties")) + try props.load(in) + finally in.close() + import scala.collection.JavaConverters._ + props.asScala.toMap +} + +def versionNumber(name: String): String = + versionProps(s"$name.version.number") @@ -165,7 +165,6 @@ TODO: <property name="build.dir" value="${basedir}/build"/> <property name="build-deps.dir" value="${build.dir}/deps"/> <property name="build-libs.dir" value="${build.dir}/libs"/> - <property name="build-asm.dir" value="${build.dir}/asm"/> <property name="build-forkjoin.dir" value="${build-libs.dir}"/> <property name="build-locker.dir" value="${build.dir}/locker"/> <property name="build-quick.dir" value="${build.dir}/quick"/> @@ -266,6 +265,11 @@ TODO: --> <if><not><isset property="maven-deps-done"></isset></not><then> <mkdir dir="${user.home}/.m2/repository"/> + + <artifact:remoteRepository id="sonatype-release" url="https://oss.sonatype.org/content/repositories/releases"/> + <artifact:remoteRepository id="sonatype-snapshots" url="https://oss.sonatype.org/content/repositories/snapshots"/> + <artifact:remoteRepository id="extra-repo" url="${extra.repo.url}"/> + <!-- This task has an issue where if the user directory does not exist, so we create it above. UGH. --> <artifact:dependencies pathId="extra.tasks.classpath" filesetId="extra.tasks.fileset"> <dependency groupId="biz.aQute" artifactId="bnd" version="1.50.0"/> @@ -307,6 +311,36 @@ TODO: <artifact:remoteRepository id="sonatype-release" url="https://oss.sonatype.org/content/repositories/releases"/> <artifact:remoteRepository id="extra-repo" url="${extra.repo.url}"/> + <!-- scala-java8-compat, used by the experimental -target jvm-1.8 support. --> + <if><isset property="scala-java8-compat.package"/><then> + <property name="scala-java8-compat.version" value="0.5.0"/> + <property name="scala-java8-compat.binary.version" value="2.11"/> + <artifact:dependencies pathId="scala-java8-compat.classpath" filesetId="scala-java8-compat.fileset"> + <dependency groupId="org.scala-lang.modules" artifactId="scala-java8-compat_${scala-java8-compat.binary.version}" version="${scala-java8-compat.version}"> + <exclusion groupId="org.scala-lang" artifactId="scala-library"/> + </dependency> + </artifact:dependencies> + <property name="scala-java8-compat-classes" value="${build-quick.dir}/scala-java8-compat"/> + <delete dir="${scala-java8-compat-classes}"/> + <unzip dest="${scala-java8-compat-classes}"> + <fileset refid="scala-java8-compat.fileset"/> + <patternset> + <include name="**/*.class"/> + </patternset> + </unzip> + <path id="scala-java8-compat.libs"> + <pathelement location="${scala-java8-compat-classes}"/> + </path> + <fileset id="scala-java8-compat.fileset" dir="${scala-java8-compat-classes}"> + <include name="**/*"/> + </fileset> + </then> + <else> + <path id="scala-java8-compat.libs"/> + <fileset id="scala-java8-compat.fileset" dir="." excludes="**"/> + </else> + </if> + <!-- prepare, for each of the names below, the property "@{name}.cross", set to the necessary cross suffix (usually something like "_2.11.0-M6". --> <prepareCross name="scala-xml" /> @@ -318,6 +352,11 @@ TODO: <prepareCross name="partest"/> <prepareCross name="scalacheck"/> + <artifact:dependencies pathId="asm.classpath" filesetId="asm.fileset"> + <dependency groupId="org.scala-lang.modules" artifactId="scala-asm" version="${scala-asm.version}"/> + </artifact:dependencies> + <copy-deps project="asm"/> + <!-- TODO: delay until absolutely necessary to allow minimal build, also move out partest dependency from scaladoc --> <artifact:dependencies pathId="partest.classpath" filesetId="partest.fileset" versionsId="partest.versions"> <!-- uncomment the following if you're deploying your own partest locally --> @@ -471,9 +510,9 @@ TODO: <property name="sbt.lib.dir" value="${build-sbt.dir}/${sbt.latest.version}/lib"/> <property name="sbt.interface.jar" value="${sbt.lib.dir}/interface.jar"/> - <property name="sbt.interface.url" value="http://private-repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/interface/${sbt.latest.version}/jars/interface.jar"/> + <property name="sbt.interface.url" value="http://dl.bintray.com/typesafe/ivy-releases/org.scala-sbt/interface/${sbt.latest.version}/jars/interface.jar"/> <property name="sbt.interface.src.jar" value="${sbt.src.dir}/compiler-interface-src.jar"/> - <property name="sbt.interface.src.url" value="http://private-repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/compiler-interface/${sbt.latest.version}/jars/compiler-interface-src.jar"/> + <property name="sbt.interface.src.url" value="http://dl.bintray.com/typesafe/ivy-releases/org.scala-sbt/compiler-interface/${sbt.latest.version}/jars/compiler-interface-src.jar"/> <!-- Additional command line arguments for scalac. They are added to all build targets --> @@ -588,10 +627,8 @@ TODO: </propertyfile> </then></if> - <path id="forkjoin.classpath" path="${build-libs.dir}/classes/forkjoin"/> - <path id="asm.classpath" path="${build-asm.dir}/classes"/> + <path id="forkjoin.classpath" path="${build-forkjoin.dir}/classes/forkjoin"/> <property name="forkjoin-classes" refid="forkjoin.classpath"/> - <property name="asm-classes" refid="asm.classpath"/> <!-- the following properties fully define staged-docs, staged-pack, make-bundle, copy-bundle and mvn-package for each of the projects --> <property name="library.description" value="Scala Standard Library"/> @@ -658,7 +695,7 @@ TODO: <property name="partest-extras.description" value="Scala Compiler Testing Tool (compiler-specific extras)"/> <property name="partest-javaagent.description" value="Scala Compiler Testing Tool (compiler-specific java agent)"/> - <!-- projects without project-specific options: asm, forkjoin, manual, bin, repl --> + <!-- projects without project-specific options: forkjoin, manual, bin, repl --> <for list="actors,compiler,interactive,scaladoc,library,parser-combinators,partest,partest-extras,partest-javaagent,reflect,scalap,swing,xml,continuations-plugin,continuations-library" param="project"> <sequential> <!-- description is mandatory --> @@ -718,6 +755,7 @@ TODO: <pathelement location="${build-locker.dir}/classes/library"/> <path refid="forkjoin.classpath"/> <path refid="aux.libs"/> + <path refid="scala-java8-compat.libs"/> </path> <path id="locker.reflect.build.path"> @@ -739,6 +777,7 @@ TODO: <pathelement location="${build-quick.dir}/classes/library"/> <path refid="forkjoin.classpath"/> <path refid="aux.libs"/> + <path refid="scala-java8-compat.libs"/> </path> <path id="quick.actors.build.path"> @@ -827,6 +866,7 @@ TODO: <path id="pack.library.files"> <fileset dir="${build-quick.dir}/classes/library"/> <fileset dir="${forkjoin-classes}"/> + <fileset refid="scala-java8-compat.fileset"/> </path> <path id="pack.actors.files"> @@ -840,8 +880,9 @@ TODO: <fileset dir="${build-quick.dir}/classes/scaladoc"/> <fileset dir="${build-quick.dir}/classes/interactive"/> <fileset dir="${build-quick.dir}/classes/repl"/> - <fileset dir="${asm-classes}"/> </path> + <fileset id="pack.compiler.include-jars" refid="asm.fileset"/> + <property name="pack.compiler.include-jars.defined" value="yeah"/> <!-- TODO modularize compiler. <path id="pack.scaladoc.files"> <fileset dir="${build-quick.dir}/classes/scaladoc"/> </path> @@ -1040,9 +1081,9 @@ TODO: <!-- =========================================================================== CLEANLINESS =============================================================================--> - <target name="libs.clean"> <clean build="libs"/> <clean build="asm"/> </target> - <target name="quick.clean" depends="libs.clean"> <clean build="quick"/> <clean build="pack"/> <clean build="strap"/> </target> - <target name="locker.clean" depends="quick.clean"> <clean build="locker"/> </target> + <target name="libs.clean"> <clean build="libs"/> </target> + <target name="quick.clean" depends="libs.clean"> <clean build="quick"/> <clean build="pack"/> <clean build="strap"/> </target> + <target name="locker.clean" depends="quick.clean"> <clean build="locker"/> </target> <target name="docs.clean"> <clean build="docs"/> <delete dir="${build.dir}/manmaker" includeemptydirs="yes" quiet="yes" failonerror="no"/> </target> <target name="dist.clean"> <delete dir="${dists.dir}" includeemptydirs="yes" quiet="yes" failonerror="no"/> </target> @@ -1060,8 +1101,7 @@ TODO: LOCAL DEPENDENCIES ============================================================================ --> - <target name="asm.done" depends="init"> <simple-javac project="asm" jar="no"/> </target> - <target name="forkjoin.done" depends="init"> <simple-javac project="forkjoin" args="-XDignore.symbol.file"/></target> + <target name="forkjoin.done" depends="init"> <simple-javac project="forkjoin" args="-XDignore.symbol.file" jar="no"/></target> <!-- For local development only. We only allow released versions of Scala for STARR. This builds quick (core only) and publishes it with a generated version number, @@ -1083,7 +1123,7 @@ TODO: <!-- =========================================================================== LOCAL REFERENCE BUILD (LOCKER) ============================================================================ --> - <target name="locker.start" depends="asm.done, forkjoin.done"> + <target name="locker.start" depends="forkjoin.done"> <condition property="locker.locked"><available file="${build-locker.dir}/locker.locked"/></condition></target> <target name="locker.lib" depends="locker.start" unless="locker.locked"> @@ -1151,7 +1191,7 @@ TODO: <target name="pack.reflect" depends="quick.reflect"> <staged-pack project="reflect"/> </target> <!-- TODO modularize compiler. Remove other quick targets when they become modules. --> - <target name="pack.comp" depends="quick.comp, quick.scaladoc, quick.interactive, quick.repl, asm.done"> + <target name="pack.comp" depends="quick.comp, quick.scaladoc, quick.interactive, quick.repl"> <staged-pack project="compiler" manifest="${build-pack.dir}/META-INF/MANIFEST.MF"> <pre> <!-- TODO the files copied here do not influence actuality of this target (nor does the manifest) --> <copy todir="${build-pack.dir}/lib"> diff --git a/compare-build-dirs-ignore-patterns b/compare-build-dirs-ignore-patterns new file mode 100644 index 0000000000..8c8160ba15 --- /dev/null +++ b/compare-build-dirs-ignore-patterns @@ -0,0 +1,8 @@ +.DS_Store +*.complete +locker +deps +scala-continuations-*.jar +scala-parser-combinators*.jar +scala-swing*.jar +scala-xml*.jar diff --git a/compare-build-dirs.sh b/compare-build-dirs.sh new file mode 100755 index 0000000000..f6806dd422 --- /dev/null +++ b/compare-build-dirs.sh @@ -0,0 +1,5 @@ +# Compares build directories generated by Ant and sbt build definitions +# This let's us to see how far are we from achieving perfect parity +# between the builds + +diff -X compare-build-dirs-ignore-patterns -qr build/ build-sbt/ diff --git a/project/ScalaTool.scala b/project/ScalaTool.scala new file mode 100644 index 0000000000..559b215c18 --- /dev/null +++ b/project/ScalaTool.scala @@ -0,0 +1,44 @@ +import sbt._ +import org.apache.commons.lang3.StringUtils.replaceEach + +/** + * A class that generates a shell or batch script to execute a Scala program. + * + * This is a simplified copy of Ant task (see scala.tools.ant.ScalaTool). + */ +case class ScalaTool(mainClass: String, + classpath: List[String], + properties: Map[String, String], + javaOpts: String, + toolFlags: String) { + // For classpath, the platform specific + // 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) = { + val varRegex = """@(\w+)@""" // the group should be able to capture each of the keys of the map below + + val variables = Map( + ("@@" -> "@"), // for backwards compatibility + ("@class@" -> mainClass), + ("@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%") + })) + ) + + val (from, to) = variables.unzip + replaceEach(template, from.toArray, to.toArray) + } + + def writeScript(file: String, platform: String, rootDir: File, outDir: File): File = { + val templatePath = s"scala/tools/ant/templates/tool-$platform.tmpl" + val suffix = platform match { case "windows" => ".bat" case _ => "" } + val scriptFile = outDir / s"$file$suffix" + IO.write(scriptFile, patchedToolScript(IO.read(rootDir / templatePath), platform)) + scriptFile + } +} diff --git a/project/build.properties b/project/build.properties new file mode 100644 index 0000000000..748703f770 --- /dev/null +++ b/project/build.properties @@ -0,0 +1 @@ +sbt.version=0.13.7 diff --git a/project/plugins.sbt b/project/plugins.sbt new file mode 100644 index 0000000000..dc266a8db1 --- /dev/null +++ b/project/plugins.sbt @@ -0,0 +1 @@ +libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.3.2"
\ No newline at end of file diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap index d0a5b452a8..5048f3fdb9 100755 --- a/scripts/jobs/integrate/bootstrap +++ b/scripts/jobs/integrate/bootstrap @@ -1,74 +1,87 @@ #!/bin/bash -e -# TODO: different scripts for the different phases -- usually we don't need to bootstrap the modules, -# since we can use the previous version of scala for STARR as well as for compiling the modules (assuming it's binary compatible) -# We should move away from the complicated bootstrap and set up our release schedule so we always have a previous build that satisfies these criteria. -# (Potentially trivially, by splitting up this script, and publishing locker as if it were a real release.) - -# requirements: -# sbtCmd must point to sbt from sbt-extras (this is the standard on the Scala jenkins, so we only support that one) -# - ~/.sonatype-curl that consists of user = USER:PASS -# - ~/.m2/settings.xml with credentials for sonatype - # <server> - # <id>private-repo</id> - # <username>jenkinside</username> - # <password></password> - # </server> -# - ~/.credentials (for sonatype) - # realm=Sonatype Nexus Repository Manager - # host=oss.sonatype.org - # user=lamp - # password= -# - ~/.credentials-private-repo for private-repo.typesafe.com, as follows: - # realm=Artifactory Realm - # host=private-repo.typesafe.com - # user=jenkinside - # password= -# - ~/.sbt/0.13/plugins/gpg.sbt with: -# addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.1") - -# Modus operandi: -# -# Determine Scala version as: -# -# $SCALA_VER_BASE$SCALA_VER_SUFFIX (if former variable is set) -# By parsing the tag (if HEAD is tagged as v$base$suffix) -# By parsing build.number for the base version, suffixing with -$sha-nightly -# Serialize these versions to jenkins.properties, which are passed downstream to scala-release-2.11.x-dist. -# This also removes the need to tag scala/scala-dist (not possible for nightlies, still encouraged for releases, but not a hard requirement). -# -# Determine Module Versions -# -# When running in "versions.properties" mode (the default), derive tags from these versions and build, publishing only those modules that are not available yet. -# Otherwise, build HEAD for all modules, derive a -nightly version for them. -# Bootstrap: -# -# Build minimal core of Scala as this version (aka locker), publish to private-repo -# Build modules required to bootstrap, publish to private-repo -# Build Scala using the previously built core and bootstrap modules, publish to private-repo This overwrites the minimal core on private-repo -# Stage to sonatype (unless building a -nightly release): -# -# Stage this Scala build on sonatype -# Rebuild modules with this Scala build, and stage them on sonatype as well -# This script can be run in multiple modes. It is design to work without any input, -# so that it could be run in Travis CI. In that mode, it'll build a release when -# the current HEAD of the checkout in $WORKSPACE is tagged, and stage to sonatype. Otherwise, -# it'll build a nightly. + +# Script Overview +# - determine scala version +# - determine module versions +# - build minimal core (aka locker) of Scala, use the determined version number, publish to private-repo +# - build those modules where a binary compatible version doesn't exist, publish to private-repo +# - build Scala using the previously built core and bootstrap modules, publish to private-repo (overwrites the minimal core version on private-repo) +# - for releases (not nightlies) +# - stage Scala on sonatype +# - rebuild modules that needed a rebuild with this Scala build, and stage them on sonatype +# - for nightlies +# - force rebuild all modules and publish them locally (for testing purposes) +# - the Scala version is serialized to jenkins.properties, which is passed downstream to scala-release jobs +# - this removes the need to tag scala/scala-dist (it's still encouraged for releases, but not a hard requirement) + + +# Specifying the Scala version: +# - To build a release (this enables publishing to sonatype): +# - Either specify SCALA_VER_BASE. You may also specify SCALA_VER_SUFFIX, the Scala version is SCALA_VER=$SCALA_VER_BASE$SCALA_VER_SUFFIX. +# - Or have the current HEAD tagged as v$base$suffix +# - 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 + + +# Specifying module versions: there are two modes +# - If moduleVersioning="versions.properties" (default): in this mode we use release versions for the modules. +# - Module versions are read from the versions.properties file. +# - Set <MODULE>_VER to override the default, e.g. XML_VER="1.0.4". +# - The git revision is set to <MODULE>_REF="v$<MODULE>_VER". Make sure the tag exists (you can't override <MODULE>_REF). # -# Since the nightlies are intended to be a drop in replacement, all modules are built with the -# full Scala version as their binary version, so that you can just set scalaVersion to the -# nightly's sha-derived version and be good to go. +# - Otherwise (moduleVersioning has some other value): in this mode we use nightly version nubmers for modules. +# - By default the script sets all <MODULE>_REF to "HEAD", override to build a specific revision. +# - The <MODULE>_VER is set to a nightly version, for example "1.0.3-7-g14888a2-nightly" (you can't override <MODULE>_VER) + + +# Modules are automatically built if necessary. +# - A module is built if it doesn't exist in the maven repository. Note that the lookup uses two versions: +# - The version of the module (see below how it's determined) +# - The binary version of of the SCALA_VER release that is being built +# - sbt computes the binary version when looking up / building modules (*). Examples: +# - 2.12.0-M1, 2.12.0-RC3: the full version is used +# - 2.12.0, 2.12.1-M1, 2.12.1-RC3, 2.12.1: the binary version 2.12 is used # -# The other way to trigger a release is by setting the SCALA_VER_BASE env var. +# - Example: assume that `scala-xml_2.11 % 1.0.3` and `scala-xml_2.12.0-M1 % 1.0.3` both exists +# - XML_VER=1.0.3 and SCALA_VER=2.11.7 => no rebuild (binary version remains 2.11) +# - XML_VER=1.0.3 and SCALA_VER=2.12.0-M2 => rebuild (new binary version 2.12.0-M2) +# - XML_VER=1.0.4 and SCALA_VER=2.11.7 => rebuild (new version for the module, not yet on maven) +# NOTE: this is not the recommended way of publishing a module. Instead, prefer to release `scala-xml_2.11 % 1.0.4` +# using the existing scala 2.11.6 compiler before releasing 2.11.7. Sometimes it's necessary though. One +# example was 2.11.1, which contained a fix in the backend (SerialVersionUID was ignored). All modules needed +# to be re-built using the 2.11.1 release, we could not use 2.11.0. We could also not release the modules +# after 2.11.1 was out, because that way the scala-library-all pom of 2.11.1 would depend on the old modules. # -# By default, we build the versions of the modules as specified by versions.properties -# (as specified in the HEAD commit). Set moduleVersioning to something random -# to trigger building HEAD of each module, generating a fresh -$(git describe)-nightly version for each. +# (*) https://github.com/sbt/sbt/blob/0.13.8/util/cross/src/main/input_sources/CrossVersionUtil.scala#L39 + + +# Binary incompatible changes in Modules: example with Scala 2.11 / 2.12 and scala-parser-combinators +# - The 1.0.x branch on scala-parser-combinators remains binary compatible with 1.0.0 +# - Scala 2.11 will always use 1.0.x releases: we ship scala-parser-combinators with the distribution, +# so we cannot introduce incompatible changes in a minor release. +# - The master branch of scala-parser-combinators contains binary incompatible changes, versioned 1.1.x +# - Scala 2.12 will use 1.1.x releases +# - No changes to the build script required: just put the 1.1.x version number into versions.properties # -# PS: set publishToSonatype to anything but "yes" to avoid publishing to sonatype -# (publishing only done when $WORKSPACE checkout's HEAD is tagged / SCALA_VER_BASE is set.) +# Note: It's still OK for a module to release a binary incompatible version to maven, for example +# scala-parser-combinators_2.11 % 1.1.0. Users can depend on this in their sbt build. But for the +# distribution (tar/zip archives, scala-library-all) we have to stay on the binary compatible version. + + +# Requirements +# - sbtCmd 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: +# addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.1") + +# Note: private-repo used to be private-repo.typesafe.com. now we're running artifactory on scala-ci.typesafe.com/artifactory -# set to something besides the default to build nightly snapshots of the modules instead of some tagged version moduleVersioning=${moduleVersioning-"versions.properties"} publishPrivateTask=${publishPrivateTask-"publish"} @@ -78,22 +91,13 @@ publishLockerPrivateTask=${publishLockerPrivateTask-$publishPrivateTask} # set t sbtCmd=${sbtCmd-sbt} # TESTING (this is a marker for defaults to change when testing locally: should be sbtx on my mac) -# 0.13.5 does not respect "set every scalaVersion", see -# https://github.com/scala/scala-parser-combinators/pull/27 -sbtCmd="$sbtCmd -sbt-version 0.13.2" +sbtCmd="$sbtCmd -sbt-version 0.13.8" forceRebuild=${forceRebuild-no} -# publishToSonatype -# set to anything but "yes" to avoid publishing to sonatype -# overridden to "no" when no SCALA_VER_BASE is passed and HEAD is not tagged with a valid version tag -# - antBuildTask="${antBuildTask-nightly}" # TESTING leave empty to avoid the sanity check (don't set it to "init" because ant will croak) clean="clean" # TESTING leave empty to speed up testing - - baseDir=${WORKSPACE-`pwd`} scriptsDir="$baseDir/scripts" . $scriptsDir/common @@ -108,8 +112,23 @@ rm -rf $baseDir/resolutionScratch_ mkdir -p $baseDir/resolutionScratch_ # repo used to publish "locker" scala to (to start the bootstrap) -privateCred="private-repo" -privateRepo="http://private-repo.typesafe.com/typesafe/scala-release-temp/" +releaseTempRepoCred="private-repo" +releaseTempRepoUrl=${releaseTempRepoUrl-"https://scala-ci.typesafe.com/artifactory/scala-release-temp/"} +jcenterCacheUrl=${jcenterCacheUrl-"https://scala-ci.typesafe.com/artifactory/jcenter/"} + +# Used below in sbtArgs since we use a dedicated repository to share artifcacts between jobs, +# so we need to configure SBT to use these rather than its default, Maven Central. +# See http://www.scala-sbt.org/0.13/docs/Proxy-Repositories.html +sbtRepositoryConfig="$scriptsDir/repositories-scala-release" +cat > "$sbtRepositoryConfig" << EOF +[repositories] + private-repo: $releaseTempRepoUrl + jcenter-cache: $jcenterCacheUrl + typesafe-ivy-releases: https://dl.bintray.com/typesafe/ivy-releases/, [organisation]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly + sbt-plugin-releases: https://dl.bintray.com/sbt/sbt-plugin-releases/, [organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] + maven-central + local +EOF ##### git gfxd() { @@ -125,7 +144,7 @@ update() { cd $2 git fetch --tags "https://github.com/$1/$2.git" - (git fetch "https://github.com/$1/$2.git" $3 && git checkout -q FETCH_HEAD) #|| git checkout -q $3 # || fallback is for local testing on tag + (git fetch "https://github.com/$1/$2.git" $3 && git checkout -fq FETCH_HEAD) #|| git checkout -fq $3 # || fallback is for local testing on tag git reset --hard } @@ -158,7 +177,7 @@ function st_stagingRepoClose() { # the old version (on jenkins, and I don't want to upgrade for risk of breaking other builds) honors -sbt-dir # the new version of sbt-extras ignores sbt-dir, so we pass it in as -Dsbt.global.base # need to set sbt-dir to one that has the gpg.sbt plugin config -sbtArgs="-no-colors -ivy $baseDir/ivy2 -Dsbt.override.build.repos=true -Dsbt.repository.config=$scriptsDir/repositories-scala-release -Dsbt.global.base=$HOME/.sbt/0.13 -sbt-dir $HOME/.sbt/0.13" +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[@]}" "$@" @@ -168,7 +187,8 @@ sbtBuild() { sbtResolve() { cd $baseDir/resolutionScratch_ touch build.sbt - cross=${4-binary} # Disabled / binary / full + # Can be set to `full` if a module requires cross-versioning against the full Scala version, like the continuations plugin. + cross=${4-binary} echo "### sbtResolve: $sbtCmd $sbtArgs " "${scalaVersionTasks[@]}" "\"$1\" % \"$2\" % \"$3\" cross CrossVersion.$cross" $sbtCmd $sbtArgs "${scalaVersionTasks[@]}" \ "set libraryDependencies := Seq(\"$1\" % \"$2\" % \"$3\" cross CrossVersion.$cross)" \ @@ -274,18 +294,21 @@ buildActorsMigration(){ fi } +# should only be called with publishTasks publishing to private-repo buildScalacheck(){ if [ "$SCALACHECK_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scalacheck" "scalacheck" $SCALACHECK_VER ) then echo "Found scalacheck $SCALACHECK_VER; not building." else update rickynils scalacheck $SCALACHECK_REF && gfxd - sbtBuild 'set version := "'$SCALACHECK_VER'"' 'set VersionKeys.scalaParserCombinatorsVersion := "'$PARSERS_VER'"' $clean $publishPrivateTask # test times out NOTE: never published to sonatype + sbtBuild 'set version := "'$SCALACHECK_VER'"' 'set VersionKeys.scalaParserCombinatorsVersion := "'$PARSERS_VER'"' $clean publish # test times out NOTE: never published to sonatype SCALACHECK_BUILT="yes" fi } # build modules, using ${buildTasks[@]} (except for Scalacheck, which is hard-coded to publish to private-repo) buildModules() { + publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-private-repo")' "set every publishTo := Some(\"private-repo\" at \"$releaseTempRepoUrl\")") + buildTasks=($publishPrivateTask) buildXML buildParsers buildContinuations @@ -296,19 +319,62 @@ buildModules() { # buildPartestIface } +buildPublishedModules() { + publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-sonatype")' "set pgpPassphrase := Some(Array.empty)") + buildTasks=($publishSonatypeTaskModules) + buildXML + buildParsers + buildContinuations + buildSwing + buildActorsMigration + buildPartest + # buildPartestIface +} + ## BUILD STEPS: +scalaVerToBinary() { + # $1 = SCALA_VER + # $2 = SCALA_VER_BASE + # $3 = SCALA_VER_SUFFIX + + local RE='\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)' + local majMin="$(echo $2 | sed -e "s#$RE#\1.\2#")" + local patch="$(echo $2 | sed -e "s#$RE#\3#")" + + # The binary version is majMin (e.g. "2.12") if + # - there's no suffix : 2.12.0, 2.12.1 + # - the suffix starts with "-bin": 2.12.0-bin-M1 + # - the patch version is > 0 : 2.12.1-M1, 1.12.3-RC2, 2.12.1-sha-nightly, 2.12.2-SNAPSHOT + # + # Othwersise, the binary version is the full version: 2.12.0-M1, 2.12.0-RC2, 2.12.0-sha-nightly, 2.12.0-SNAPSHOT + # + # Adapted from sbt: https://github.com/sbt/sbt/blob/0.13.8/util/cross/src/main/input_sources/CrossVersionUtil.scala#L39 + # + # Note: during the pre-release cycle of a major release (e.g. before 2.12.0), the SCALA_BINARY_VER of nightly / SNAPSHOT + # versions is the full version, e.g. 2.12.0-sha-nightly, so modules are always re-built. This is in line with what sbt + # does: for example, with scalaVersion := "2.12.0-SNAPSHOT", sbt will resolve scala-xml as scala-xml_2.12.0-SNAPSHOT. + # Once the 2.12.0 release is out, the binary version is 2.12 for all versions (e.g. for 2.12.1-sha-nightly). + + if [[ "$3" == "" || "${3:0:4}" == "-bin" || "$patch" != "0" ]]; then + echo "$majMin" + else + echo "$1" + fi +} + determineScalaVersion() { cd $WORKSPACE parseScalaProperties "versions.properties" + echo "repo_ref=2.11.x" >> $baseDir/jenkins.properties # for the -dist downstream jobs that build the actual archives + + # each of the branches below defines the following vars: SCALA_VER_BASE, SCALA_VER_SUFFIX, SCALADOC_SOURCE_LINKS_VER, publishToSonatype if [ -z "$SCALA_VER_BASE" ]; then echo "No SCALA_VER_BASE specified." - scalaTag=$(git describe --exact-match ||:) - - SCALA_BINARY_VER=${SCALA_BINARY_VER-"$scala_binary_version"} + scalaTag=$(git describe --tag --exact-match ||:) if [ -z "$scalaTag" ] then @@ -318,9 +384,8 @@ determineScalaVersion() { SCALA_VER_SUFFIX="-$(git rev-parse --short HEAD)-nightly" SCALADOC_SOURCE_LINKS_VER=$(git rev-parse HEAD) - # TODO: publish nightly snapshot using this script + # TODO: publish nightly snapshot using this script - currently it's a separate jenkins job still running at EPFL. publishToSonatype="no" - echo "repo_ref=2.11.x" >> $baseDir/jenkins.properties # for the -dist downstream jobs that build the actual archives else echo "HEAD is tagged as $scalaTag." # borrowed from https://github.com/cloudflare/semver_bash/blob/master/semver.sh @@ -342,13 +407,11 @@ determineScalaVersion() { fi SCALA_VER="$SCALA_VER_BASE$SCALA_VER_SUFFIX" + SCALA_BINARY_VER=$(scalaVerToBinary $SCALA_VER $SCALA_VER_BASE $SCALA_VER_SUFFIX) + echo "version=$SCALA_VER" >> $baseDir/jenkins.properties echo "sbtDistVersionOverride=-Dproject.version=$SCALA_VER" >> $baseDir/jenkins.properties - # We don't override the scala binary version: when running in -nightly + versions.properties versioning mode, - # we intend to be a drop-in replacement -- all you need to do is change the Scala version - # In order to override this, add 'set every scalaBinaryVersion := "'$SCALA_BINARY_VER'"', - # which, when used with pre-release Scala version numbers, will require tweaking at the sbt usage site as well. scalaVersionTasks=('set every scalaVersion := "'$SCALA_VER'"') echo "Building Scala $SCALA_VER." @@ -356,19 +419,18 @@ determineScalaVersion() { deriveVersion() { update $1 $2 $3 &> /dev/null - echo "$(git describe --match=v* | cut -dv -f2)-nightly" + echo "$(git describe --tag --match=v* | cut -dv -f2)-nightly" } deriveVersionAnyTag() { update $1 $2 $3 &> /dev/null - echo "$(git describe | cut -dv -f2)-nightly" + echo "$(git describe --tag | cut -dv -f2)-nightly" } # determineScalaVersion must have been called deriveModuleVersions() { - if [ "$moduleVersioning" == "versions.properties" ] - then - # use versions.properties as defaults when no version specified on command line + if [ "$moduleVersioning" == "versions.properties" ]; then + # use versions.properties as defaults when no version specified on the command line XML_VER=${XML_VER-$scala_xml_version_number} PARSERS_VER=${PARSERS_VER-$scala_parser_combinators_version_number} CONTINUATIONS_VER=${CONTINUATIONS_VER-$scala_continuations_plugin_version_number} @@ -377,32 +439,32 @@ deriveModuleVersions() { PARTEST_VER=${PARTEST_VER-$partest_version_number} SCALACHECK_VER=${SCALACHECK_VER-$scalacheck_version_number} - # If a _VER was not specified, the corresponding _REF will be non-empty by now (as specified, or HEAD) - XML_REF=${XML_REF-"v$XML_VER"} - PARSERS_REF=${PARSERS_REF-"v$PARSERS_VER"} - CONTINUATIONS_REF=${CONTINUATIONS_REF-"v$CONTINUATIONS_VER"} - SWING_REF=${SWING_REF-"v$SWING_VER"} - ACTORS_MIGRATION_REF=${ACTORS_MIGRATION_REF-"v$ACTORS_MIGRATION_VER"} - PARTEST_REF=${PARTEST_REF-"v$PARTEST_VER"} - # PARTEST_IFACE_REF=${PARTEST_IFACE_REF-"v$PARTEST_IFACE_VER"} - SCALACHECK_REF=${SCALACHECK_REF-"$SCALACHECK_VER"} + XML_REF="v$XML_VER" + PARSERS_REF="v$PARSERS_VER" + CONTINUATIONS_REF="v$CONTINUATIONS_VER" + SWING_REF="v$SWING_VER" + ACTORS_MIGRATION_REF="v$ACTORS_MIGRATION_VER" + PARTEST_REF="v$PARTEST_VER" + # PARTEST_IFACE_REF="v$PARTEST_IFACE_VER" + SCALACHECK_REF="$SCALACHECK_VER" # no `v` in their tags else - XML_VER=${XML_VER-$(deriveVersion scala scala-xml "$XML_REF")} - PARSERS_VER=${PARSERS_VER-$(deriveVersion scala scala-parser-combinators "$PARSERS_REF")} - CONTINUATIONS_VER=${CONTINUATIONS_VER-$(deriveVersion scala scala-continuations "$CONTINUATIONS_REF")} - SWING_VER=${SWING_VER-$(deriveVersion scala scala-swing "$SWING_REF")} - ACTORS_MIGRATION_VER=${ACTORS_MIGRATION_VER-$(deriveVersion scala actors-migration "$ACTORS_MIGRATION_REF")} - PARTEST_VER=${PARTEST_VER-$(deriveVersion scala scala-partest "$PARTEST_REF")} - SCALACHECK_VER=${SCALACHECK_VER-$(deriveVersionAnyTag rickynils scalacheck "$SCALACHECK_REF")} - + # use HEAD as default when no revision is specified on the command line XML_REF=${XML_REF-"HEAD"} PARSERS_REF=${PARSERS_REF-"HEAD"} CONTINUATIONS_REF=${CONTINUATIONS_REF-"HEAD"} SWING_REF=${SWING_REF-"HEAD"} ACTORS_MIGRATION_REF=${ACTORS_MIGRATION_REF-"HEAD"} PARTEST_REF=${PARTEST_REF-"HEAD"} - # PARTEST_IFACE_REF=${PARTEST_IFACE_REF-"HEAD"} + # PARTEST_IFACE_REF=${PARTEST_IFACE_REF-"HEAD"} SCALACHECK_REF=${SCALACHECK_REF-"HEAD"} + + XML_VER=$(deriveVersion scala scala-xml "$XML_REF") + PARSERS_VER=$(deriveVersion scala scala-parser-combinators "$PARSERS_REF") + CONTINUATIONS_VER=$(deriveVersion scala scala-continuations "$CONTINUATIONS_REF") + SWING_VER=$(deriveVersion scala scala-swing "$SWING_REF") + ACTORS_MIGRATION_VER=$(deriveVersion scala actors-migration "$ACTORS_MIGRATION_REF") + PARTEST_VER=$(deriveVersion scala scala-partest "$PARTEST_REF") + SCALACHECK_VER=$(deriveVersionAnyTag rickynils scalacheck "$SCALACHECK_REF") fi echo "Module versions (versioning strategy: $moduleVersioning):" @@ -417,6 +479,29 @@ deriveModuleVersions() { # PARTEST_IFACE_VER=${PARTEST_IFACE_VER-$(deriveVersion scala scala-partest-interface "$PARTEST_IFACE_REF")} } +createNetrcFile() { + local netrcFile=$HOME/`basename $1`-netrc + grep 'host=' $1 | sed 's/host=\(.*\)/machine \1/' > $netrcFile + grep 'user=' $1 | sed 's/user=\(.*\)/login \1/' >> $netrcFile + grep 'password=' $1 | sed 's/password=\(.*\)/password \1/' >> $netrcFile +} + +removeExistingBuilds() { + createNetrcFile "$HOME/.credentials-private-repo" + local netrcFile="$HOME/.credentials-private-repo-netrc" + + local storageApiUrl=`echo $releaseTempRepoUrl | sed 's/\(scala-release-temp\)/api\/storage\/\1/'` + local scalaLangModules=`curl -s $storageApiUrl/org/scala-lang | jq -r '.children | .[] | "org/scala-lang" + .uri'` + + for module in "org/scalacheck" $scalaLangModules; do + local artifacts=`curl -s $storageApiUrl/$module | jq -r ".children | .[] | select(.uri | contains(\"$SCALA_VER\")) | .uri"` + for artifact in $artifacts; do + echo "Deleting $releaseTempRepoUrl$module$artifact" + curl -s --netrc-file $netrcFile -X DELETE $releaseTempRepoUrl$module$artifact + done + done +} + constructUpdatedModuleVersions() { updatedModuleVersions=() @@ -457,8 +542,8 @@ bootstrap() { # in sabbus lingo, the resulting Scala build will be used as starr to build the released Scala compiler ant -Dmaven.version.number=$SCALA_VER\ -Dremote.snapshot.repository=NOPE\ - -Dremote.release.repository=$privateRepo\ - -Drepository.credentials.id=$privateCred\ + -Dremote.release.repository=$releaseTempRepoUrl\ + -Drepository.credentials.id=$releaseTempRepoCred\ -Dscalac.args.optimise=-optimise\ -Ddocs.skip=1\ -Dlocker.skip=1\ @@ -471,8 +556,6 @@ bootstrap() { # publish to our internal repo (so we can resolve the modules in the scala build below) # we only need to build the modules necessary to build Scala itself # since the version of locker and quick are the same - publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-private-repo")' "set every publishTo := Some(\"private-repo\" at \"$privateRepo\")") - buildTasks=($publishPrivateTask) buildModules constructUpdatedModuleVersions @@ -496,14 +579,14 @@ bootstrap() { # which is fully cross-versioned (for $SCALA_VER, the version we're releasing) ant -Dstarr.version=$SCALA_VER\ -Dscala.full.version=$SCALA_VER\ - -Dextra.repo.url=$privateRepo\ + -Dextra.repo.url=$releaseTempRepoUrl\ -Dmaven.version.suffix=$SCALA_VER_SUFFIX\ ${updatedModuleVersions[@]} \ -Dupdate.versions=1\ -Dscaladoc.git.commit=$SCALADOC_SOURCE_LINKS_VER\ -Dremote.snapshot.repository=NOPE\ - -Dremote.release.repository=$privateRepo\ - -Drepository.credentials.id=$privateCred\ + -Dremote.release.repository=$releaseTempRepoUrl\ + -Drepository.credentials.id=$releaseTempRepoCred\ -Dscalac.args.optimise=-optimise\ $antBuildTask $publishPrivateTask @@ -529,9 +612,7 @@ publishSonatype() { # (was hoping we could make everything go to the same staging repo, but it's not timing that causes two staging repos to be opened) # NOTE: only publish those for which versions are set # test and publish to sonatype, assuming you have ~/.sbt/0.13/sonatype.sbt and ~/.sbt/0.13/plugin/gpg.sbt - publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-sonatype")' "set pgpPassphrase := Some(Array.empty)") - buildTasks=($publishSonatypeTaskModules) - buildModules + buildPublishedModules open=$(st_stagingReposOpen) allOpenUrls=$(echo $open | jq '.repositoryURI' | tr -d \") @@ -551,15 +632,10 @@ determineScalaVersion deriveModuleVersions +removeExistingBuilds + bootstrap if [ "$publishToSonatype" == "yes" ] then publishSonatype - else # build modules one more time, just to mimic the regular build as much when running as nightly - echo "### Rebuilding modules with quick, publishing to $baseDir/ivy/local" - buildTasks=(publish-local) - # buildScalacheck always uses publishPrivateTask (not buildTasks). we override it to avoid publishing to private-repo. - publishPrivateTask="publish-local" - forceRebuild="yes" - buildModules fi diff --git a/scripts/jobs/integrate/ide b/scripts/jobs/integrate/ide index 5c1e6199e3..1651ad2892 100755 --- a/scripts/jobs/integrate/ide +++ b/scripts/jobs/integrate/ide @@ -23,7 +23,7 @@ echo "maven.version.number=$scalaVersion" >> versions.properties # pass prRepoUrl in, which uber-build passes along to dbuild (in sbt-builds-for-ide) # the "-P pr-scala" maven arg accomplishes the same thing for maven (directly used in uber-build) -BASEDIR="$baseDir" prRepoUrl="$prRepoUrl" MAVEN_ARGS="-P pr-scala"\ +BASEDIR="$baseDir" prRepoUrl="$prRepoUrl" IDE_M2_REPO="$prRepoUrl" MAVEN_ARGS="-P pr-scala"\ $uberBuildDir/uber-build.sh $uberBuildDir/config/$uberBuildConfig $repo_ref $scalaVersion # uber-build puts its local repo under target/m2repo diff --git a/scripts/jobs/validate/test b/scripts/jobs/validate/test index c1c02c80cb..bedef2e458 100755 --- a/scripts/jobs/validate/test +++ b/scripts/jobs/validate/test @@ -11,7 +11,7 @@ case $prDryRun in # (in that sense it's locker, since it was built with starr by that upstream job) ant -Dstarr.version=$scalaVersion \ -Dscalac.args.optimise=-optimise \ - -Dlocker.skip=1 -Dstarr.use.released=1 -Dextra.repo.url=$prRepoUrl \ + -Dlocker.skip=1 -Dextra.repo.url=$prRepoUrl \ $testExtraArgs ${testTarget-test.core docs.done} ;; esac
\ No newline at end of file diff --git a/scripts/repositories-scala-release b/scripts/repositories-scala-release deleted file mode 100644 index 00538a08ff..0000000000 --- a/scripts/repositories-scala-release +++ /dev/null @@ -1,7 +0,0 @@ -[repositories] - plugins: http://dl.bintray.com/sbt/sbt-plugin-releases/, [organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] - private-repo: http://private-repo.typesafe.com/typesafe/scala-release-temp/ - typesafe-ivy-releases: http://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly - sbt-plugin-releases: http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] - maven-central - local
\ No newline at end of file diff --git a/spec/01-lexical-syntax.md b/spec/01-lexical-syntax.md index 3972961f58..e26cb796c8 100644 --- a/spec/01-lexical-syntax.md +++ b/spec/01-lexical-syntax.md @@ -101,19 +101,18 @@ _ : = => <- <: <% >: # @ The Unicode operators `\u21D2` ‘$\Rightarrow$’ and `\u2190` ‘$\leftarrow$’, which have the ASCII equivalents `=>` and `<-`, are also reserved. -### Example -Here are examples of identifiers: -```scala - x Object maxIndex p2p empty_? - + `yield` αρετη _y dot_product_* - __system _MAX_LEN_ -``` +> Here are examples of identifiers: +> ```scala +> x Object maxIndex p2p empty_? +> + `yield` αρετη _y dot_product_* +> __system _MAX_LEN_ +> ``` + +<!-- --> -### Example -When one needs to access Java identifiers that are reserved words in Scala, use backquote-enclosed strings. -For instance, the statement `Thread.yield()` is illegal, since -`yield` is a reserved word in Scala. However, here's a -work-around: `` Thread.`yield`() `` +> When one needs to access Java identifiers that are reserved words in Scala, use backquote-enclosed strings. +> For instance, the statement `Thread.yield()` is illegal, since `yield` is a reserved word in Scala. +> However, here's a work-around: `` Thread.`yield`() `` ## Newline Characters @@ -205,99 +204,96 @@ A single new line token is accepted - after an [infix operator](06-expressions.html#prefix,-infix,-and-postfix-operations), if the first token on the next line can start an expression, - in front of a [parameter clause](04-basic-declarations-and-definitions.html#function-declarations-and-definitions), and -- after an [annotation](11-user-defined-annotations.html#user-defined-annotations). - -### Example - -The newline tokens between the two lines are not -treated as statement separators. - -```scala -if (x > 0) - x = x - 1 - -while (x > 0) - x = x / 2 - -for (x <- 1 to 10) - println(x) - -type - IntList = List[Int] -``` - -### Example - -```scala -new Iterator[Int] -{ - private var x = 0 - def hasNext = true - def next = { x += 1; x } -} -``` - -With an additional newline character, the same code is interpreted as -an object creation followed by a local block: - -```scala -new Iterator[Int] - -{ - private var x = 0 - def hasNext = true - def next = { x += 1; x } -} -``` - -### Example - -```scala - x < 0 || - x > 10 -``` - -With an additional newline character, the same code is interpreted as -two expressions: - -```scala - x < 0 || - - x > 10 -``` - -### Example - -```scala -def func(x: Int) - (y: Int) = x + y -``` - -With an additional newline character, the same code is interpreted as -an abstract function definition and a syntactically illegal statement: - -```scala -def func(x: Int) - - (y: Int) = x + y -``` - -### Example - -```scala -@serializable -protected class Data { ... } -``` - -With an additional newline character, the same code is interpreted as -an attribute and a separate statement (which is syntactically -illegal). - -```scala -@serializable - -protected class Data { ... } -``` +- after an [annotation](11-annotations.html#user-defined-annotations). + +> The newline tokens between the two lines are not +> treated as statement separators. +> +> ```scala +> if (x > 0) +> x = x - 1 +> +> while (x > 0) +> x = x / 2 +> +> for (x <- 1 to 10) +> println(x) +> +> type +> IntList = List[Int] +> ``` + +<!-- --> + +> ```scala +> new Iterator[Int] +> { +> private var x = 0 +> def hasNext = true +> def next = { x += 1; x } +> } +> ``` +> +> With an additional newline character, the same code is interpreted as +> an object creation followed by a local block: +> +> ```scala +> new Iterator[Int] +> +> { +> private var x = 0 +> def hasNext = true +> def next = { x += 1; x } +> } +> ``` + +<!-- --> + +> ```scala +> x < 0 || +> x > 10 +> ``` +> +> With an additional newline character, the same code is interpreted as +> two expressions: +> +> ```scala +> x < 0 || +> +> x > 10 +> ``` + +<!-- --> + +> ```scala +> def func(x: Int) +> (y: Int) = x + y +> ``` +> +> With an additional newline character, the same code is interpreted as +> an abstract function definition and a syntactically illegal statement: +> +> ```scala +> def func(x: Int) +> +> (y: Int) = x + y +> ``` + +<!-- --> + +> ```scala +> @serializable +> protected class Data { ... } +> ``` +> +> With an additional newline character, the same code is interpreted as +> an attribute and a separate statement (which is syntactically illegal). +> +> ```scala +> @serializable +> +> protected class Data { ... } +> ``` ## Literals @@ -351,11 +347,9 @@ is _pt_. The numeric ranges given by these types are: |`Short` | $-2\^{15}$ to $2\^{15}-1$| |`Char` | $0$ to $2\^{16}-1$ | -### Example - -```scala -0 21 0xFFFFFFFF -42L -``` +> ```scala +> 0 21 0xFFFFFFFF -42L +> ``` ### Floating Point Literals @@ -379,20 +373,18 @@ If a floating point literal in a program is followed by a token starting with a letter, there must be at least one intervening whitespace character between the two tokens. -### Example +> ```scala +> 0.0 1e30f 3.14159f 1.0e-100 .1 +> ``` -```scala -0.0 1e30f 3.14159f 1.0e-100 .1 -``` +<!-- --> -### Example +> The phrase `1.toString` parses as three different tokens: +> the integer literal `1`, a `.`, and the identifier `toString`. -The phrase `1.toString` parses as three different tokens: -the integer literal `1`, a `.`, and the identifier `toString`. +<!-- --> -### Example - -`1.` is not a valid floating point literal because the mandatory digit after the `.` is missing. +> `1.` is not a valid floating point literal because the mandatory digit after the `.` is missing. ### Boolean Literals @@ -413,11 +405,9 @@ A character literal is a single character enclosed in quotes. The character is either a printable unicode character or is described by an [escape sequence](#escape-sequences). -### Example - -```scala -'a' '\u0041' '\n' '\t' -``` +> ```scala +> 'a' '\u0041' '\n' '\t' +> ``` Note that `'\u000A'` is _not_ a valid character literal because Unicode conversion is done before literal parsing and the Unicode @@ -439,12 +429,10 @@ contains a double quote character, it must be escaped, i.e. `"\""`. The value of a string literal is an instance of class `String`. -### Example - -```scala -"Hello,\nWorld!" -"This string contains a \" character." -``` +> ```scala +> "Hello,\nWorld!" +> "This string contains a \" character." +> ``` #### Multi-Line String Literals @@ -461,45 +449,43 @@ must not necessarily be printable; newlines or other control characters are also permitted. Unicode escapes work as everywhere else, but none of the escape sequences [here](#escape-sequences) are interpreted. -### Example - -```scala - """the present string - spans three - lines.""" -``` - -This would produce the string: - -```scala -the present string - spans three - lines. -``` - -The Scala library contains a utility method `stripMargin` -which can be used to strip leading whitespace from multi-line strings. -The expression - -```scala - """the present string - |spans three - |lines.""".stripMargin -``` - -evaluates to - -```scala -the present string -spans three -lines. -``` - -Method `stripMargin` is defined in class -[scala.collection.immutable.StringLike](http://www.scala-lang.org/api/current/#scala.collection.immutable.StringLike). -Because there is a predefined -[implicit conversion](06-expressions.html#implicit-conversions) from `String` to -`StringLike`, the method is applicable to all strings. +> ```scala +> """the present string +> spans three +> lines.""" +> ``` +> +> This would produce the string: +> +> ```scala +> the present string +> spans three +> lines. +> ``` +> +> The Scala library contains a utility method `stripMargin` +> which can be used to strip leading whitespace from multi-line strings. +> The expression +> +> ```scala +> """the present string +> |spans three +> |lines.""".stripMargin +> ``` +> +> evaluates to +> +> ```scala +> the present string +> spans three +> lines. +> ``` +> +> Method `stripMargin` is defined in class +> [scala.collection.immutable.StringLike](http://www.scala-lang.org/api/current/#scala.collection.immutable.StringLike). +> Because there is a predefined +> [implicit conversion](06-expressions.html#implicit-conversions) from `String` to +> `StringLike`, the method is applicable to all strings. ### Escape Sequences @@ -587,15 +573,13 @@ The scanner switches from XML mode to Scala mode if either Note that no Scala tokens are constructed in XML mode, and that comments are interpreted as text. -### Example - -The following value definition uses an XML literal with two embedded -Scala expressions: - -```scala -val b = <book> - <title>The Scala Language Specification</title> - <version>{scalaBook.version}</version> - <authors>{scalaBook.authors.mkList("", ", ", "")}</authors> - </book> -``` +> The following value definition uses an XML literal with two embedded +> Scala expressions: +> +> ```scala +> val b = <book> +> <title>The Scala Language Specification</title> +> <version>{scalaBook.version}</version> +> <authors>{scalaBook.authors.mkList("", ", ", "")}</authors> +> </book> +> ``` diff --git a/spec/02-identifiers-names-and-scopes.md b/spec/02-identifiers-names-and-scopes.md index 62d326934f..0a9c5dfe77 100644 --- a/spec/02-identifiers-names-and-scopes.md +++ b/spec/02-identifiers-names-and-scopes.md @@ -1,5 +1,5 @@ --- -title: Identifiers, Names and Scopes +title: Identifiers, Names & Scopes layout: default chapter: 2 --- @@ -69,7 +69,7 @@ the member of the type $T$ of $e$ which has the name $x$ in the same namespace as the identifier. It is an error if $T$ is not a [value type](03-types.html#value-types). The type of $e.x$ is the member type of the referenced entity in $T$. -### Example +###### Example Assume the following two definitions of objects named `X` in packages `P` and `Q`. diff --git a/spec/03-types.md b/spec/03-types.md index 5658e15f44..94b7916634 100644 --- a/spec/03-types.md +++ b/spec/03-types.md @@ -147,7 +147,7 @@ A qualified type designator has the form `p.t` where `p` is a [path](#paths) and _t_ is a type name. Such a type designator is equivalent to the type projection `p.type#t`. -### Example +###### Example Some type designators and their expansions are listed below. We assume a local type parameter $t$, a value `maintable` @@ -178,7 +178,8 @@ well-formed if each actual type parameter _conforms to its bounds_, i.e. $\sigma L_i <: T_i <: \sigma U_i$ where $\sigma$ is the substitution $[ a_1 := T_1 , \ldots , a_n := T_n ]$. -### Example Parameterized Types +###### Example Parameterized Types + Given the partial type definitions: ```scala @@ -202,7 +203,7 @@ F[List, Int] G[S, String] ``` -### Example +###### Example Given the [above type definitions](#example-parameterized-types), the following types are ill-formed: @@ -255,10 +256,10 @@ AnnotType ::= SimpleType {Annotation} ``` An annotated type $T$ $a_1, \ldots, a_n$ -attaches [annotations](11-user-defined-annotations.html#user-defined-annotations) +attaches [annotations](11-annotations.html#user-defined-annotations) $a_1 , \ldots , a_n$ to the type $T$. -### Example +###### Example The following type adds the `@suspendable` annotation to the type `String`: @@ -304,7 +305,7 @@ A compound type may also consist of just a refinement $\\{ R \\}$ with no preceding component types. Such a type is equivalent to `AnyRef` $\\{ R \\}$. -### Example +###### Example The following example shows how to declare and use a method which a parameter type that contains a refinement with structural declarations. @@ -500,7 +501,7 @@ or [tuple types](#tuple-types). Their expansion is then the expansion in the equivalent parameterized type. -### Example +###### Example Assume the class definitions @@ -524,7 +525,7 @@ An alternative formulation of the first type above using wildcard syntax is: Ref[_ <: java.lang.Number] ``` -### Example +###### Example The type `List[List[_]]` is equivalent to the existential type @@ -532,7 +533,7 @@ The type `List[List[_]]` is equivalent to the existential type List[List[t] forSome { type t }] . ``` -### Example +###### Example Assume a covariant type @@ -658,7 +659,7 @@ same name, we model An overloaded type consisting of type alternatives $T_1 \commadots T_n (n \geq 2)$ is denoted internally $T_1 \overload \ldots \overload T_n$. -### Example +###### Example ``` def println: Unit def println(s: String): Unit = $\ldots$ @@ -676,7 +677,7 @@ println: => Unit $\overload$ [A] (A) (A => String) Unit ``` -### Example +###### Example ``` def f(x: T): T = $\ldots$ val f = 0 @@ -834,8 +835,7 @@ transitive relation that satisfies the following conditions. - For every type constructor $T$ (with any number of type parameters), `scala.Nothing <: $T$ <: scala.Any`. -- For every class type $T$ such that `$T$ <: scala.AnyRef` and not - `$T$ <: scala.NotNull` one has `scala.Null <: $T$`. +- For every class type $T$ such that `$T$ <: scala.AnyRef` one has `scala.Null <: $T$`. - A type variable or abstract type $t$ conforms to its upper bound and its lower bound conforms to $t$. - A class type or parameterized type conforms to any of its base-types. diff --git a/spec/04-basic-declarations-and-definitions.md b/spec/04-basic-declarations-and-definitions.md index 65d79dd5f4..7fb5427d36 100644 --- a/spec/04-basic-declarations-and-definitions.md +++ b/spec/04-basic-declarations-and-definitions.md @@ -1,5 +1,5 @@ --- -title: Basic Declarations and Definitions +title: Basic Declarations & Definitions layout: default chapter: 4 --- @@ -563,7 +563,7 @@ abstract class Sequence[+A] { } ``` -### Example +###### Example ```scala abstract class OutputChannel[-A] { diff --git a/spec/05-classes-and-objects.md b/spec/05-classes-and-objects.md index 8681c93193..8be792d3cb 100644 --- a/spec/05-classes-and-objects.md +++ b/spec/05-classes-and-objects.md @@ -1,5 +1,5 @@ --- -title: Classes and Objects +title: Classes & Objects layout: default chapter: 5 --- @@ -368,7 +368,7 @@ it is possible to add new defaults (if the corresponding parameter in the superclass does not have a default) or to override the defaults of the superclass (otherwise). -### Example +###### Example Consider the definitions: @@ -395,6 +395,7 @@ class C extends A with B { type T <: C } Let $C$ be a class type. The _inheritance closure_ of $C$ is the smallest set $\mathscr{S}$ of types such that +- $C$ is in $\mathscr{S}$. - If $T$ is in $\mathscr{S}$, then every type $T'$ which forms syntactically a part of $T$ is also in $\mathscr{S}$. - If $T$ is a class type in $\mathscr{S}$, then all [parents](#templates) @@ -498,9 +499,7 @@ the validity and meaning of a modifier are as follows. The `private` modifier can be used with any definition or declaration in a template. Such members can be accessed only from within the directly enclosing template and its companion module or -[companion class](#object-definitions). They -are not inherited by subclasses and they may not override definitions -in parent classes. +[companion class](#object-definitions). The modifier can be _qualified_ with an identifier $C$ (e.g. `private[$C$]`) that must denote a class or package @@ -524,7 +523,8 @@ either class-private or object-private, but not if it is marked case the member is called _qualified private_. Class-private or object-private members may not be abstract, and may -not have `protected` or `override` modifiers. +not have `protected` or `override` modifiers. They are not inherited +by subclasses and they may not override definitions in parent classes. ### `protected` The `protected` modifier applies to class member definitions. @@ -699,7 +699,7 @@ Here, parameter section is called _polymorphic_, otherwise it is called _monomorphic_. - $as$ is a possibly empty sequence of - [annotations](11-user-defined-annotations.html#user-defined-annotations). + [annotations](11-annotations.html#user-defined-annotations). If any annotations are given, they apply to the primary constructor of the class. - $m$ is an [access modifier](#modifiers) such as @@ -744,7 +744,7 @@ which when applied to parameters conforming to types $\mathit{ps}$ initializes instances of type `$c$[$\mathit{tps}\,$]` by evaluating the template $t$. -### Example +###### Example The following example illustrates `val` and `var` parameters of a class `C`: ```scala @@ -990,7 +990,7 @@ it is not statically known at the time the trait is defined. If $D$ is not a trait, then its actual supertype is simply its least proper supertype (which is statically known). -### Example +###### Example The following trait defines the property of being comparable to objects of some type. It contains an abstract method `<` and default implementations of the other diff --git a/spec/06-expressions.md b/spec/06-expressions.md index 133ec3c8e5..85e288bf5f 100644 --- a/spec/06-expressions.md +++ b/spec/06-expressions.md @@ -148,10 +148,6 @@ The selection $e.x$ is evaluated by first evaluating the qualifier expression $e$, which yields an object $r$, say. The selection's result is then the member of $r$ that is either defined by $m$ or defined by a definition overriding $m$. -If that member has a type which -conforms to `scala.NotNull`, the member's value must be initialized -to a value different from `null`, otherwise a `scala.UnitializedError` -is thrown. ## This and Super @@ -205,7 +201,7 @@ to the type or method of $x$ in the parent trait of $C$ whose simple name is $T$. That member must be uniquely defined. If it is a method, it must be concrete. -### Example +###### Example Consider the following class definitions ```scala @@ -516,7 +512,7 @@ In the latter case, the concrete self type of the expression is the compound type `$T$ with $x$.type`. The expression is evaluated by creating a fresh -object of type $T$ which is is initialized by evaluating $c$. The +object of type $T$ which is initialized by evaluating $c$. The type of the expression is $T$. A general instance creation expression is of the form @@ -778,7 +774,7 @@ Expr1 ::= PostfixExpr `:' Annotation {Annotation} ``` An annotated expression `$e$: @$a_1$ $\ldots$ @$a_n$` -attaches [annotations](11-user-defined-annotations.html#user-defined-annotations) $a_1 , \ldots , a_n$ to the +attaches [annotations](11-annotations.html#user-defined-annotations) $a_1 , \ldots , a_n$ to the expression $e$. ## Assignments @@ -815,7 +811,7 @@ Here are some assignment expressions and their equivalent expansions. |`x.f(i) = e` | `x.f.update(i, e)` | |`x.f(i, j) = e` | `x.f.update(i, j, e)`| -### Example Imperative Matrix Multiplication +###### Example Imperative Matrix Multiplication Here is the usual imperative code for matrix multiplication. @@ -1221,9 +1217,9 @@ In that case, a fresh name for the parameter is chosen arbitrarily. A named parameter of an anonymous function may be optionally preceded by an `implicit` modifier. In that case the parameter is -labeled [`implicit`](07-implicit-parameters-and-views.html#implicit-parameters-and-views); however the +labeled [`implicit`](07-implicits.html#implicit-parameters-and-views); however the parameter section itself does not count as an implicit parameter -section in the sense defined [here](07-implicit-parameters-and-views.html#implicit-parameters). Hence, arguments to +section in the sense defined [here](07-implicits.html#implicit-parameters). Hence, arguments to anonymous functions always have to be given explicitly. ###### Example @@ -1341,7 +1337,7 @@ available implicit conversions are given in the next two sub-sections. We say, a type $T$ is _compatible_ to a type $U$ if $T$ weakly conforms to $U$ after applying [eta-expansion](#eta-expansion) and -[view applications](07-implicit-parameters-and-views.html#views). +[view applications](07-implicits.html#views). ### Value Conversions @@ -1389,7 +1385,7 @@ term `{ $e$; () }`. ###### View Application If none of the previous conversions applies, and $e$'s type does not conform to the expected type $\mathit{pt}$, it is attempted to convert -$e$ to the expected type with a [view](07-implicit-parameters-and-views.html#views). +$e$ to the expected type with a [view](07-implicits.html#views). ###### Dynamic Member Selection If none of the previous conversions applies, and $e$ is a prefix @@ -1408,7 +1404,7 @@ type $T$ by evaluating the expression to which $m$ is bound. ###### Implicit Application If the method takes only implicit parameters, implicit -arguments are passed following the rules [here](07-implicit-parameters-and-views.html#implicit-parameters). +arguments are passed following the rules [here](07-implicits.html#implicit-parameters). ###### Eta Expansion Otherwise, if the method is not a constructor, diff --git a/spec/07-implicit-parameters-and-views.md b/spec/07-implicits.md index 27a50cf058..5e10373959 100644 --- a/spec/07-implicit-parameters-and-views.md +++ b/spec/07-implicits.md @@ -1,10 +1,10 @@ --- -title: Implicit Parameters and Views +title: Implicits layout: default chapter: 7 --- -# Implicit Parameters and Views +# Implicits ## The Implicit Modifier @@ -19,7 +19,8 @@ and can be used as implicit conversions called [views](#views). The `implicit` modifier is illegal for all type members, as well as for [top-level objects](09-top-level-definitions.html#packagings). -### Example Monoid +###### Example Monoid + The following code defines an abstract class of monoids and two concrete implementations, `StringMonoid` and `IntMonoid`. The two implementations are marked implicit. @@ -180,7 +181,7 @@ To prevent such infinite expansions, the compiler keeps track of a stack of “open implicit types” for which implicit arguments are currently being searched. Whenever an implicit argument for type $T$ is searched, the “core type” of $T$ is added to the stack. Here, the _core type_ -of $T$ is $T$ with aliases expanded, top-level type [annotations](11-user-defined-annotations.html#user-defined-annotations) and +of $T$ is $T$ with aliases expanded, top-level type [annotations](11-annotations.html#user-defined-annotations) and [refinements](03-types.html#compound-types) removed, and occurrences of top-level existentially bound variables replaced by their upper bounds. The core type is removed from the stack once the search for @@ -284,7 +285,8 @@ As for implicit parameters, overloading resolution is applied if there are several possible candidates (of either the call-by-value or the call-by-name category). -### Example Ordered +###### Example Ordered + Class `scala.Ordered[A]` contains a method ```scala diff --git a/spec/08-pattern-matching.md b/spec/08-pattern-matching.md index e75bddc096..c494fbcef5 100644 --- a/spec/08-pattern-matching.md +++ b/spec/08-pattern-matching.md @@ -371,7 +371,7 @@ bound type variables in a typed pattern or constructor pattern. Inference takes into account the expected type of the pattern. -### Type parameter inference for typed patterns. +### Type parameter inference for typed patterns Assume a typed pattern $p: T'$. Let $T$ result from $T'$ where all wildcards in $T'$ are renamed to fresh variable names. Let $a_1 , \ldots , a_n$ be @@ -437,7 +437,7 @@ complexity of inferred bounds. Minimality and maximality of types have to be understood relative to the set of types of acceptable complexity. -#### Type parameter inference for constructor patterns. +### Type parameter inference for constructor patterns Assume a constructor pattern $C(p_1 , \ldots , p_n)$ where class $C$ has type type parameters $a_1 , \ldots , a_n$. These type parameters are inferred in the same way as for the typed pattern @@ -593,7 +593,7 @@ the compilation of pattern matching can emit warnings which diagnose that a given set of patterns is not exhaustive, i.e. that there is a possibility of a `MatchError` being raised at run-time. -### Example +###### Example Consider the following definitions of arithmetic terms: diff --git a/spec/09-top-level-definitions.md b/spec/09-top-level-definitions.md index e3185d8b7d..b8a8dc7e0a 100644 --- a/spec/09-top-level-definitions.md +++ b/spec/09-top-level-definitions.md @@ -151,7 +151,7 @@ contain a class `B`, a compiler-time error would result. A _program_ is a top-level object that has a member method _main_ of type `(Array[String])Unit`. Programs can be -executed from a command shell. The program's command arguments are are +executed from a command shell. The program's command arguments are passed to the `main` method as a parameter of type `Array[String]`. diff --git a/spec/10-xml-expressions-and-patterns.md b/spec/10-xml-expressions-and-patterns.md index 407b2b9a67..b70fb86471 100644 --- a/spec/10-xml-expressions-and-patterns.md +++ b/spec/10-xml-expressions-and-patterns.md @@ -1,5 +1,5 @@ --- -title: XML Expressions and Patterns +title: XML layout: default chapter: 10 --- diff --git a/spec/11-user-defined-annotations.md b/spec/11-annotations.md index 2c5830c103..d66f24abf8 100644 --- a/spec/11-user-defined-annotations.md +++ b/spec/11-annotations.md @@ -1,17 +1,19 @@ --- -title: User-Defined Annotations +title: Annotations layout: default chapter: 11 --- -# User-Defined Annotations +# Annotations ```ebnf Annotation ::= ‘@’ SimpleType {ArgumentExprs} ConstrAnnotation ::= ‘@’ SimpleType ArgumentExprs ``` -User-defined annotations associate meta-information with definitions. +## Definition + +Annotations associate meta-information with definitions. A simple annotation has the form `@$c$` or `@$c(a_1 , \ldots , a_n)$`. Here, $c$ is a constructor of a class $C$, which must conform to the class `scala.Annotation`. @@ -33,6 +35,10 @@ String @local // Type annotation (e: @unchecked) match { ... } // Expression annotation ``` +## Predefined Annotations + +### Java Platform Annotations + The meaning of annotation clauses is implementation-dependent. On the Java platform, the following annotations have a standard meaning. @@ -61,7 +67,7 @@ Java platform, the following annotations have a standard meaning. clause for the method or constructor must mention the class of that exception or one of the superclasses of the class of that exception. -## Java Beans Annotations +### Java Beans Annotations * `@scala.beans.BeanProperty` When prefixed to a definition of some variable `X`, this annotation causes getter and setter methods `getX`, `setX` @@ -76,18 +82,21 @@ Java platform, the following annotations have a standard meaning. * `@scala.beans.BooleanBeanProperty` This annotation is equivalent to `scala.reflect.BeanProperty`, but the generated getter method is named `isX` instead of `getX`. -## Deprecation Annotations +### Deprecation Annotations - * `@deprecated(<stringlit>)` Marks a definition as deprecated. Accesses to the + * `@deprecated(message: <stringlit>, since: <stringlit>)`<br/> + Marks a definition as deprecated. Accesses to the defined entity will then cause a deprecated warning mentioning the - message `<stringlit>` to be issued from the compiler. Deprecated - warnings are suppressed in code that belongs itself to a definition + _message_ `<stringlit>` to be issued from the compiler. + The argument _since_ documents since when the definition should be considered deprecated.<br/> + Deprecated warnings are suppressed in code that belongs itself to a definition that is labeled deprecated. - * `@deprecatedName(name: <symbollit>)` Marks a formal parameter name as deprecated. Invocations of this entity + * `@deprecatedName(name: <symbollit>)`<br/> + Marks a formal parameter name as deprecated. Invocations of this entity using named parameter syntax refering to the deprecated parameter name cause a deprecation warning. -## Scala Compiler Annotations +### Scala Compiler Annotations * `@unchecked` When applied to the selector of a `match` expression, this attribute suppresses any warnings about non-exhaustive pattern @@ -141,6 +150,8 @@ Java platform, the following annotations have a standard meaning. a definition, the compiler will instead use the specialized version. See the [specialization sid](http://docs.scala-lang.org/sips/completed/scala-specialization.html) for more details of the implementation. +## User-defined Annotations + Other annotations may be interpreted by platform- or application-dependent tools. Class `scala.Annotation` has two sub-traits which are used to indicate how these annotations are diff --git a/spec/12-the-scala-standard-library.md b/spec/12-the-scala-standard-library.md index 988d9804ec..e76035f458 100644 --- a/spec/12-the-scala-standard-library.md +++ b/spec/12-the-scala-standard-library.md @@ -1,5 +1,5 @@ --- -title: The Scala Standard Library +title: Standard Library layout: default chapter: 12 --- @@ -233,7 +233,7 @@ for type `Int` and for all subrange types. The `toString` method displays its receiver as an integer or floating point number. -### Example +###### Example This is the signature of the numeric value type `Int`: @@ -332,7 +332,7 @@ The `toString` method returns `"()"`. ## Standard Reference Classes This section presents some standard Scala reference classes which are -treated in a special way by the Scala compiler -- either Scala provides +treated in a special way by the Scala compiler – either Scala provides syntactic sugar for them, or the Scala compiler generates special code for their operations. Other classes in the standard Scala library are documented in the Scala library documentation by HTML pages. diff --git a/spec/13-syntax-summary.md b/spec/13-syntax-summary.md index 2b9571cc73..7f73e107de 100644 --- a/spec/13-syntax-summary.md +++ b/spec/13-syntax-summary.md @@ -15,6 +15,8 @@ UnicodeEscape ::= ‘\‘ ‘u‘ {‘u‘} hexDigit hexDigit hexDigit hexDigit hexDigit ::= ‘0’ | … | ‘9’ | ‘A’ | … | ‘F’ | ‘a’ | … | ‘f’ ``` +## Lexical Syntax + The lexical syntax of Scala is given by the following grammar in EBNF form: ```ebnf @@ -72,8 +74,10 @@ nl ::= $\mathit{“new line character”}$ semi ::= ‘;’ | nl {nl} ``` +## Context-free Syntax + The context-free syntax of Scala is given by the following EBNF -grammar. +grammar: ```ebnf Literal ::= [‘-’] integerLiteral diff --git a/spec/15-changelog.md b/spec/15-changelog.md new file mode 100644 index 0000000000..54310c921c --- /dev/null +++ b/spec/15-changelog.md @@ -0,0 +1,823 @@ +--- +title: Changelog +layout: default +chapter: 15 +--- + +# Changelog + +Changes in Version 2.8.0 +------------------------ + +#### Trailing commas + +Trailing commas in expression, argument, type or pattern sequences are +no longer supported. + +Changes in Version 2.8 +---------------------- + +Changed visibility rules for nested packages (where done?) + +Changed [visibility rules](02-identifiers-names-and-scopes.html) +so that packages are no longer treated specially. + +Added section on [weak conformance](03-types.html#weak-conformance). +Relaxed type rules for conditionals, +match expressions, try expressions to compute their result type using +least upper bound wrt weak conformance. Relaxed type rule for local type +inference so that argument types need only weekly conform to inferred +formal parameter types. Added section on +[numeric widening](06-expressions.html#numeric-widening) to support +weak conformance. + +Tightened rules to avoid accidential [overrides](05-classes-and-objects.html#overriding). + +Removed class literals. + +Added section on [context bounds](07-implicits.html#context-bounds-and-view-bounds). + +Clarified differences between [`isInstanceOf` and pattern matches](12-the-scala-standard-library.html#root-classes). + +Allowed [`implicit` modifier on function literals](06-expressions.html#anonymous-functions) with a single parameter. + +Changes in Version 2.7.2 +------------------------ + +_(10-Nov-2008)_ + +#### Precedence of Assignment Operators + +The [precedence of assignment operators](06-expressions.html#prefix,-infix,-and-postfix-operations) +has been brought in line with. From now on `+=`, has the same precedence as `=`. + +#### Wildcards as function parameters + +A formal parameter to an anonymous fucntion may now be a +[wildcard represented by an underscore](06-expressions.html#placeholder-syntax-for-anonymous-functions). + +> _ => 7 // The function that ignores its argument +> // and always returns 7. + +#### Unicode alternative for left arrow + +The Unicode glyph ‘\\(\leftarrow\\)’ \\(`\u2190`\\) is now treated as a reserved +identifier, equivalent to the ASCII symbol ‘`<-`’. + +Changes in Version 2.7.1 +------------------------ + +_(09-April-2008)_ + +#### Change in Scoping Rules for Wildcard Placeholders in Types + +A wildcard in a type now binds to the closest enclosing type +application. For example `List[List[_]]` is now equivalent to this +existential type: + + List[List[t] forSome { type t }] + +In version 2.7.0, the type expanded instead to: + + List[List[t]] forSome { type t } + +The new convention corresponds exactly to the way wildcards in Java are +interpreted. + +#### No Contractiveness Requirement for Implicits + +The contractiveness requirement for +[implicit method definitions](07-implicits.html#implicit-parameters) +has been dropped. Instead it is checked for each implicit expansion individually +that the expansion does not result in a cycle or a tree of infinitely +growing types. + +Changes in Version 2.7.0 +------------------------ + +_(07-Feb-2008)_ + +#### Java Generics + +Scala now supports Java generic types by default: + +- A generic type in Java such as `ArrayList<String>` is translated to + a generic type in Scala: `ArrayList[String]`. + +- A wildcard type such as `ArrayList<? extends Number>` is translated + to `ArrayList[_ <: Number]`. This is itself a shorthand for the + existential type `ArrayList[T] forSome { type T <: Number }`. + +- A raw type in Java such as `ArrayList` is translated to + `ArrayList[_]`, which is a shorthand for + `ArrayList[T] forSome { type T }`. + +This translation works if `-target:jvm-1.5` is specified, which is the +new default. For any other target, Java generics are not recognized. To +ensure upgradability of Scala codebases, extraneous type parameters for +Java classes under `-target:jvm-1.4` are simply ignored. For instance, +when compiling with `-target:jvm-1.4`, a Scala type such as +`ArrayList[String]` is simply treated as the unparameterized type +`ArrayList`. + +#### Changes to Case Classes + +The Scala compiler generates now for every case class a companion +extractor object (). For instance, given the case class: + + case class X(elem: String) + +the following companion object is generated: + + object X { + def unapply(x: X): Some[String] = Some(x.elem) + def apply(s: String): X = new X(s) + } + +If the object exists already, only the `apply` and `unapply` methods are +added to it. + +Three restrictions on case classes have been removed. + +1. Case classes can now inherit from other case classes. + +2. Case classes may now be `abstract`. + +3. Case classes may now come with companion objects. + +Changes in Version 2.6.1 +------------------------ + +_(30-Nov-2007)_ + +#### Mutable variables introduced by pattern binding + +Mutable variables can now be introduced by a pattern matching definition +(), just like values can. Examples: + + var (x, y) = if (positive) (1, 2) else (-1, -3) + var hd :: tl = mylist + +#### Self-types + +Self types can now be introduced without defining an alias name for +`this` (). Example: + + class C { + type T <: Trait + trait Trait { this: T => ... } + } + +Changes in Version 2.6 +---------------------- + +_(27-July-2007)_ + +#### Existential types + +It is now possible to define existential types (). An existential type +has the form `T forSome {Q}` where `Q` is a sequence of value and/or +type declarations. Given the class definitions + + class Ref[T] + abstract class Outer { type T } + +one may for example write the following existential types + + Ref[T] forSome { type T <: java.lang.Number } + Ref[x.T] forSome { val x: Outer } + +#### Lazy values + +It is now possible to define lazy value declarations using the new +modifier `lazy` (). A `lazy` value definition evaluates its right hand +side \\(e\\) the first time the value is accessed. Example: + + import compat.Platform._ + val t0 = currentTime + lazy val t1 = currentTime + val t2 = currentTime + + println("t0 <= t2: " + (t0 <= t2)) //true + println("t1 <= t2: " + (t1 <= t2)) //false (lazy evaluation of t1) + +#### Structural types + +It is now possible to declare structural types using type refinements +(). For example: + + class File(name: String) { + def getName(): String = name + def open() { /*..*/ } + def close() { println("close file") } + } + def test(f: { def getName(): String }) { println(f.getName) } + + test(new File("test.txt")) + test(new java.io.File("test.txt")) + +There’s also a shorthand form for creating values of structural types. +For instance, + + new { def getName() = "aaron" } + +is a shorthand for + + new AnyRef{ def getName() = "aaron" } + +Changes in Version 2.5 +---------------------- + +_(02-May-2007)_ + +#### Type constructor polymorphism[^1] + +Type parameters () and abstract type members () can now also abstract +over type constructors (). + +This allows a more precise `Iterable` interface: + + trait Iterable[+T] { + type MyType[+T] <: Iterable[T] // MyType is a type constructor + + def filter(p: T => Boolean): MyType[T] = ... + def map[S](f: T => S): MyType[S] = ... + } + + abstract class List[+T] extends Iterable[T] { + type MyType[+T] = List[T] + } + +This definition of `Iterable` makes explicit that mapping a function +over a certain structure (e.g., a `List`) will yield the same structure +(containing different elements). + +#### Early object initialization + +It is now possible to initialize some fields of an object before any +parent constructors are called (). This is particularly useful for +traits, which do not have normal constructor parameters. Example: + + trait Greeting { + val name: String + val msg = "How are you, "+name + } + class C extends { + val name = "Bob" + } with Greeting { + println(msg) + } + +In the code above, the field is initialized before the constructor of is +called. Therefore, field `msg` in class is properly initialized to . + +#### For-comprehensions, revised + +The syntax of for-comprehensions has changed (). In the new syntax, +generators do not start with a anymore, but filters start with an (and +are called guards). A semicolon in front of a guard is optional. For +example: + + for (val x <- List(1, 2, 3); x % 2 == 0) println(x) + +is now written + + for (x <- List(1, 2, 3) if x % 2 == 0) println(x) + +The old syntax is still available but will be deprecated in the future. + +#### Implicit anonymous functions + +It is now possible to define anonymous functions using underscores in +parameter position (). For instance, the expressions in the left column +are each function values which expand to the anonymous functions on +their right. + + _ + 1 x => x + 1 + _ * _ (x1, x2) => x1 * x2 + (_: int) * 2 (x: int) => (x: int) * 2 + if (_) x else y z => if (z) x else y + _.map(f) x => x.map(f) + _.map(_ + 1) x => x.map(y => y + 1) + +As a special case (), a partially unapplied method is now designated + `m _` instead of the previous notation `&m`. + +The new notation will displace the special syntax forms `.m()` for +abstracting over method receivers and `&m` for treating an unapplied +method as a function value. For the time being, the old syntax forms are +still available, but they will be deprecated in the future. + +#### Pattern matching anonymous functions, refined + +It is now possible to use case clauses to define a function value +directly for functions of arities greater than one (). Previously, only +unary functions could be defined that way. Example: + + def scalarProduct(xs: Array[Double], ys: Array[Double]) = + (0.0 /: (xs zip ys)) { + case (a, (b, c)) => a + b * c + } + +Changes in Version 2.4 +---------------------- + +_(09-Mar-2007)_ + +#### Object-local private and protected + +The `private` and `protected` modifiers now accept a `[this]` qualifier +(). A definition \\(M\\) which is labelled `private[this]` is private, +and in addition can be accessed only from within the current object. +That is, the only legal prefixes for \\(M\\) are `this` or `$C$.this`. +Analogously, a definition \\(M\\) which is labelled `protected[this]` is +protected, and in addition can be accessed only from within the current +object. + +#### Tuples, revised + +The syntax for [tuples](06-expressions.html#tuples) has been changed from \\(\\{…\\}\\) to +\\((…)\\). For any sequence of types \\(T_1 , … , T_n\\), + +\\((T_1 , … , T_n)\\) is a shorthand for `Tuple$n$[$T_1 , … , T_n$]`. + +Analogously, for any sequence of expressions or patterns \\(x_1 +, … , x_n\\), + +\\((x_1 , … , x_n)\\) is a shorthand for `Tuple$n$($x_1 , … , x_n$)`. + +#### Access modifiers for primary constructors + +The primary constructor of a class can now be marked or (). If such an +access modifier is given, it comes between the name of the class and its +value parameters. Example: + + class C[T] private (x: T) { ... } + +#### Annotations + +The support for attributes has been extended and its syntax changed (). +Attributes are now called <span>*annotations*</span>. The syntax has +been changed to follow Java’s conventions, e.g. `@attribute` instead of +`[attribute]`. The old syntax is still available but will be deprecated +in the future. + +Annotations are now serialized so that they can be read by compile-time +or run-time tools. Class has two sub-traits which are used to indicate +how annotations are retained. Instances of an annotation class +inheriting from trait will be stored in the generated class files. +Instances of an annotation class inheriting from trait will be visible +to the Scala type-checker in every compilation unit where the annotated +symbol is accessed. + +#### Decidable subtyping + +The implementation of subtyping has been changed to prevent infinite +recursions. Termination of subtyping is now ensured by a new restriction +of class graphs to be finitary (). + +#### Case classes cannot be abstract + +It is now explicitly ruled out that case classes can be abstract (). The +specification was silent on this point before, but did not explain how +abstract case classes were treated. The Scala compiler allowed the +idiom. + +#### New syntax for self aliases and self types + +It is now possible to give an explicit alias name and/or type for the +self reference (). For instance, in + + class C { self: D => + ... + } + +the name is introduced as an alias for within and the self type () of is +assumed to be . This construct is introduced now in order to replace +eventually both the qualified this construct and the clause in Scala. + +#### Assignment Operators + +It is now possible to combine operators with assignments (). Example: + + var x: int = 0 + x += 1 + +Changes in Version 2.3.2 +------------------------ + +_(23-Jan-2007)_ + +#### Extractors + +It is now possible to define patterns independently of case classes, +using methods in extractor objects (). Here is an example: + + object Twice { + def apply(x:Int): int = x*2 + def unapply(z:Int): Option[int] = if (z%2==0) Some(z/2) else None + } + val x = Twice(21) + x match { case Twice(n) => Console.println(n) } // prints 21 + +In the example, `Twice` is an extractor object with two methods: + +- The method is used to build even numbers. + +- The method is used to decompose an even number; it is in a sense the + reverse of . `unapply` methods return option types: for a match that + suceeds, for a match that fails. Pattern variables are returned as + the elements of . If there are several variables, they are grouped + in a tuple. + +In the second-to-last line, ’s method is used to construct a number . In +the last line, is tested against the pattern . This pattern succeeds for +even numbers and assigns to the variable one half of the number that was +tested. The pattern match makes use of the method of object . More +details on extractors can be found in the paper “Matching Objects with +Patterns” by Emir, Odersky and Williams. + +#### Tuples + +A new lightweight syntax for tuples has been introduced (). For any +sequence of types \\(T_1 , … , T_n\\), + +\\(\{T_1 , … , T_n \}\\) is a shorthand for `Tuple$n$[$T_1 , … , T_n$]`. + +Analogously, for any sequence of expressions or patterns \\(x_1, … , x_n\\), + +\\(\{x_1 , … , x_n \}\\) is a shorthand for `Tuple$n$($x_1 , … , x_n$)`. + +#### Infix operators of greater arities + +It is now possible to use methods which have more than one parameter as +infix operators (). In this case, all method arguments are written as a +normal parameter list in parentheses. Example: + + class C { + def +(x: int, y: String) = ... + } + val c = new C + c + (1, "abc") + +#### Deprecated attribute + +A new standard attribute `deprecated` is available (11-annotations.html#deprecation-annotations). If a member +definition is marked with this attribute, any reference to the member +will cause a “deprecated” warning message to be emitted. + +Changes in Version 2.3 +---------------------- + +_(23-Nov-2006)_ + +#### Procedures + +A simplified syntax for functions returning `unit` has been introduced +(). Scala now allows the following shorthands: + +`def f(params)` \\(\mbox{for}\\) `def f(params): unit` +`def f(params) { ... }` \\(\mbox{for}\\) `def f(params): unit = { ... }` + +#### Type Patterns + +The syntax of types in patterns has been refined (). Scala now +distinguishes between type variables (starting with a lower case letter) +and types as type arguments in patterns. Type variables are bound in the +pattern. Other type arguments are, as in previous versions, erased. The +Scala compiler will now issue an “unchecked” warning at places where +type erasure might compromise type-safety. + +#### Standard Types + +The recommended names for the two bottom classes in Scala’s type +hierarchy have changed as follows: + + All ==> Nothing + AllRef ==> Null + +The old names are still available as type aliases. + +Changes in Version 2.1.8 +------------------------ + +_(23-Aug-2006)_ + +#### Visibility Qualifier for protected + +Protected members can now have a visibility qualifier (), e.g. +`protected[<qualifier>]`. In particular, one can now simulate package +protected access as in Java writing + + protected[P] def X ... + +where would name the package containing . + +#### Relaxation of Private Acess + +Private members of a class can now be referenced from the companion +module of the class and vice versa () + +#### Implicit Lookup + +The lookup method for implicit definitions has been generalized (). When +searching for an implicit definition matching a type \\(T\\), now are +considered + +1. all identifiers accessible without prefix, and + +2. all members of companion modules of classes associated with \\(T\\). + +(The second clause is more general than before). Here, a class is +<span>*associated*</span> with a type \\(T\\) if it is referenced by +some part of \\(T\\), or if it is a base class of some part of \\(T\\). +For instance, to find implicit members corresponding to the type + + HashSet[List[Int], String] + +one would now look in the companion modules (aka static parts) of , , , +and . Before, it was just the static part of . + +#### Tightened Pattern Match + +A typed pattern match with a singleton type now tests whether the +selector value is reference-equal to p (). Example: + + val p = List(1, 2, 3) + val q = List(1, 2) + val r = q + r match { + case _: p.type => Console.println("p") + case _: q.type => Console.println("q") + } + +This will match the second case and hence will print “”. Before, the +singleton types were erased to , and therefore the first case would have +matched, which is non-sensical. + +Changes in Version 2.1.7 +------------------------ + +_(19-Jul-2006)_ + +#### Multi-Line string literals + +It is now possible to write multi-line string-literals enclosed in +triple quotes (). Example: + + """this is a + multi-line + string literal""" + +No escape substitutions except for unicode escapes are performed in such +string literals. + +#### Closure Syntax + +The syntax of closures has been slightly restricted (). The form + + x: T => E + +is valid only when enclosed in braces, i.e. `{ x: T => E }`. The +following is illegal, because it might be read as the value x typed with +the type T =\> E: + + val f = x: T => E + +Legal alternatives are: + + val f = { x: T => E } + val f = (x: T) => E + +Changes in Version 2.1.5 +------------------------ + +_(24-May-2006)_ + +#### Class Literals + +There is a new syntax for class literals (): For any class type \\(C\\), +`classOf[$C$]` designates the run-time representation of \\(C\\). + +Changes in Version 2.0 +---------------------- + +_(12-Mar-2006)_ + +Scala in its second version is different in some details from the first +version of the language. There have been several additions and some old +idioms are no longer supported. This appendix summarizes the main +changes. + +#### New Keywords + +The following three words are now reserved; they cannot be used as +identifiers () + + implicit match requires + +#### Newlines as Statement Separators + +Newlines can now be used as statement separators in place of semicolons +() + +#### Syntax Restrictions + +There are some other situations where old constructs no longer work: + +##### *Pattern matching expressions* + +The `match` keyword now appears only as infix operator between a +selector expression and a number of cases, as in: + + expr match { + case Some(x) => ... + case None => ... + } + +Variants such as ` expr.match {...} ` or just ` match {...} ` are no +longer supported. + +##### *“With” in extends clauses* + +The idiom + + class C with M { ... } + +is no longer supported. A `with` connective is only allowed following an +`extends` clause. For instance, the line above would have to be written + + class C extends AnyRef with M { ... } . + +However, assuming `M` is a trait (see [sec:traits]), it is also legal to +write + + class C extends M { ... } + +The latter expression is treated as equivalent to + + class C extends S with M { ... } + +where `S` is the superclass of `M`. + +##### *Regular Expression Patterns* + +The only form of regular expression pattern that is currently supported +is a sequence pattern, which might end in a sequence wildcard . Example: + + case List(1, 2, _*) => ... // will match all lists starting with \code{1,2}. + +It is at current not clear whether this is a permanent restriction. We +are evaluating the possibility of re-introducing full regular expression +patterns in Scala. + +#### Selftype Annotations + +The recommended syntax of selftype annotations has changed. + + class C: T extends B { ... } + +becomes + + class C requires T extends B { ... } + +That is, selftypes are now indicated by the new `requires` keyword. The +old syntax is still available but is considered deprecated. + +#### For-comprehensions + +For-comprehensions () now admit value and pattern definitions. Example: + + for { + val x <- List.range(1, 100) + val y <- List.range(1, x) + val z = x + y + isPrime(z) + } yield Pair(x, y) + +Note the definition `val z = x + y` as the third item in the +for-comprehension. + +#### Conversions + +The rules for implicit conversions of methods to functions () have been +tightened. Previously, a parameterized method used as a value was always +implicitly converted to a function. This could lead to unexpected +results when method arguments where forgotten. Consider for instance the +statement below: + + show(x.toString) + +where `show` is defined as follows: + + def show(x: String) = Console.println(x) . + +Most likely, the programmer forgot to supply an empty argument list `()` +to `toString`. The previous Scala version would treat this code as a +partially applied method, and expand it to: + + show(() => x.toString()) + +As a result, the address of a closure would be printed instead of the +value of `s`. + +Scala version 2.0 will apply a conversion from partially applied method +to function value only if the expected type of the expression is indeed +a function type. For instance, the conversion would not be applied in +the code above because the expected type of `show`’s parameter is +`String`, not a function type. + +The new convention disallows some previously legal code. Example: + + def sum(f: int => double)(a: int, b: int): double = + if (a > b) 0 else f(a) + sum(f)(a + 1, b) + + val sumInts = sum(x => x) // error: missing arguments + +The partial application of `sum` in the last line of the code above will +not be converted to a function type. Instead, the compiler will produce +an error message which states that arguments for method `sum` are +missing. The problem can be fixed by providing an expected type for the +partial application, for instance by annotating the definition of +`sumInts` with its type: + + val sumInts: (int, int) => double = sum(x => x) // OK + +On the other hand, Scala version 2.0 now automatically applies methods +with empty parameter lists to `()` argument lists when necessary. For +instance, the `show` expression above will now be expanded to + + show(x.toString()) . + +Scala version 2.0 also relaxes the rules of overriding with respect to +empty parameter lists. The revised definition of <span>*matching +members*</span> () makes it now possible to override a method with an +explicit, but empty parameter list `()` with a parameterless method, and +<span>*vice versa*</span>. For instance, the following class definition +is now legal: + + class C { + override def toString: String = ... + } + +Previously this definition would have been rejected, because the +`toString` method as inherited from `java.lang.Object` takes an empty +parameter list. + +#### Class Parameters + +A class parameter may now be prefixed by `val` or `var` (). + +#### Private Qualifiers + +Previously, Scala had three levels of visibility: +<span>*private*</span>, <span>*protected*</span> and +<span>*public*</span>. There was no way to restrict accesses to members +of the current package, as in Java. Scala 2 now defines access +qualifiers that let one express this level of visibility, among others. +In the definition + + private[C] def f(...) + +access to `f` is restricted to all code within the class or package `C` +(which must contain the definition of `f`) () + +#### Changes in the Mixin Model + +The model which details mixin composition of classes has changed +significantly. The main differences are: + +1. We now distinguish between <span>*traits*</span> that are used as + mixin classes and normal classes. The syntax of traits has been + generalized from version 1.0, in that traits are now allowed to have + mutable fields. However, as in version 1.0, traits still may not + have constructor parameters. + +2. Member resolution and super accesses are now both defined in terms + of a <span>*class linearization*</span>. + +3. Scala’s notion of method overloading has been generalized; in + particular, it is now possible to have overloaded variants of the + same method in a subclass and in a superclass, or in several + different mixins. This makes method overloading in Scala + conceptually the same as in Java. + +The new mixin model is explained in more detail in . + +#### Implicit Parameters + +Views in Scala 1.0 have been replaced by the more general concept of +implicit parameters () + +#### Flexible Typing of Pattern Matching + +The new version of Scala implements more flexible typing rules when it +comes to pattern matching over heterogeneous class hierarchies (). A +<span>*heterogeneous class hierarchy*</span> is one where subclasses +inherit a common superclass with different parameter types. With the new +rules in Scala version 2.0 one can perform pattern matches over such +hierarchies with more precise typings that keep track of the information +gained by comparing the types of a selector and a matching pattern (). +This gives Scala capabilities analogous to guarded algebraic data types. + +[^1]: Implemented by Adriaan Moors diff --git a/spec/README.md b/spec/README.md index 97c3fdf832..2f582dec5c 100644 --- a/spec/README.md +++ b/spec/README.md @@ -8,7 +8,7 @@ Third, we'd like to support different output formats. An html page per chapter w ## Editing -We use redcarpet 3.1 and jekyll 2 (currently in alpha) to generate the html. Essentially, this is what github pages use. +We use redcarpet 3.1 and jekyll 2 to generate the html. Essentially, this is what github pages use. ## Building diff --git a/spec/_includes/numbering.css b/spec/_includes/numbering.css index 8df08098bc..2a22ce28b5 100644 --- a/spec/_includes/numbering.css +++ b/spec/_includes/numbering.css @@ -1,4 +1,3 @@ -// based on http://philarcher.org/css/numberheadings.css, h1 { /* must reset here */ counter-reset: chapter {{ page.chapter }}; @@ -40,7 +39,6 @@ h3:before { display: inline; margin-right: 1em; } - h3[id*='example'] { /* must increment here */ counter-increment: example; diff --git a/spec/_layouts/default.yml b/spec/_layouts/default.yml index 64ba4a1639..69791d26ad 100644 --- a/spec/_layouts/default.yml +++ b/spec/_layouts/default.yml @@ -16,75 +16,31 @@ }); </script> <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/2.3-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> + <script src="//code.jquery.com/jquery-2.1.3.min.js"></script> <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.2/styles/default.min.css"> - <link rel="stylesheet" href="public/octicons/octicons.css"> - <script src="public/highlight/highlight.pack.js"></script> - <script src="public/scripts/navigation.js"></script> - <!-- need to use include to see value of page.chapter variable --> <style type="text/css"> {% include numbering.css %} - - /* proper rendering of MathJax into highlighted code blocks */ - .fixws { white-space: pre; } - .fixws .math { white-space: nowrap; } </style> - <script type="text/javascript"> - // clear content of H3 nodes that start with "Example:" - // the content is only there to determine ID of the H3 element (redcarpet doesn't let us set css id) - $( document ).ready(function(){ $("h3[id*='example']").text("") }) - - // no language auto-detect so that EBDF isn't detected as scala - hljs.configure({ - languages: [] - }); - - // syntax highlighting after mathjax is loaded so that mathjax can be used in code blocks - MathJax.Hub.Queue(function () { - hljs.initHighlighting(); - $("pre nobr").addClass("fixws"); - }) - - // and finally TOC generation - $(document).ready(function() { - $('.toc').navigation(); - }) - </script> - <link rel="stylesheet" type="text/css" href="public/stylesheets/screen.css"> + <link rel="stylesheet" type="text/css" media="(max-width: 1400px), (orientation: portrait)" href="public/stylesheets/screen-small.css"> <link rel="stylesheet" type="text/css" media="print" href="public/stylesheets/print.css"> + <link rel="stylesheet" type="text/css" href="public/stylesheets/fonts.css"> <title>{{ page.title }}</title> </head> <body> -<div id="header"> -<a alt="The Scala Language Specification" href="{{site.baseurl}}/"><img id="scala-logo" src="public/images/scala-logo-red-spiral-dark.png" /> -<h1 class="no-numbering">Language Specification</h1></a> -</div> -<div id="container"> -<div id="navigation"> -<ol> - {% assign sorted_pages = site.pages | sort:"name" %} - {% for post in sorted_pages %} - {% if post.chapter >= 0 %} - {% if page.url == post.url %} - <li class="active-page"> - <a href="{{site.baseurl}}{{ post.url }}"> {{ post.title }}</a> - <div class="toc"></div> - </li> - {% else %} - <li> - <a href="{{site.baseurl}}{{ post.url }}"> {{ post.title }}</a> - </li> - {% endif %} - {% endif %} - {% endfor %} -</ol> -</div> -<div id="content-container"> + <header> + <nav id="chapters"><a id="github" href="https://github.com/scala/scala/tree/2.11.x/spec"><img src="public/images/github-logo@2x.png" alt="Edit at Github"></a>{% assign sorted_pages = site.pages | sort:"name" %}{% for post in sorted_pages %}{% if post.chapter >= 0 %}<a href="{{site.baseurl}}{{ post.url }}">{{post.chapter}} {{ post.title }}</a>{% endif %}{% endfor %}</nav> + </header> + <aside class="left"><nav id="toc"></nav></aside> + + <main id="content"> {{ content }} -</div> -</div> + </main> + + <script src="public/scripts/toc.js"></script> + <script src="public/scripts/highlight.pack.js"></script> + <script src="public/scripts/main.js"></script> </body> </html> diff --git a/spec/_layouts/toc.yml b/spec/_layouts/toc.yml index caf0be1a3a..4da7d41bea 100644 --- a/spec/_layouts/toc.yml +++ b/spec/_layouts/toc.yml @@ -6,23 +6,25 @@ <link rel="icon" type="image/png" href="public/favicon.ico"> <link rel="shortcut icon" type="image/png" href="public/favicon.ico"> - <link rel="stylesheet" type="text/css" href="public/stylesheets/screen.css"> - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> + <script src="//code.jquery.com/jquery-2.1.3.min.js"></script> <title>{{ page.title }}</title> - <script type="text/javascript"> - $(document).ready(function() { - $('#the-scala-language-specification').css('display','none'); - }) - </script> + <link rel="stylesheet" type="text/css" href="public/stylesheets/screen.css"> + <link rel="stylesheet" type="text/css" href="public/stylesheets/screen-toc.css"> + <link rel="stylesheet" type="text/css" href="public/stylesheets/fonts.css"> </head> <body> -<div id="header"> -<a alt="The Scala Language Specification" href="{{site.baseurl}}/"><img id="scala-logo" src="public/images/scala-logo-red-spiral-dark.png" /> -<h1 class="no-numbering">Language Specification</h1></a> -</div> +<header> + <div id="header-main"> + <img id="scala-logo" src="public/images/scala-spiral-white.png" /> + <span id="title">Scala Language Specification</span> + <a id="github" href="https://github.com/scala/scala/tree/2.11.x/spec"><img src="public/images/github-logo@2x.png" alt="Edit at Github"></a> + </div> + <div id="header-sub">Version 2.11</div> +</header> +<main> {{ content }} - +</main> </body> </html> diff --git a/spec/index.md b/spec/index.md index ee9c2a5f78..d7e79dafb7 100644 --- a/spec/index.md +++ b/spec/index.md @@ -1,18 +1,9 @@ --- -title: Scala Language Reference +title: Scala Language Specification layout: toc --- -# The Scala Language Specification -# Version 2.11 - -### Maintained online at [https://github.com/scala/scala/tree/2.11.x/spec](https://github.com/scala/scala/tree/2.11.x/spec) - -### Martin Odersky, Philippe Altherr, Vincent Cremet, Gilles Dubochet, Burak Emir, Philipp Haller, Stéphane Micheloud, Nikolay Mihaylov, Adriaan Moors, Lukas Rytz, Michel Schinz, Erik Stenman, Matthias Zenger - -### Markdown Conversion by Iain McGinniss. - -## Table of Contents +# Table of Contents <ol> {% assign sorted_pages = site.pages | sort:"name" %} @@ -27,7 +18,13 @@ layout: toc {% endfor %} </ol> -## Preface +#### Authors and Contributors + +Martin Odersky, Philippe Altherr, Vincent Cremet, Gilles Dubochet, Burak Emir, Philipp Haller, Stéphane Micheloud, Nikolay Mihaylov, Adriaan Moors, Lukas Rytz, Michel Schinz, Erik Stenman, Matthias Zenger + +Markdown Conversion by Iain McGinniss. + +#### Preface Scala is a Java-like programming language which unifies object-oriented and functional programming. It is a pure diff --git a/spec/public/fonts/Heuristica-Bold.woff b/spec/public/fonts/Heuristica-Bold.woff Binary files differnew file mode 100644 index 0000000000..904579683d --- /dev/null +++ b/spec/public/fonts/Heuristica-Bold.woff diff --git a/spec/public/fonts/Heuristica-BoldItalic.woff b/spec/public/fonts/Heuristica-BoldItalic.woff Binary files differnew file mode 100644 index 0000000000..a3c5234453 --- /dev/null +++ b/spec/public/fonts/Heuristica-BoldItalic.woff diff --git a/spec/public/fonts/Heuristica-Regular.woff b/spec/public/fonts/Heuristica-Regular.woff Binary files differnew file mode 100644 index 0000000000..f5c1f8b2db --- /dev/null +++ b/spec/public/fonts/Heuristica-Regular.woff diff --git a/spec/public/fonts/Heuristica-RegularItalic.woff b/spec/public/fonts/Heuristica-RegularItalic.woff Binary files differnew file mode 100644 index 0000000000..d2c8664593 --- /dev/null +++ b/spec/public/fonts/Heuristica-RegularItalic.woff diff --git a/spec/public/fonts/LuxiMono-Bold.woff b/spec/public/fonts/LuxiMono-Bold.woff Binary files differnew file mode 100644 index 0000000000..8581bb5aa4 --- /dev/null +++ b/spec/public/fonts/LuxiMono-Bold.woff diff --git a/spec/public/fonts/LuxiMono-BoldOblique.woff b/spec/public/fonts/LuxiMono-BoldOblique.woff Binary files differnew file mode 100644 index 0000000000..607ccf5cd0 --- /dev/null +++ b/spec/public/fonts/LuxiMono-BoldOblique.woff diff --git a/spec/public/fonts/LuxiMono-Regular.woff b/spec/public/fonts/LuxiMono-Regular.woff Binary files differnew file mode 100644 index 0000000000..a478ad9ef2 --- /dev/null +++ b/spec/public/fonts/LuxiMono-Regular.woff diff --git a/spec/public/fonts/LuxiMono-RegularOblique.woff b/spec/public/fonts/LuxiMono-RegularOblique.woff Binary files differnew file mode 100644 index 0000000000..26999f990f --- /dev/null +++ b/spec/public/fonts/LuxiMono-RegularOblique.woff diff --git a/spec/public/fonts/LuxiSans-Bold.woff b/spec/public/fonts/LuxiSans-Bold.woff Binary files differnew file mode 100644 index 0000000000..162621568b --- /dev/null +++ b/spec/public/fonts/LuxiSans-Bold.woff diff --git a/spec/public/fonts/LuxiSans-Regular.woff b/spec/public/fonts/LuxiSans-Regular.woff Binary files differnew file mode 100644 index 0000000000..89d980218f --- /dev/null +++ b/spec/public/fonts/LuxiSans-Regular.woff diff --git a/spec/public/images/github-logo@2x.png b/spec/public/images/github-logo@2x.png Binary files differnew file mode 100644 index 0000000000..285b0fee2f --- /dev/null +++ b/spec/public/images/github-logo@2x.png diff --git a/spec/public/images/scala-logo-red-spiral-dark.png b/spec/public/images/scala-logo-red-spiral-dark.png Binary files differdeleted file mode 100644 index 09b66b5e6a..0000000000 --- a/spec/public/images/scala-logo-red-spiral-dark.png +++ /dev/null diff --git a/spec/public/images/scala-spiral-white.png b/spec/public/images/scala-spiral-white.png Binary files differnew file mode 100644 index 0000000000..46aaf80824 --- /dev/null +++ b/spec/public/images/scala-spiral-white.png diff --git a/spec/public/highlight/LICENSE b/spec/public/scripts/LICENSE-highlight index 422deb7350..fe2f67b162 100644 --- a/spec/public/highlight/LICENSE +++ b/spec/public/scripts/LICENSE-highlight @@ -8,8 +8,8 @@ modification, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of highlight.js nor the names of its contributors - may be used to endorse or promote products derived from this software + * Neither the name of highlight.js nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY diff --git a/spec/public/scripts/LICENSE-toc b/spec/public/scripts/LICENSE-toc new file mode 100644 index 0000000000..4e236e8696 --- /dev/null +++ b/spec/public/scripts/LICENSE-toc @@ -0,0 +1,18 @@ +(The MIT License) +Copyright (c) 2013 Greg Allen +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file diff --git a/spec/public/highlight/highlight.pack.js b/spec/public/scripts/highlight.pack.js index bfeca09abb..bfeca09abb 100644 --- a/spec/public/highlight/highlight.pack.js +++ b/spec/public/scripts/highlight.pack.js diff --git a/spec/public/scripts/main.js b/spec/public/scripts/main.js new file mode 100644 index 0000000000..f0509aba41 --- /dev/null +++ b/spec/public/scripts/main.js @@ -0,0 +1,57 @@ +function currentChapter() { + var path = document.location.pathname; + var idx = path.lastIndexOf("/") + 1; + var chap = path.substring(idx, idx + 2); + return parseInt(chap, 10); +} + +function heading(i, heading, $heading) { + var currentLevel = parseInt(heading.tagName.substring(1)); + var result = ""; + if (currentLevel === this.headerLevel) { + this.headerCounts[this.headerLevel] += 1; + return "" + this.headerCounts[this.headerLevel] + " " + $heading.text(); + } else if (currentLevel < this.headerLevel) { + while(currentLevel < this.headerLevel) { + this.headerCounts[this.headerLevel] = 1; + this.headerLevel -= 1; + } + this.headerCounts[this.headerLevel] += 1; + return "" + this.headerCounts[this.headerLevel]+ " " + $heading.text(); + } else { + while(currentLevel > this.headerLevel) { + this.headerLevel += 1; + this.headerCounts[this.headerLevel] = 1; + } + return "" + this.headerCounts[this.headerLevel]+ " " + $heading.text(); + } +} + +$('#toc').toc( + { + 'selectors': 'h1,h2,h3', + 'smoothScrolling': false, + 'chapter': currentChapter(), + 'headerLevel': 1, + 'headerCounts': [-1, currentChapter() - 1, 1, 1], + 'headerText': heading + } +); + +// no language auto-detect so that EBNF isn't detected as scala +hljs.configure({ + languages: [] +}); + +// syntax highlighting after mathjax is loaded so that mathjax can be used in code blocks +MathJax.Hub.Queue(function () { + hljs.initHighlighting(); + $("pre nobr").addClass("fixws"); +}) + +$("#chapters a").each(function (index) { + if (document.location.pathname.endsWith($(this).attr("href"))) + $(this).addClass("chapter-active"); + else + $(this).removeClass("chapter-active"); +}); diff --git a/spec/public/scripts/navigation.js b/spec/public/scripts/navigation.js deleted file mode 100644 index c046bf4d54..0000000000 --- a/spec/public/scripts/navigation.js +++ /dev/null @@ -1,70 +0,0 @@ -(function($){ $.fn.navigation = function() { - - // the TOC already contains H1 so we start at H2 - var headers = $('h2, h3, h4, h5').filter(function() { - // exclude examples - if (this.id.substr(0, 7) == 'example') { - return false; - } - - // get all headers with an id - return this.id; - }); - - var output = $(this); - - var get_level = function(n) { return parseInt(n.nodeName.replace('H', ''), 10); } - - var back_to_top = '<span title="Return to top" class="to_top octicon octicon-chevron-up"></span>'; - - if (headers.length && output.length) { - var level = get_level(headers[0]); - var current_level; - var html = '<ol>'; - - headers.each(function(_, header) { - current_level = get_level(header); - - if (current_level === level) { - // same level as before - html += '<li><a href="#' + header.id + '">' + header.innerHTML + '</a>'; - } else if (current_level <= level) { - // higher level, we go back up and chose intermediary lists - for(i = current_level; i < level; i++) { - html += '</li></ol>'; - } - html += '<li><a href="#' + header.id + '">' + header.innerHTML + '</a>'; - } else if (current_level > level) { - // lower level, we open new nested lists - for(i = current_level; i > level; i--) { - html += '<ol><li>'; - } - html += '<a href="#' + header.id + '">' + header.innerHTML + '</a>'; - } - - var header_link = '<a class="anchor" href="#' + header.id + '"><span class="octicon octicon-link"></span></a>'; - $(header).prepend(header_link); - - if (!$(header).prev().is('h1')) { - $(header).after(back_to_top); - } - - level = current_level; - }); - - html += '</ol>'; - - output.html(html); - } - - // back to top links - $(document).on('click', '.to_top', function() { - $(window).scrollTop(0); - window.location.hash = ''; - }); - - // we add one more at the end of the document - $('#content-container').append(back_to_top); - -};})(jQuery); - diff --git a/spec/public/scripts/toc.js b/spec/public/scripts/toc.js new file mode 100644 index 0000000000..070d7b7a93 --- /dev/null +++ b/spec/public/scripts/toc.js @@ -0,0 +1,128 @@ +/*! + * toc - jQuery Table of Contents Plugin + * v0.3.2 + * http://projects.jga.me/toc/ + * copyright Greg Allen 2014 + * MIT License +*/ +(function($) { +var verboseIdCache = {}; +$.fn.toc = function(options) { + var self = this; + var opts = $.extend({}, jQuery.fn.toc.defaults, options); + + var container = $(opts.container); + var headings = $(opts.selectors, container); + var headingOffsets = []; + var activeClassName = opts.activeClass; + + var scrollTo = function(e, callback) { + $('li', self).removeClass(activeClassName); + $(e.target).parent().addClass(activeClassName); + }; + + //highlight on scroll + var timeout; + var highlightOnScroll = function(e) { + if (timeout) { + clearTimeout(timeout); + } + timeout = setTimeout(function() { + var top = $(window).scrollTop(), + highlighted, closest = Number.MAX_VALUE, index = 0; + + for (var i = 0, c = headingOffsets.length; i < c; i++) { + var currentClosest = Math.abs(headingOffsets[i] - top); + if (currentClosest < closest) { + index = i; + closest = currentClosest; + } + } + + $('li', self).removeClass(activeClassName); + highlighted = $('li:eq('+ index +')', self).addClass(activeClassName); + opts.onHighlight(highlighted); + }, 50); + }; + if (opts.highlightOnScroll) { + $(window).bind('scroll', highlightOnScroll); + highlightOnScroll(); + } + + return this.each(function() { + //build TOC + var el = $(this); + var ul = $(opts.listType); + + headings.each(function(i, heading) { + var $h = $(heading); + headingOffsets.push($h.offset().top - opts.highlightOffset); + + var anchorName = opts.anchorName(i, heading, opts.prefix); + + //add anchor + if(heading.id !== anchorName) { + var anchor = $('<span/>').attr('id', anchorName).insertBefore($h); + } + + //build TOC item + var a = $('<a/>') + .text(opts.headerText(i, heading, $h)) + .attr('href', '#' + anchorName) + .bind('click', function(e) { + $(window).unbind('scroll', highlightOnScroll); + scrollTo(e, function() { + $(window).bind('scroll', highlightOnScroll); + }); + el.trigger('selected', $(this).attr('href')); + }); + + var li = $('<li/>') + .addClass(opts.itemClass(i, heading, $h, opts.prefix)) + .append(a); + + ul.append(li); + }); + el.html(ul); + }); +}; + + +jQuery.fn.toc.defaults = { + container: 'body', + listType: '<ul/>', + selectors: 'h1,h2,h3', + prefix: 'toc', + activeClass: 'toc-active', + onHighlight: function() {}, + highlightOnScroll: true, + highlightOffset: 100, + anchorName: function(i, heading, prefix) { + if(heading.id.length) { + return heading.id; + } + + var candidateId = $(heading).text().replace(/[^a-z0-9]/ig, ' ').replace(/\s+/g, '-').toLowerCase(); + if (verboseIdCache[candidateId]) { + var j = 2; + + while(verboseIdCache[candidateId + j]) { + j++; + } + candidateId = candidateId + '-' + j; + + } + verboseIdCache[candidateId] = true; + + return prefix + '-' + candidateId; + }, + headerText: function(i, heading, $heading) { + return $heading.text(); + }, + itemClass: function(i, heading, $heading, prefix) { + return prefix + '-' + $heading[0].tagName.toLowerCase(); + } + +}; + +})(jQuery); diff --git a/spec/public/stylesheets/fonts.css b/spec/public/stylesheets/fonts.css new file mode 100644 index 0000000000..36efb2bbd5 --- /dev/null +++ b/spec/public/stylesheets/fonts.css @@ -0,0 +1,73 @@ +@font-face { + font-family: 'Luxi Sans'; + src: local('Luxi Sans Regular'), + url('../fonts/LuxiSans-Regular.woff') format('woff'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Luxi Sans'; + src: local('Luxi Sans Bold'), + url('../fonts/LuxiSans-Bold.woff') format('woff'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'Luxi Mono'; + src: local('Luxi Mono Regular'), + url('../fonts/LuxiMono-Regular.woff') format('woff'); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: 'Luxi Mono'; + src: local('Luxi Mono Oblique'), + url('../fonts/LuxiMono-BoldOblique.woff') format('woff'); + font-weight: normal; + font-style: oblique; +} +@font-face { + font-family: 'Luxi Mono'; + src: local('Luxi Mono Bold'), + url('../fonts/LuxiMono-Bold.woff') format('woff'); + font-weight: bold; + font-style: normal; +} +@font-face { + font-family: 'Luxi Mono'; + src: local('Luxi Mono Bold Oblique'), + url('../fonts/LuxiMono-BoldOblique.woff') format('woff'); + font-weight: bold; + font-style: oblique; +} + +@font-face { + font-family: 'Heuristica'; + src: local('Heuristica Regular'), + url('../fonts/Heuristica-Regular.woff') format('woff'); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: 'Heuristica'; + src: local('Heuristica Italic'), + url('../fonts/Heuristica-RegularItalic.woff') format('woff'); + font-weight: normal; + font-style: italic; +} +@font-face { + font-family: 'Heuristica'; + src: local('Heuristica Bold'), + url('../fonts/Heuristica-Bold.woff') format('woff'); + font-weight: bold; + font-style: normal; +} +@font-face { + font-family: 'Heuristica'; + src: local('Heuristica Bold Italic'), + url('../fonts/Heuristica-BoldItalic.woff') format('woff'); + font-weight: bold; + font-style: italic; +} diff --git a/spec/public/stylesheets/screen-small.css b/spec/public/stylesheets/screen-small.css new file mode 100644 index 0000000000..674db7c490 --- /dev/null +++ b/spec/public/stylesheets/screen-small.css @@ -0,0 +1,57 @@ +body { + padding: 0px; + margin: 0px; +} +aside.left { + position: relative; + margin: 0px auto; + overflow: visible; + height: inherit; + margin-bottom: 40px; + background-color: #073642; +} +header { + position: relative; + height: inherit; + min-height: 32px; +} +main { + max-width: 1000px; + min-width: 600px; + margin: 0 auto; +} + +#chapters a { + font-size: 14px; + max-height: 32px; + padding: 4px 8px; + white-space: nowrap; + display: inline-block; +} +#chapters > #github { + padding: 14px; +} + +#toc { + overflow: visible; +} +#toc .toc-active { + background: inherit; +} +#toc .toc-h1 { + display: inherit; +} +#toc .toc-h1 a { + padding-left: 10px; + color: #FFFFFF; + background: #72D0EB; +} +#toc .toc-h2 a { + padding-left: 30px; +} +#toc .toc-h3 a { + padding-left: 50px; +} +#toc a { + font-size: 14px; +} diff --git a/spec/public/stylesheets/screen-toc.css b/spec/public/stylesheets/screen-toc.css new file mode 100644 index 0000000000..7a04bd00f9 --- /dev/null +++ b/spec/public/stylesheets/screen-toc.css @@ -0,0 +1,37 @@ +body { + padding: 0px; + margin: 0px; +} +header { + height: 96px; + padding: 0px; + width: 100%; + position: relative; + color: #FFFFFF; +} +#header-main { + height: 68px; + line-height: 1.2; + font-size: 32px; +} +#header-sub { + padding-left: 64px; + height: 28px; + background-color:#72D0EB; + vertical-align: middle; +} +#scala-logo { + padding: 10px; +} +#title { + vertical-align: middle; +} +#github { + height: 40px; + padding: 14px; + float: right; + font-size: 0px; +} +li { + margin: 5px; +} diff --git a/spec/public/stylesheets/screen.css b/spec/public/stylesheets/screen.css index dbb3ebe1b3..fdddba0b45 100644 --- a/spec/public/stylesheets/screen.css +++ b/spec/public/stylesheets/screen.css @@ -1,8 +1,8 @@ /* from https://gist.github.com/andyferra/2554919 */ body { - font-family: Helvetica, arial, sans-serif; - font-size: 14px; + font-family:Heuristica,Georgia,serif; + color: #222222; line-height: 1.6; padding-bottom: 10px; @@ -18,7 +18,11 @@ body { } a { - color: #4183C4; + color: #08C; + text-decoration: none; +} +a:hover, a:focus { + } a.absent { color: #cc0000; @@ -41,13 +45,21 @@ a.anchor span { } h1, h2, h3, h4, h5, h6 { - margin: 20px 0 10px; + margin: 30px 0 0px; + padding: 0; + /* Fix anchor position due to header */ + padding-top: 32px; + margin-top: -32px; font-weight: bold; -webkit-font-smoothing: antialiased; cursor: text; position: relative; } +h1, h2 { + font-weight: normal; +} + h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor { text-decoration: none; } @@ -95,7 +107,6 @@ h1 { h2 { font-size: 24px; - border-bottom: 1px solid #cccccc; color: black; } @@ -117,7 +128,7 @@ h6 { } p, blockquote, ul, ol, dl, li, table, pre { - margin: 15px 0; + margin: 5px 0 15px; -moz-font-feature-settings: "onum"; -ms-font-feature-settings: "onum"; -webkit-font-feature-settings: "onum"; @@ -125,7 +136,7 @@ p, blockquote, ul, ol, dl, li, table, pre { } hr { - background: transparent url("../../images/modules/pulls/dirty-shade.png") repeat-x 0 0; + background: transparent repeat-x 0 0; border: 0 none; color: #cccccc; height: 4px; @@ -207,7 +218,7 @@ dl dd > :last-child { blockquote { border-left: 4px solid #dddddd; padding: 0 15px; - color: #777777; + color: #222222; } blockquote > :first-child { margin-top: 0; @@ -215,31 +226,34 @@ blockquote > :first-child { blockquote > :last-child { margin-bottom: 0; } +blockquote:before { + content: "Example"; + color: #777777; + font-size: 14px; + font-weight: bold; +} table { padding: 0; + margin: 0; + border: none; + border-collapse: collapse; } table tr { - border-top: 1px solid #cccccc; background-color: white; - margin: 0; - padding: 0; } table tr:nth-child(2n) { background-color: #f8f8f8; } table tr th { + background-color: #EAEAEA; font-weight: bold; - border: 1px solid #cccccc; text-align: left; - margin: 0; - padding: 6px 13px; + padding: 5px 13px; } table tr td { - border: 1px solid #cccccc; text-align: left; - margin: 0; - padding: 6px 13px; + padding: 5px 13px; } table tr th :first-child, table tr td :first-child { margin-top: 0; @@ -327,11 +341,14 @@ span.float-right > span { text-align: right; } +pre, code, tt { + font:14px "Luxi Mono", 'andale mono', 'lucida console', monospace; + line-height:1.5; +} + .highlight pre { - border: 1px solid #eaeaea; - background-color: #f8f8f8; + background-color: #F8F8F8; border-radius: 3px; - line-height: 19px; overflow: auto; padding: 6px 10px; white-space: nowrap; @@ -343,86 +360,144 @@ code { margin: 0; padding: 0; white-space: pre; - font-size: 16px; } -#navigation { - margin-right: 10px; - float: right; - width: 26%; - display: inline; - color: #8B8B8B; - font-size: 15px; - font-weight: bold; - background-color: #F3F4F4; +aside.left { + height: 100%; + position: fixed; + direction: rtl; + overflow: auto; + left: 0px; + width: 320px; + bottom: -32px; + font-family: "Luxi Sans", serif; + background-color: #073642; } -#content-container { - float: left; - width: 70%; - display: inline; +aside.left > nav { + direction: ltr; + top: 32px; + padding-bottom: 32px; } -#container { - padding-top: 10px; - width: 100%; +article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { + display: block; } -#navigation a { - text-decoration: none; - color: #8B8B8B; +audio, canvas, img, svg, video { + vertical-align: middle; } -#navigation a:hover { - text-decoration: underline; +audio, canvas, progress, video { + display: inline-block; + vertical-align: baseline; } -.active-page { - color: #171717; +main { + position: relative; + top: 32px; + margin: 0 0 0 320px; + padding: 0px 32px; + max-width: 800px; + min-width: 800px; + min-height: 580px; + background-color: #FFF; } -.active-page a { - color: #171717 !important; +header { + position: fixed; + top: 0px; + left: 0px; + height: 32px; + width: 100%; + background-color: #002B36; + margin: 0px 0px; + padding: 0px 0px; + font-family: "Luxi Sans", serif; + font-weight: bold; + z-index: 10; + overflow: hidden; + text-shadow: 1px 1px 0px rgba(0, 43, 54, 0.15); } -.to_top { - position: absolute; - margin-top: -35px; - right: 27%; - color: gray; - cursor: pointer; - width: 16px; height: 16px; - display: block; +#chapters a { + color: #FFFFFF; + text-decoration: none; + font-size: 0.63vw; + padding: 100% 8px; } -.to_top:hover { - color: black; +#chapters a:hover, #chapters a:focus, #github:hover, #github:focus { + background: #DC322F; + -webkit-transition: background .2s ease-in; + -moz-transition: background .2s ease-in; + -ms-transition: background .2s ease-in; + -o-transition: background .2s ease-in; + transition: background .2s ease-in; } -#scala-logo { - float: left; - width: 168px; - height: 48px; - margin-right: 25px; +#chapters a.chapter-active { + background: #72D0EB; } -#header { - padding-top: 16px; - padding-bottom: 10px; - margin-bottom: 10px; - height: 64px; - border-bottom: 1px solid #cccccc; + +#toc ul { + margin: 0; + padding: 0; + list-style: none; } -#header a { - height: 100%; - display: block; +#toc li { + margin: 0; + padding: 0; +} + +#toc a { + color: #FFFFFF; /*#073642;*/ + font-weight: bold; + font-size: 12px; + display: block; + text-shadow: 1px 1px 0px rgba(0, 43, 54, 0.15); +} + +#toc a:hover, #toc a:focus { + background: #DC322F; text-decoration: none; + -webkit-transition: background .2s ease-in; + -moz-transition: background .2s ease-in; + -ms-transition: background .2s ease-in; + -o-transition: background .2s ease-in; + transition: background .2s ease-in; } -#header h1 { - cursor: pointer; - padding-top: 6px; - margin-bottom: 0px; - font-size: 30px; +#toc .toc-h1 { + display: none; +} + +#toc .toc-h2 a { + padding-left: 10px; +} + +#toc .toc-h3 a { + padding-left: 30px; +} + +#toc .toc-active { + background: #72D0EB; +} + +#toc .toc-active a { + color: #FFFFFF; +} + +#chapters > #github { + padding: 0px; + float: right; +} + +.hljs{ + background: #f8f8f8; } +/* proper rendering of MathJax into highlighted code blocks */ +.fixws { white-space: pre; } +.fixws .math { white-space: nowrap; } diff --git a/src/asm/README b/src/asm/README deleted file mode 100644 index 58d555acde..0000000000 --- a/src/asm/README +++ /dev/null @@ -1,37 +0,0 @@ -Version 5.0.3, SVN r1748, tags/ASM_5_0_3 - -Git SVN repo: https://github.com/lrytz/asm - - git svn howto: https://github.com/lrytz/asm/issues/1 - -Upgrading ASM -------------- - -Check the commit history of src/asm: https://github.com/scala/scala/commits/2.11.x/src/asm. -Find the previous commit that upgraded ASM and take a look at its commit message. It should -be a squashed version of a pull request that shows the precise procedure how the last upgrade -was made. - -Start by deleting all source files in src/asm/ and copy the ones from the latest ASM release. - -Excluded Files (don't copy): - - package.html files - - org/objectweb/asm/commons, but keep CodeSizeEvaluator.java - - org/objectweb/asm/optimizer - - org/objectweb/asm/xml - -Re-packaging and cosmetic changes: - - convert line endings (there are some CRLF) - find src/asm/scala/tools/asm -name '*.java' | xargs dos2unix - - change package clauses - find src/asm/scala/tools/asm -name '*.java' | xargs sed -i '' -e 's/package org\.objectweb\.asm/package scala.tools.asm/' - - update imports - find src/asm/scala/tools/asm -name '*.java' | xargs sed -i '' -e 's/import org\.objectweb\.asm/import scala.tools.asm/' - - update @links, @associates - find src/asm/scala/tools/asm -name '*.java' | xargs sed -i '' -e 's/@link org\.objectweb\.asm/@link scala.tools.asm/' - find src/asm/scala/tools/asm -name '*.java' | xargs sed -i '' -e 's/@associates org\.objectweb\.asm/@associates scala.tools.asm/' - - remove trailing whitespace - find src/asm/scala/tools/asm -name '*.java' | xargs sed -i '' -e 's/[ ]*$//' - -Include the actual changes that we have in our repostiory - - Include the commits labelled [asm-cherry-pick] in the non-squashed PR of the previous upgrade - - Include the changes that were added to src/asm since the last upgrade and label them [asm-cherry-pick] diff --git a/src/asm/scala/tools/asm/AnnotationVisitor.java b/src/asm/scala/tools/asm/AnnotationVisitor.java deleted file mode 100644 index abcaf1d6d1..0000000000 --- a/src/asm/scala/tools/asm/AnnotationVisitor.java +++ /dev/null @@ -1,169 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * A visitor to visit a Java annotation. The methods of this class must be - * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> | - * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public abstract class AnnotationVisitor { - - /** - * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected final int api; - - /** - * The annotation visitor to which this visitor must delegate method calls. - * May be null. - */ - protected AnnotationVisitor av; - - /** - * Constructs a new {@link AnnotationVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public AnnotationVisitor(final int api) { - this(api, null); - } - - /** - * Constructs a new {@link AnnotationVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param av - * the annotation visitor to which this visitor must delegate - * method calls. May be null. - */ - public AnnotationVisitor(final int api, final AnnotationVisitor av) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { - throw new IllegalArgumentException(); - } - this.api = api; - this.av = av; - } - - /** - * Visits a primitive value of the annotation. - * - * @param name - * the value name. - * @param value - * the actual value, whose type must be {@link Byte}, - * {@link Boolean}, {@link Character}, {@link Short}, - * {@link Integer} , {@link Long}, {@link Float}, {@link Double}, - * {@link String} or {@link Type} or OBJECT or ARRAY sort. This - * value can also be an array of byte, boolean, short, char, int, - * long, float or double values (this is equivalent to using - * {@link #visitArray visitArray} and visiting each array element - * in turn, but is more convenient). - */ - public void visit(String name, Object value) { - if (av != null) { - av.visit(name, value); - } - } - - /** - * Visits an enumeration value of the annotation. - * - * @param name - * the value name. - * @param desc - * the class descriptor of the enumeration class. - * @param value - * the actual enumeration value. - */ - public void visitEnum(String name, String desc, String value) { - if (av != null) { - av.visitEnum(name, desc, value); - } - } - - /** - * Visits a nested annotation value of the annotation. - * - * @param name - * the value name. - * @param desc - * the class descriptor of the nested annotation class. - * @return a visitor to visit the actual nested annotation value, or - * <tt>null</tt> if this visitor is not interested in visiting this - * nested annotation. <i>The nested annotation value must be fully - * visited before calling other methods on this annotation - * visitor</i>. - */ - public AnnotationVisitor visitAnnotation(String name, String desc) { - if (av != null) { - return av.visitAnnotation(name, desc); - } - return null; - } - - /** - * Visits an array value of the annotation. Note that arrays of primitive - * types (such as byte, boolean, short, char, int, long, float or double) - * can be passed as value to {@link #visit visit}. This is what - * {@link ClassReader} does. - * - * @param name - * the value name. - * @return a visitor to visit the actual array value elements, or - * <tt>null</tt> if this visitor is not interested in visiting these - * values. The 'name' parameters passed to the methods of this - * visitor are ignored. <i>All the array values must be visited - * before calling other methods on this annotation visitor</i>. - */ - public AnnotationVisitor visitArray(String name) { - if (av != null) { - return av.visitArray(name); - } - return null; - } - - /** - * Visits the end of the annotation. - */ - public void visitEnd() { - if (av != null) { - av.visitEnd(); - } - } -} diff --git a/src/asm/scala/tools/asm/AnnotationWriter.java b/src/asm/scala/tools/asm/AnnotationWriter.java deleted file mode 100644 index 6de74ce041..0000000000 --- a/src/asm/scala/tools/asm/AnnotationWriter.java +++ /dev/null @@ -1,371 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * An {@link AnnotationVisitor} that generates annotations in bytecode form. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -final class AnnotationWriter extends AnnotationVisitor { - - /** - * The class writer to which this annotation must be added. - */ - private final ClassWriter cw; - - /** - * The number of values in this annotation. - */ - private int size; - - /** - * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation - * writers used for annotation default and annotation arrays use unnamed - * values. - */ - private final boolean named; - - /** - * The annotation values in bytecode form. This byte vector only contains - * the values themselves, i.e. the number of values must be stored as a - * unsigned short just before these bytes. - */ - private final ByteVector bv; - - /** - * The byte vector to be used to store the number of values of this - * annotation. See {@link #bv}. - */ - private final ByteVector parent; - - /** - * Where the number of values of this annotation must be stored in - * {@link #parent}. - */ - private final int offset; - - /** - * Next annotation writer. This field is used to store annotation lists. - */ - AnnotationWriter next; - - /** - * Previous annotation writer. This field is used to store annotation lists. - */ - AnnotationWriter prev; - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link AnnotationWriter}. - * - * @param cw - * the class writer to which this annotation must be added. - * @param named - * <tt>true<tt> if values are named, <tt>false</tt> otherwise. - * @param bv - * where the annotation values must be stored. - * @param parent - * where the number of annotation values must be stored. - * @param offset - * where in <tt>parent</tt> the number of annotation values must - * be stored. - */ - AnnotationWriter(final ClassWriter cw, final boolean named, - final ByteVector bv, final ByteVector parent, final int offset) { - super(Opcodes.ASM5); - this.cw = cw; - this.named = named; - this.bv = bv; - this.parent = parent; - this.offset = offset; - } - - // ------------------------------------------------------------------------ - // Implementation of the AnnotationVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public void visit(final String name, final Object value) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - if (value instanceof String) { - bv.put12('s', cw.newUTF8((String) value)); - } else if (value instanceof Byte) { - bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); - } else if (value instanceof Boolean) { - int v = ((Boolean) value).booleanValue() ? 1 : 0; - bv.put12('Z', cw.newInteger(v).index); - } else if (value instanceof Character) { - bv.put12('C', cw.newInteger(((Character) value).charValue()).index); - } else if (value instanceof Short) { - bv.put12('S', cw.newInteger(((Short) value).shortValue()).index); - } else if (value instanceof Type) { - bv.put12('c', cw.newUTF8(((Type) value).getDescriptor())); - } else if (value instanceof byte[]) { - byte[] v = (byte[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('B', cw.newInteger(v[i]).index); - } - } else if (value instanceof boolean[]) { - boolean[] v = (boolean[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index); - } - } else if (value instanceof short[]) { - short[] v = (short[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('S', cw.newInteger(v[i]).index); - } - } else if (value instanceof char[]) { - char[] v = (char[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('C', cw.newInteger(v[i]).index); - } - } else if (value instanceof int[]) { - int[] v = (int[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('I', cw.newInteger(v[i]).index); - } - } else if (value instanceof long[]) { - long[] v = (long[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('J', cw.newLong(v[i]).index); - } - } else if (value instanceof float[]) { - float[] v = (float[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('F', cw.newFloat(v[i]).index); - } - } else if (value instanceof double[]) { - double[] v = (double[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('D', cw.newDouble(v[i]).index); - } - } else { - Item i = cw.newConstItem(value); - bv.put12(".s.IFJDCS".charAt(i.type), i.index); - } - } - - @Override - public void visitEnum(final String name, final String desc, - final String value) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); - } - - @Override - public AnnotationVisitor visitAnnotation(final String name, - final String desc) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - // write tag and type, and reserve space for values count - bv.put12('@', cw.newUTF8(desc)).putShort(0); - return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); - } - - @Override - public AnnotationVisitor visitArray(final String name) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - // write tag, and reserve space for array size - bv.put12('[', 0); - return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); - } - - @Override - public void visitEnd() { - if (parent != null) { - byte[] data = parent.data; - data[offset] = (byte) (size >>> 8); - data[offset + 1] = (byte) size; - } - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - /** - * Returns the size of this annotation writer list. - * - * @return the size of this annotation writer list. - */ - int getSize() { - int size = 0; - AnnotationWriter aw = this; - while (aw != null) { - size += aw.bv.length; - aw = aw.next; - } - return size; - } - - /** - * Puts the annotations of this annotation writer list into the given byte - * vector. - * - * @param out - * where the annotations must be put. - */ - void put(final ByteVector out) { - int n = 0; - int size = 2; - AnnotationWriter aw = this; - AnnotationWriter last = null; - while (aw != null) { - ++n; - size += aw.bv.length; - aw.visitEnd(); // in case user forgot to call visitEnd - aw.prev = last; - last = aw; - aw = aw.next; - } - out.putInt(size); - out.putShort(n); - aw = last; - while (aw != null) { - out.putByteArray(aw.bv.data, 0, aw.bv.length); - aw = aw.prev; - } - } - - /** - * Puts the given annotation lists into the given byte vector. - * - * @param panns - * an array of annotation writer lists. - * @param off - * index of the first annotation to be written. - * @param out - * where the annotations must be put. - */ - static void put(final AnnotationWriter[] panns, final int off, - final ByteVector out) { - int size = 1 + 2 * (panns.length - off); - for (int i = off; i < panns.length; ++i) { - size += panns[i] == null ? 0 : panns[i].getSize(); - } - out.putInt(size).putByte(panns.length - off); - for (int i = off; i < panns.length; ++i) { - AnnotationWriter aw = panns[i]; - AnnotationWriter last = null; - int n = 0; - while (aw != null) { - ++n; - aw.visitEnd(); // in case user forgot to call visitEnd - aw.prev = last; - last = aw; - aw = aw.next; - } - out.putShort(n); - aw = last; - while (aw != null) { - out.putByteArray(aw.bv.data, 0, aw.bv.length); - aw = aw.prev; - } - } - } - - /** - * Puts the given type reference and type path into the given bytevector. - * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported. - * - * @param typeRef - * a reference to the annotated type. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param out - * where the type reference and type path must be put. - */ - static void putTarget(int typeRef, TypePath typePath, ByteVector out) { - switch (typeRef >>> 24) { - case 0x00: // CLASS_TYPE_PARAMETER - case 0x01: // METHOD_TYPE_PARAMETER - case 0x16: // METHOD_FORMAL_PARAMETER - out.putShort(typeRef >>> 16); - break; - case 0x13: // FIELD - case 0x14: // METHOD_RETURN - case 0x15: // METHOD_RECEIVER - out.putByte(typeRef >>> 24); - break; - case 0x47: // CAST - case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT - case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT - out.putInt(typeRef); - break; - // case 0x10: // CLASS_EXTENDS - // case 0x11: // CLASS_TYPE_PARAMETER_BOUND - // case 0x12: // METHOD_TYPE_PARAMETER_BOUND - // case 0x17: // THROWS - // case 0x42: // EXCEPTION_PARAMETER - // case 0x43: // INSTANCEOF - // case 0x44: // NEW - // case 0x45: // CONSTRUCTOR_REFERENCE - // case 0x46: // METHOD_REFERENCE - default: - out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8); - break; - } - if (typePath == null) { - out.putByte(0); - } else { - int length = typePath.b[typePath.offset] * 2 + 1; - out.putByteArray(typePath.b, typePath.offset, length); - } - } -} diff --git a/src/asm/scala/tools/asm/Attribute.java b/src/asm/scala/tools/asm/Attribute.java deleted file mode 100644 index ac40a758a2..0000000000 --- a/src/asm/scala/tools/asm/Attribute.java +++ /dev/null @@ -1,255 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * A non standard class, field, method or code attribute. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public class Attribute { - - /** - * The type of this attribute. - */ - public final String type; - - /** - * The raw value of this attribute, used only for unknown attributes. - */ - byte[] value; - - /** - * The next attribute in this attribute list. May be <tt>null</tt>. - */ - Attribute next; - - /** - * Constructs a new empty attribute. - * - * @param type - * the type of the attribute. - */ - protected Attribute(final String type) { - this.type = type; - } - - /** - * Returns <tt>true</tt> if this type of attribute is unknown. The default - * implementation of this method always returns <tt>true</tt>. - * - * @return <tt>true</tt> if this type of attribute is unknown. - */ - public boolean isUnknown() { - return true; - } - - /** - * Returns <tt>true</tt> if this type of attribute is a code attribute. - * - * @return <tt>true</tt> if this type of attribute is a code attribute. - */ - public boolean isCodeAttribute() { - return false; - } - - /** - * Returns the labels corresponding to this attribute. - * - * @return the labels corresponding to this attribute, or <tt>null</tt> if - * this attribute is not a code attribute that contains labels. - */ - protected Label[] getLabels() { - return null; - } - - /** - * Reads a {@link #type type} attribute. This method must return a - * <i>new</i> {@link Attribute} object, of type {@link #type type}, - * corresponding to the <tt>len</tt> bytes starting at the given offset, in - * the given class reader. - * - * @param cr - * the class that contains the attribute to be read. - * @param off - * index of the first byte of the attribute's content in - * {@link ClassReader#b cr.b}. The 6 attribute header bytes, - * containing the type and the length of the attribute, are not - * taken into account here. - * @param len - * the length of the attribute's content. - * @param buf - * buffer to be used to call {@link ClassReader#readUTF8 - * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass} - * or {@link ClassReader#readConst readConst}. - * @param codeOff - * index of the first byte of code's attribute content in - * {@link ClassReader#b cr.b}, or -1 if the attribute to be read - * is not a code attribute. The 6 attribute header bytes, - * containing the type and the length of the attribute, are not - * taken into account here. - * @param labels - * the labels of the method's code, or <tt>null</tt> if the - * attribute to be read is not a code attribute. - * @return a <i>new</i> {@link Attribute} object corresponding to the given - * bytes. - */ - protected Attribute read(final ClassReader cr, final int off, - final int len, final char[] buf, final int codeOff, - final Label[] labels) { - Attribute attr = new Attribute(type); - attr.value = new byte[len]; - System.arraycopy(cr.b, off, attr.value, 0, len); - return attr; - } - - /** - * Returns the byte array form of this attribute. - * - * @param cw - * the class to which this attribute must be added. This - * parameter can be used to add to the constant pool of this - * class the items that corresponds to this attribute. - * @param code - * the bytecode of the method corresponding to this code - * attribute, or <tt>null</tt> if this attribute is not a code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to this - * code attribute, or <tt>null</tt> if this attribute is not a - * code attribute. - * @param maxStack - * the maximum stack size of the method corresponding to this - * code attribute, or -1 if this attribute is not a code - * attribute. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to this code attribute, or -1 if this attribute - * is not a code attribute. - * @return the byte array form of this attribute. - */ - protected ByteVector write(final ClassWriter cw, final byte[] code, - final int len, final int maxStack, final int maxLocals) { - ByteVector v = new ByteVector(); - v.data = value; - v.length = value.length; - return v; - } - - /** - * Returns the length of the attribute list that begins with this attribute. - * - * @return the length of the attribute list that begins with this attribute. - */ - final int getCount() { - int count = 0; - Attribute attr = this; - while (attr != null) { - count += 1; - attr = attr.next; - } - return count; - } - - /** - * Returns the size of all the attributes in this attribute list. - * - * @param cw - * the class writer to be used to convert the attributes into - * byte arrays, with the {@link #write write} method. - * @param code - * the bytecode of the method corresponding to these code - * attributes, or <tt>null</tt> if these attributes are not code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to - * these code attributes, or <tt>null</tt> if these attributes - * are not code attributes. - * @param maxStack - * the maximum stack size of the method corresponding to these - * code attributes, or -1 if these attributes are not code - * attributes. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to these code attributes, or -1 if these - * attributes are not code attributes. - * @return the size of all the attributes in this attribute list. This size - * includes the size of the attribute headers. - */ - final int getSize(final ClassWriter cw, final byte[] code, final int len, - final int maxStack, final int maxLocals) { - Attribute attr = this; - int size = 0; - while (attr != null) { - cw.newUTF8(attr.type); - size += attr.write(cw, code, len, maxStack, maxLocals).length + 6; - attr = attr.next; - } - return size; - } - - /** - * Writes all the attributes of this attribute list in the given byte - * vector. - * - * @param cw - * the class writer to be used to convert the attributes into - * byte arrays, with the {@link #write write} method. - * @param code - * the bytecode of the method corresponding to these code - * attributes, or <tt>null</tt> if these attributes are not code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to - * these code attributes, or <tt>null</tt> if these attributes - * are not code attributes. - * @param maxStack - * the maximum stack size of the method corresponding to these - * code attributes, or -1 if these attributes are not code - * attributes. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to these code attributes, or -1 if these - * attributes are not code attributes. - * @param out - * where the attributes must be written. - */ - final void put(final ClassWriter cw, final byte[] code, final int len, - final int maxStack, final int maxLocals, final ByteVector out) { - Attribute attr = this; - while (attr != null) { - ByteVector b = attr.write(cw, code, len, maxStack, maxLocals); - out.putShort(cw.newUTF8(attr.type)).putInt(b.length); - out.putByteArray(b.data, 0, b.length); - attr = attr.next; - } - } -} diff --git a/src/asm/scala/tools/asm/ByteVector.java b/src/asm/scala/tools/asm/ByteVector.java deleted file mode 100644 index 3bca7af12a..0000000000 --- a/src/asm/scala/tools/asm/ByteVector.java +++ /dev/null @@ -1,339 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * A dynamically extensible vector of bytes. This class is roughly equivalent to - * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient. - * - * @author Eric Bruneton - */ -public class ByteVector { - - /** - * The content of this vector. - */ - byte[] data; - - /** - * Actual number of bytes in this vector. - */ - int length; - - /** - * Constructs a new {@link ByteVector ByteVector} with a default initial - * size. - */ - public ByteVector() { - data = new byte[64]; - } - - /** - * Constructs a new {@link ByteVector ByteVector} with the given initial - * size. - * - * @param initialSize - * the initial size of the byte vector to be constructed. - */ - public ByteVector(final int initialSize) { - data = new byte[initialSize]; - } - - /** - * Puts a byte into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param b - * a byte. - * @return this byte vector. - */ - public ByteVector putByte(final int b) { - int length = this.length; - if (length + 1 > data.length) { - enlarge(1); - } - data[length++] = (byte) b; - this.length = length; - return this; - } - - /** - * Puts two bytes into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param b1 - * a byte. - * @param b2 - * another byte. - * @return this byte vector. - */ - ByteVector put11(final int b1, final int b2) { - int length = this.length; - if (length + 2 > data.length) { - enlarge(2); - } - byte[] data = this.data; - data[length++] = (byte) b1; - data[length++] = (byte) b2; - this.length = length; - return this; - } - - /** - * Puts a short into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param s - * a short. - * @return this byte vector. - */ - public ByteVector putShort(final int s) { - int length = this.length; - if (length + 2 > data.length) { - enlarge(2); - } - byte[] data = this.data; - data[length++] = (byte) (s >>> 8); - data[length++] = (byte) s; - this.length = length; - return this; - } - - /** - * Puts a byte and a short into this byte vector. The byte vector is - * automatically enlarged if necessary. - * - * @param b - * a byte. - * @param s - * a short. - * @return this byte vector. - */ - ByteVector put12(final int b, final int s) { - int length = this.length; - if (length + 3 > data.length) { - enlarge(3); - } - byte[] data = this.data; - data[length++] = (byte) b; - data[length++] = (byte) (s >>> 8); - data[length++] = (byte) s; - this.length = length; - return this; - } - - /** - * Puts an int into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param i - * an int. - * @return this byte vector. - */ - public ByteVector putInt(final int i) { - int length = this.length; - if (length + 4 > data.length) { - enlarge(4); - } - byte[] data = this.data; - data[length++] = (byte) (i >>> 24); - data[length++] = (byte) (i >>> 16); - data[length++] = (byte) (i >>> 8); - data[length++] = (byte) i; - this.length = length; - return this; - } - - /** - * Puts a long into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param l - * a long. - * @return this byte vector. - */ - public ByteVector putLong(final long l) { - int length = this.length; - if (length + 8 > data.length) { - enlarge(8); - } - byte[] data = this.data; - int i = (int) (l >>> 32); - data[length++] = (byte) (i >>> 24); - data[length++] = (byte) (i >>> 16); - data[length++] = (byte) (i >>> 8); - data[length++] = (byte) i; - i = (int) l; - data[length++] = (byte) (i >>> 24); - data[length++] = (byte) (i >>> 16); - data[length++] = (byte) (i >>> 8); - data[length++] = (byte) i; - this.length = length; - return this; - } - - /** - * Puts an UTF8 string into this byte vector. The byte vector is - * automatically enlarged if necessary. - * - * @param s - * a String whose UTF8 encoded length must be less than 65536. - * @return this byte vector. - */ - public ByteVector putUTF8(final String s) { - int charLength = s.length(); - if (charLength > 65535) { - throw new IllegalArgumentException(); - } - int len = length; - if (len + 2 + charLength > data.length) { - enlarge(2 + charLength); - } - byte[] data = this.data; - // optimistic algorithm: instead of computing the byte length and then - // serializing the string (which requires two loops), we assume the byte - // length is equal to char length (which is the most frequent case), and - // we start serializing the string right away. During the serialization, - // if we find that this assumption is wrong, we continue with the - // general method. - data[len++] = (byte) (charLength >>> 8); - data[len++] = (byte) charLength; - for (int i = 0; i < charLength; ++i) { - char c = s.charAt(i); - if (c >= '\001' && c <= '\177') { - data[len++] = (byte) c; - } else { - length = len; - return encodeUTF8(s, i, 65535); - } - } - length = len; - return this; - } - - /** - * Puts an UTF8 string into this byte vector. The byte vector is - * automatically enlarged if necessary. The string length is encoded in two - * bytes before the encoded characters, if there is space for that (i.e. if - * this.length - i - 2 >= 0). - * - * @param s - * the String to encode. - * @param i - * the index of the first character to encode. The previous - * characters are supposed to have already been encoded, using - * only one byte per character. - * @param maxByteLength - * the maximum byte length of the encoded string, including the - * already encoded characters. - * @return this byte vector. - */ - ByteVector encodeUTF8(final String s, int i, int maxByteLength) { - int charLength = s.length(); - int byteLength = i; - char c; - for (int j = i; j < charLength; ++j) { - c = s.charAt(j); - if (c >= '\001' && c <= '\177') { - byteLength++; - } else if (c > '\u07FF') { - byteLength += 3; - } else { - byteLength += 2; - } - } - if (byteLength > maxByteLength) { - throw new IllegalArgumentException(); - } - int start = length - i - 2; - if (start >= 0) { - data[start] = (byte) (byteLength >>> 8); - data[start + 1] = (byte) byteLength; - } - if (length + byteLength - i > data.length) { - enlarge(byteLength - i); - } - int len = length; - for (int j = i; j < charLength; ++j) { - c = s.charAt(j); - if (c >= '\001' && c <= '\177') { - data[len++] = (byte) c; - } else if (c > '\u07FF') { - data[len++] = (byte) (0xE0 | c >> 12 & 0xF); - data[len++] = (byte) (0x80 | c >> 6 & 0x3F); - data[len++] = (byte) (0x80 | c & 0x3F); - } else { - data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); - data[len++] = (byte) (0x80 | c & 0x3F); - } - } - length = len; - return this; - } - - /** - * Puts an array of bytes into this byte vector. The byte vector is - * automatically enlarged if necessary. - * - * @param b - * an array of bytes. May be <tt>null</tt> to put <tt>len</tt> - * null bytes into this byte vector. - * @param off - * index of the fist byte of b that must be copied. - * @param len - * number of bytes of b that must be copied. - * @return this byte vector. - */ - public ByteVector putByteArray(final byte[] b, final int off, final int len) { - if (length + len > data.length) { - enlarge(len); - } - if (b != null) { - System.arraycopy(b, off, data, length, len); - } - length += len; - return this; - } - - /** - * Enlarge this byte vector so that it can receive n more bytes. - * - * @param size - * number of additional bytes that this byte vector should be - * able to receive. - */ - private void enlarge(final int size) { - int length1 = 2 * data.length; - int length2 = length + size; - byte[] newData = new byte[length1 > length2 ? length1 : length2]; - System.arraycopy(data, 0, newData, 0, length); - data = newData; - } -} diff --git a/src/asm/scala/tools/asm/ClassReader.java b/src/asm/scala/tools/asm/ClassReader.java deleted file mode 100644 index 8b0e12cb04..0000000000 --- a/src/asm/scala/tools/asm/ClassReader.java +++ /dev/null @@ -1,2496 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -import java.io.IOException; -import java.io.InputStream; - -/** - * A Java class parser to make a {@link ClassVisitor} visit an existing class. - * This class parses a byte array conforming to the Java class file format and - * calls the appropriate visit methods of a given class visitor for each field, - * method and bytecode instruction encountered. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public class ClassReader { - - /** - * True to enable signatures support. - */ - static final boolean SIGNATURES = true; - - /** - * True to enable annotations support. - */ - static final boolean ANNOTATIONS = true; - - /** - * True to enable stack map frames support. - */ - static final boolean FRAMES = true; - - /** - * True to enable bytecode writing support. - */ - static final boolean WRITER = true; - - /** - * True to enable JSR_W and GOTO_W support. - */ - static final boolean RESIZE = true; - - /** - * Flag to skip method code. If this class is set <code>CODE</code> - * attribute won't be visited. This can be used, for example, to retrieve - * annotations for methods and method parameters. - */ - public static final int SKIP_CODE = 1; - - /** - * Flag to skip the debug information in the class. If this flag is set the - * debug information of the class is not visited, i.e. the - * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and - * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be - * called. - */ - public static final int SKIP_DEBUG = 2; - - /** - * Flag to skip the stack map frames in the class. If this flag is set the - * stack map frames of the class is not visited, i.e. the - * {@link MethodVisitor#visitFrame visitFrame} method will not be called. - * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is - * used: it avoids visiting frames that will be ignored and recomputed from - * scratch in the class writer. - */ - public static final int SKIP_FRAMES = 4; - - /** - * Flag to expand the stack map frames. By default stack map frames are - * visited in their original format (i.e. "expanded" for classes whose - * version is less than V1_6, and "compressed" for the other classes). If - * this flag is set, stack map frames are always visited in expanded format - * (this option adds a decompression/recompression step in ClassReader and - * ClassWriter which degrades performances quite a lot). - */ - public static final int EXPAND_FRAMES = 8; - - /** - * The class to be parsed. <i>The content of this array must not be - * modified. This field is intended for {@link Attribute} sub classes, and - * is normally not needed by class generators or adapters.</i> - */ - public final byte[] b; - - /** - * The start index of each constant pool item in {@link #b b}, plus one. The - * one byte offset skips the constant pool item tag that indicates its type. - */ - private final int[] items; - - /** - * The String objects corresponding to the CONSTANT_Utf8 items. This cache - * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item, - * which GREATLY improves performances (by a factor 2 to 3). This caching - * strategy could be extended to all constant pool items, but its benefit - * would not be so great for these items (because they are much less - * expensive to parse than CONSTANT_Utf8 items). - */ - private final String[] strings; - - /** - * Maximum length of the strings contained in the constant pool of the - * class. - */ - private final int maxStringLength; - - /** - * Start index of the class header information (access, name...) in - * {@link #b b}. - */ - public final int header; - - // ------------------------------------------------------------------------ - // Constructors - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link ClassReader} object. - * - * @param b - * the bytecode of the class to be read. - */ - public ClassReader(final byte[] b) { - this(b, 0, b.length); - } - - /** - * Constructs a new {@link ClassReader} object. - * - * @param b - * the bytecode of the class to be read. - * @param off - * the start offset of the class data. - * @param len - * the length of the class data. - */ - public ClassReader(final byte[] b, final int off, final int len) { - this.b = b; - // checks the class version - if (readShort(off + 6) > Opcodes.V1_8) { - throw new IllegalArgumentException(); - } - // parses the constant pool - items = new int[readUnsignedShort(off + 8)]; - int n = items.length; - strings = new String[n]; - int max = 0; - int index = off + 10; - for (int i = 1; i < n; ++i) { - items[i] = index + 1; - int size; - switch (b[index]) { - case ClassWriter.FIELD: - case ClassWriter.METH: - case ClassWriter.IMETH: - case ClassWriter.INT: - case ClassWriter.FLOAT: - case ClassWriter.NAME_TYPE: - case ClassWriter.INDY: - size = 5; - break; - case ClassWriter.LONG: - case ClassWriter.DOUBLE: - size = 9; - ++i; - break; - case ClassWriter.UTF8: - size = 3 + readUnsignedShort(index + 1); - if (size > max) { - max = size; - } - break; - case ClassWriter.HANDLE: - size = 4; - break; - // case ClassWriter.CLASS: - // case ClassWriter.STR: - // case ClassWriter.MTYPE - default: - size = 3; - break; - } - index += size; - } - maxStringLength = max; - // the class header information starts just after the constant pool - header = index; - } - - /** - * Returns the class's access flags (see {@link Opcodes}). This value may - * not reflect Deprecated and Synthetic flags when bytecode is before 1.5 - * and those flags are represented by attributes. - * - * @return the class access flags - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public int getAccess() { - return readUnsignedShort(header); - } - - /** - * Returns the internal name of the class (see - * {@link Type#getInternalName() getInternalName}). - * - * @return the internal class name - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public String getClassName() { - return readClass(header + 2, new char[maxStringLength]); - } - - /** - * Returns the internal of name of the super class (see - * {@link Type#getInternalName() getInternalName}). For interfaces, the - * super class is {@link Object}. - * - * @return the internal name of super class, or <tt>null</tt> for - * {@link Object} class. - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public String getSuperName() { - return readClass(header + 4, new char[maxStringLength]); - } - - /** - * Returns the internal names of the class's interfaces (see - * {@link Type#getInternalName() getInternalName}). - * - * @return the array of internal names for all implemented interfaces or - * <tt>null</tt>. - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public String[] getInterfaces() { - int index = header + 6; - int n = readUnsignedShort(index); - String[] interfaces = new String[n]; - if (n > 0) { - char[] buf = new char[maxStringLength]; - for (int i = 0; i < n; ++i) { - index += 2; - interfaces[i] = readClass(index, buf); - } - } - return interfaces; - } - - /** - * Copies the constant pool data into the given {@link ClassWriter}. Should - * be called before the {@link #accept(ClassVisitor,int)} method. - * - * @param classWriter - * the {@link ClassWriter} to copy constant pool into. - */ - void copyPool(final ClassWriter classWriter) { - char[] buf = new char[maxStringLength]; - int ll = items.length; - Item[] items2 = new Item[ll]; - for (int i = 1; i < ll; i++) { - int index = items[i]; - int tag = b[index - 1]; - Item item = new Item(i); - int nameType; - switch (tag) { - case ClassWriter.FIELD: - case ClassWriter.METH: - case ClassWriter.IMETH: - nameType = items[readUnsignedShort(index + 2)]; - item.set(tag, readClass(index, buf), readUTF8(nameType, buf), - readUTF8(nameType + 2, buf)); - break; - case ClassWriter.INT: - item.set(readInt(index)); - break; - case ClassWriter.FLOAT: - item.set(Float.intBitsToFloat(readInt(index))); - break; - case ClassWriter.NAME_TYPE: - item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf), - null); - break; - case ClassWriter.LONG: - item.set(readLong(index)); - ++i; - break; - case ClassWriter.DOUBLE: - item.set(Double.longBitsToDouble(readLong(index))); - ++i; - break; - case ClassWriter.UTF8: { - String s = strings[i]; - if (s == null) { - index = items[i]; - s = strings[i] = readUTF(index + 2, - readUnsignedShort(index), buf); - } - item.set(tag, s, null, null); - break; - } - case ClassWriter.HANDLE: { - int fieldOrMethodRef = items[readUnsignedShort(index + 1)]; - nameType = items[readUnsignedShort(fieldOrMethodRef + 2)]; - item.set(ClassWriter.HANDLE_BASE + readByte(index), - readClass(fieldOrMethodRef, buf), - readUTF8(nameType, buf), readUTF8(nameType + 2, buf)); - break; - } - case ClassWriter.INDY: - if (classWriter.bootstrapMethods == null) { - copyBootstrapMethods(classWriter, items2, buf); - } - nameType = items[readUnsignedShort(index + 2)]; - item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf), - readUnsignedShort(index)); - break; - // case ClassWriter.STR: - // case ClassWriter.CLASS: - // case ClassWriter.MTYPE - default: - item.set(tag, readUTF8(index, buf), null, null); - break; - } - - int index2 = item.hashCode % items2.length; - item.next = items2[index2]; - items2[index2] = item; - } - - int off = items[1] - 1; - classWriter.pool.putByteArray(b, off, header - off); - classWriter.items = items2; - classWriter.threshold = (int) (0.75d * ll); - classWriter.index = ll; - } - - /** - * Copies the bootstrap method data into the given {@link ClassWriter}. - * Should be called before the {@link #accept(ClassVisitor,int)} method. - * - * @param classWriter - * the {@link ClassWriter} to copy bootstrap methods into. - */ - private void copyBootstrapMethods(final ClassWriter classWriter, - final Item[] items, final char[] c) { - // finds the "BootstrapMethods" attribute - int u = getAttributes(); - boolean found = false; - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - if ("BootstrapMethods".equals(attrName)) { - found = true; - break; - } - u += 6 + readInt(u + 4); - } - if (!found) { - return; - } - // copies the bootstrap methods in the class writer - int boostrapMethodCount = readUnsignedShort(u + 8); - for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) { - int position = v - u - 10; - int hashCode = readConst(readUnsignedShort(v), c).hashCode(); - for (int k = readUnsignedShort(v + 2); k > 0; --k) { - hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode(); - v += 2; - } - v += 4; - Item item = new Item(j); - item.set(position, hashCode & 0x7FFFFFFF); - int index = item.hashCode % items.length; - item.next = items[index]; - items[index] = item; - } - int attrSize = readInt(u + 4); - ByteVector bootstrapMethods = new ByteVector(attrSize + 62); - bootstrapMethods.putByteArray(b, u + 10, attrSize - 2); - classWriter.bootstrapMethodsCount = boostrapMethodCount; - classWriter.bootstrapMethods = bootstrapMethods; - } - - /** - * Constructs a new {@link ClassReader} object. - * - * @param is - * an input stream from which to read the class. - * @throws IOException - * if a problem occurs during reading. - */ - public ClassReader(final InputStream is) throws IOException { - this(readClass(is, false)); - } - - /** - * Constructs a new {@link ClassReader} object. - * - * @param name - * the binary qualified name of the class to be read. - * @throws IOException - * if an exception occurs during reading. - */ - public ClassReader(final String name) throws IOException { - this(readClass( - ClassLoader.getSystemResourceAsStream(name.replace('.', '/') - + ".class"), true)); - } - - /** - * Reads the bytecode of a class. - * - * @param is - * an input stream from which to read the class. - * @param close - * true to close the input stream after reading. - * @return the bytecode read from the given input stream. - * @throws IOException - * if a problem occurs during reading. - */ - private static byte[] readClass(final InputStream is, boolean close) - throws IOException { - if (is == null) { - throw new IOException("Class not found"); - } - try { - byte[] b = new byte[is.available()]; - int len = 0; - while (true) { - int n = is.read(b, len, b.length - len); - if (n == -1) { - if (len < b.length) { - byte[] c = new byte[len]; - System.arraycopy(b, 0, c, 0, len); - b = c; - } - return b; - } - len += n; - if (len == b.length) { - int last = is.read(); - if (last < 0) { - return b; - } - byte[] c = new byte[b.length + 1000]; - System.arraycopy(b, 0, c, 0, len); - c[len++] = (byte) last; - b = c; - } - } - } finally { - if (close) { - is.close(); - } - } - } - - // ------------------------------------------------------------------------ - // Public methods - // ------------------------------------------------------------------------ - - /** - * Makes the given visitor visit the Java class of this {@link ClassReader} - * . This class is the one specified in the constructor (see - * {@link #ClassReader(byte[]) ClassReader}). - * - * @param classVisitor - * the visitor that must visit this class. - * @param flags - * option flags that can be used to modify the default behavior - * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} - * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. - */ - public void accept(final ClassVisitor classVisitor, final int flags) { - accept(classVisitor, new Attribute[0], flags); - } - - /** - * Makes the given visitor visit the Java class of this {@link ClassReader}. - * This class is the one specified in the constructor (see - * {@link #ClassReader(byte[]) ClassReader}). - * - * @param classVisitor - * the visitor that must visit this class. - * @param attrs - * prototypes of the attributes that must be parsed during the - * visit of the class. Any attribute whose type is not equal to - * the type of one the prototypes will not be parsed: its byte - * array value will be passed unchanged to the ClassWriter. - * <i>This may corrupt it if this value contains references to - * the constant pool, or has syntactic or semantic links with a - * class element that has been transformed by a class adapter - * between the reader and the writer</i>. - * @param flags - * option flags that can be used to modify the default behavior - * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} - * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. - */ - public void accept(final ClassVisitor classVisitor, - final Attribute[] attrs, final int flags) { - int u = header; // current offset in the class file - char[] c = new char[maxStringLength]; // buffer used to read strings - - Context context = new Context(); - context.attrs = attrs; - context.flags = flags; - context.buffer = c; - - // reads the class declaration - int access = readUnsignedShort(u); - String name = readClass(u + 2, c); - String superClass = readClass(u + 4, c); - String[] interfaces = new String[readUnsignedShort(u + 6)]; - u += 8; - for (int i = 0; i < interfaces.length; ++i) { - interfaces[i] = readClass(u, c); - u += 2; - } - - // reads the class attributes - String signature = null; - String sourceFile = null; - String sourceDebug = null; - String enclosingOwner = null; - String enclosingName = null; - String enclosingDesc = null; - int anns = 0; - int ianns = 0; - int tanns = 0; - int itanns = 0; - int innerClasses = 0; - Attribute attributes = null; - - u = getAttributes(); - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if ("SourceFile".equals(attrName)) { - sourceFile = readUTF8(u + 8, c); - } else if ("InnerClasses".equals(attrName)) { - innerClasses = u + 8; - } else if ("EnclosingMethod".equals(attrName)) { - enclosingOwner = readClass(u + 8, c); - int item = readUnsignedShort(u + 10); - if (item != 0) { - enclosingName = readUTF8(items[item], c); - enclosingDesc = readUTF8(items[item] + 2, c); - } - } else if (SIGNATURES && "Signature".equals(attrName)) { - signature = readUTF8(u + 8, c); - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { - anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { - tanns = u + 8; - } else if ("Deprecated".equals(attrName)) { - access |= Opcodes.ACC_DEPRECATED; - } else if ("Synthetic".equals(attrName)) { - access |= Opcodes.ACC_SYNTHETIC - | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if ("SourceDebugExtension".equals(attrName)) { - int len = readInt(u + 4); - sourceDebug = readUTF(u + 8, len, new char[len]); - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { - ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { - itanns = u + 8; - } else if ("BootstrapMethods".equals(attrName)) { - int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; - for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { - bootstrapMethods[j] = v; - v += 2 + readUnsignedShort(v + 2) << 1; - } - context.bootstrapMethods = bootstrapMethods; - } else { - Attribute attr = readAttribute(attrs, attrName, u + 8, - readInt(u + 4), c, -1, null); - if (attr != null) { - attr.next = attributes; - attributes = attr; - } - } - u += 6 + readInt(u + 4); - } - - // visits the class declaration - classVisitor.visit(readInt(items[1] - 7), access, name, signature, - superClass, interfaces); - - // visits the source and debug info - if ((flags & SKIP_DEBUG) == 0 - && (sourceFile != null || sourceDebug != null)) { - classVisitor.visitSource(sourceFile, sourceDebug); - } - - // visits the outer class - if (enclosingOwner != null) { - classVisitor.visitOuterClass(enclosingOwner, enclosingName, - enclosingDesc); - } - - // visits the class annotations and type annotations - if (ANNOTATIONS && anns != 0) { - for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitAnnotation(readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && ianns != 0) { - for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitAnnotation(readUTF8(v, c), false)); - } - } - if (ANNOTATIONS && tanns != 0) { - for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && itanns != 0) { - for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), false)); - } - } - - // visits the attributes - while (attributes != null) { - Attribute attr = attributes.next; - attributes.next = null; - classVisitor.visitAttribute(attributes); - attributes = attr; - } - - // visits the inner classes - if (innerClasses != 0) { - int v = innerClasses + 2; - for (int i = readUnsignedShort(innerClasses); i > 0; --i) { - classVisitor.visitInnerClass(readClass(v, c), - readClass(v + 2, c), readUTF8(v + 4, c), - readUnsignedShort(v + 6)); - v += 8; - } - } - - // visits the fields and methods - u = header + 10 + 2 * interfaces.length; - for (int i = readUnsignedShort(u - 2); i > 0; --i) { - u = readField(classVisitor, context, u); - } - u += 2; - for (int i = readUnsignedShort(u - 2); i > 0; --i) { - u = readMethod(classVisitor, context, u); - } - - // visits the end of the class - classVisitor.visitEnd(); - } - - /** - * Reads a field and makes the given visitor visit it. - * - * @param classVisitor - * the visitor that must visit the field. - * @param context - * information about the class being parsed. - * @param u - * the start offset of the field in the class file. - * @return the offset of the first byte following the field in the class. - */ - private int readField(final ClassVisitor classVisitor, - final Context context, int u) { - // reads the field declaration - char[] c = context.buffer; - int access = readUnsignedShort(u); - String name = readUTF8(u + 2, c); - String desc = readUTF8(u + 4, c); - u += 6; - - // reads the field attributes - String signature = null; - int anns = 0; - int ianns = 0; - int tanns = 0; - int itanns = 0; - Object value = null; - Attribute attributes = null; - - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if ("ConstantValue".equals(attrName)) { - int item = readUnsignedShort(u + 8); - value = item == 0 ? null : readConst(item, c); - } else if (SIGNATURES && "Signature".equals(attrName)) { - signature = readUTF8(u + 8, c); - } else if ("Deprecated".equals(attrName)) { - access |= Opcodes.ACC_DEPRECATED; - } else if ("Synthetic".equals(attrName)) { - access |= Opcodes.ACC_SYNTHETIC - | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { - anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { - tanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { - ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { - itanns = u + 8; - } else { - Attribute attr = readAttribute(context.attrs, attrName, u + 8, - readInt(u + 4), c, -1, null); - if (attr != null) { - attr.next = attributes; - attributes = attr; - } - } - u += 6 + readInt(u + 4); - } - u += 2; - - // visits the field declaration - FieldVisitor fv = classVisitor.visitField(access, name, desc, - signature, value); - if (fv == null) { - return u; - } - - // visits the field annotations and type annotations - if (ANNOTATIONS && anns != 0) { - for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - fv.visitAnnotation(readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && ianns != 0) { - for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - fv.visitAnnotation(readUTF8(v, c), false)); - } - } - if (ANNOTATIONS && tanns != 0) { - for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - fv.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && itanns != 0) { - for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - fv.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), false)); - } - } - - // visits the field attributes - while (attributes != null) { - Attribute attr = attributes.next; - attributes.next = null; - fv.visitAttribute(attributes); - attributes = attr; - } - - // visits the end of the field - fv.visitEnd(); - - return u; - } - - /** - * Reads a method and makes the given visitor visit it. - * - * @param classVisitor - * the visitor that must visit the method. - * @param context - * information about the class being parsed. - * @param u - * the start offset of the method in the class file. - * @return the offset of the first byte following the method in the class. - */ - private int readMethod(final ClassVisitor classVisitor, - final Context context, int u) { - // reads the method declaration - char[] c = context.buffer; - context.access = readUnsignedShort(u); - context.name = readUTF8(u + 2, c); - context.desc = readUTF8(u + 4, c); - u += 6; - - // reads the method attributes - int code = 0; - int exception = 0; - String[] exceptions = null; - String signature = null; - int methodParameters = 0; - int anns = 0; - int ianns = 0; - int tanns = 0; - int itanns = 0; - int dann = 0; - int mpanns = 0; - int impanns = 0; - int firstAttribute = u; - Attribute attributes = null; - - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if ("Code".equals(attrName)) { - if ((context.flags & SKIP_CODE) == 0) { - code = u + 8; - } - } else if ("Exceptions".equals(attrName)) { - exceptions = new String[readUnsignedShort(u + 8)]; - exception = u + 10; - for (int j = 0; j < exceptions.length; ++j) { - exceptions[j] = readClass(exception, c); - exception += 2; - } - } else if (SIGNATURES && "Signature".equals(attrName)) { - signature = readUTF8(u + 8, c); - } else if ("Deprecated".equals(attrName)) { - context.access |= Opcodes.ACC_DEPRECATED; - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { - anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { - tanns = u + 8; - } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { - dann = u + 8; - } else if ("Synthetic".equals(attrName)) { - context.access |= Opcodes.ACC_SYNTHETIC - | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { - ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { - itanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleParameterAnnotations".equals(attrName)) { - mpanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleParameterAnnotations".equals(attrName)) { - impanns = u + 8; - } else if ("MethodParameters".equals(attrName)) { - methodParameters = u + 8; - } else { - Attribute attr = readAttribute(context.attrs, attrName, u + 8, - readInt(u + 4), c, -1, null); - if (attr != null) { - attr.next = attributes; - attributes = attr; - } - } - u += 6 + readInt(u + 4); - } - u += 2; - - // visits the method declaration - MethodVisitor mv = classVisitor.visitMethod(context.access, - context.name, context.desc, signature, exceptions); - if (mv == null) { - return u; - } - - /* - * if the returned MethodVisitor is in fact a MethodWriter, it means - * there is no method adapter between the reader and the writer. If, in - * addition, the writer's constant pool was copied from this reader - * (mw.cw.cr == this), and the signature and exceptions of the method - * have not been changed, then it is possible to skip all visit events - * and just copy the original code of the method to the writer (the - * access, name and descriptor can have been changed, this is not - * important since they are not copied as is from the reader). - */ - if (WRITER && mv instanceof MethodWriter) { - MethodWriter mw = (MethodWriter) mv; - if (mw.cw.cr == this && signature == mw.signature) { - boolean sameExceptions = false; - if (exceptions == null) { - sameExceptions = mw.exceptionCount == 0; - } else if (exceptions.length == mw.exceptionCount) { - sameExceptions = true; - for (int j = exceptions.length - 1; j >= 0; --j) { - exception -= 2; - if (mw.exceptions[j] != readUnsignedShort(exception)) { - sameExceptions = false; - break; - } - } - } - if (sameExceptions) { - /* - * we do not copy directly the code into MethodWriter to - * save a byte array copy operation. The real copy will be - * done in ClassWriter.toByteArray(). - */ - mw.classReaderOffset = firstAttribute; - mw.classReaderLength = u - firstAttribute; - return u; - } - } - } - - // visit the method parameters - if (methodParameters != 0) { - for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) { - mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2)); - } - } - - // visits the method annotations - if (ANNOTATIONS && dann != 0) { - AnnotationVisitor dv = mv.visitAnnotationDefault(); - readAnnotationValue(dann, c, null, dv); - if (dv != null) { - dv.visitEnd(); - } - } - if (ANNOTATIONS && anns != 0) { - for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - mv.visitAnnotation(readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && ianns != 0) { - for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - mv.visitAnnotation(readUTF8(v, c), false)); - } - } - if (ANNOTATIONS && tanns != 0) { - for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - mv.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && itanns != 0) { - for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { - v = readAnnotationTarget(context, v); - v = readAnnotationValues(v + 2, c, true, - mv.visitTypeAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), false)); - } - } - if (ANNOTATIONS && mpanns != 0) { - readParameterAnnotations(mv, context, mpanns, true); - } - if (ANNOTATIONS && impanns != 0) { - readParameterAnnotations(mv, context, impanns, false); - } - - // visits the method attributes - while (attributes != null) { - Attribute attr = attributes.next; - attributes.next = null; - mv.visitAttribute(attributes); - attributes = attr; - } - - // visits the method code - if (code != 0) { - mv.visitCode(); - readCode(mv, context, code); - } - - // visits the end of the method - mv.visitEnd(); - - return u; - } - - /** - * Reads the bytecode of a method and makes the given visitor visit it. - * - * @param mv - * the visitor that must visit the method's code. - * @param context - * information about the class being parsed. - * @param u - * the start offset of the code attribute in the class file. - */ - private void readCode(final MethodVisitor mv, final Context context, int u) { - // reads the header - byte[] b = this.b; - char[] c = context.buffer; - int maxStack = readUnsignedShort(u); - int maxLocals = readUnsignedShort(u + 2); - int codeLength = readInt(u + 4); - u += 8; - - // reads the bytecode to find the labels - int codeStart = u; - int codeEnd = u + codeLength; - Label[] labels = context.labels = new Label[codeLength + 2]; - readLabel(codeLength + 1, labels); - while (u < codeEnd) { - int offset = u - codeStart; - int opcode = b[u] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - u += 1; - break; - case ClassWriter.LABEL_INSN: - readLabel(offset + readShort(u + 1), labels); - u += 3; - break; - case ClassWriter.LABELW_INSN: - readLabel(offset + readInt(u + 1), labels); - u += 5; - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - u += 6; - } else { - u += 4; - } - break; - case ClassWriter.TABL_INSN: - // skips 0 to 3 padding bytes - u = u + 4 - (offset & 3); - // reads instruction - readLabel(offset + readInt(u), labels); - for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) { - readLabel(offset + readInt(u + 12), labels); - u += 4; - } - u += 12; - break; - case ClassWriter.LOOK_INSN: - // skips 0 to 3 padding bytes - u = u + 4 - (offset & 3); - // reads instruction - readLabel(offset + readInt(u), labels); - for (int i = readInt(u + 4); i > 0; --i) { - readLabel(offset + readInt(u + 12), labels); - u += 8; - } - u += 8; - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - u += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - u += 3; - break; - case ClassWriter.ITFMETH_INSN: - case ClassWriter.INDYMETH_INSN: - u += 5; - break; - // case MANA_INSN: - default: - u += 4; - break; - } - } - - // reads the try catch entries to find the labels, and also visits them - for (int i = readUnsignedShort(u); i > 0; --i) { - Label start = readLabel(readUnsignedShort(u + 2), labels); - Label end = readLabel(readUnsignedShort(u + 4), labels); - Label handler = readLabel(readUnsignedShort(u + 6), labels); - String type = readUTF8(items[readUnsignedShort(u + 8)], c); - mv.visitTryCatchBlock(start, end, handler, type); - u += 8; - } - u += 2; - - // reads the code attributes - int[] tanns = null; // start index of each visible type annotation - int[] itanns = null; // start index of each invisible type annotation - int tann = 0; // current index in tanns array - int itann = 0; // current index in itanns array - int ntoff = -1; // next visible type annotation code offset - int nitoff = -1; // next invisible type annotation code offset - int varTable = 0; - int varTypeTable = 0; - boolean zip = true; - boolean unzip = (context.flags & EXPAND_FRAMES) != 0; - int stackMap = 0; - int stackMapSize = 0; - int frameCount = 0; - Context frame = null; - Attribute attributes = null; - - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - if ("LocalVariableTable".equals(attrName)) { - if ((context.flags & SKIP_DEBUG) == 0) { - varTable = u + 8; - for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { - int label = readUnsignedShort(v + 10); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } - label += readUnsignedShort(v + 12); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } - v += 10; - } - } - } else if ("LocalVariableTypeTable".equals(attrName)) { - varTypeTable = u + 8; - } else if ("LineNumberTable".equals(attrName)) { - if ((context.flags & SKIP_DEBUG) == 0) { - for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { - int label = readUnsignedShort(v + 10); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } - labels[label].line = readUnsignedShort(v + 12); - v += 4; - } - } - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { - tanns = readTypeAnnotations(mv, context, u + 8, true); - ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1 - : readUnsignedShort(tanns[0] + 1); - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { - itanns = readTypeAnnotations(mv, context, u + 8, false); - nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1 - : readUnsignedShort(itanns[0] + 1); - } else if (FRAMES && "StackMapTable".equals(attrName)) { - if ((context.flags & SKIP_FRAMES) == 0) { - stackMap = u + 10; - stackMapSize = readInt(u + 4); - frameCount = readUnsignedShort(u + 8); - } - /* - * here we do not extract the labels corresponding to the - * attribute content. This would require a full parsing of the - * attribute, which would need to be repeated in the second - * phase (see below). Instead the content of the attribute is - * read one frame at a time (i.e. after a frame has been - * visited, the next frame is read), and the labels it contains - * are also extracted one frame at a time. Thanks to the - * ordering of frames, having only a "one frame lookahead" is - * not a problem, i.e. it is not possible to see an offset - * smaller than the offset of the current insn and for which no - * Label exist. - */ - /* - * This is not true for UNINITIALIZED type offsets. We solve - * this by parsing the stack map table without a full decoding - * (see below). - */ - } else if (FRAMES && "StackMap".equals(attrName)) { - if ((context.flags & SKIP_FRAMES) == 0) { - zip = false; - stackMap = u + 10; - stackMapSize = readInt(u + 4); - frameCount = readUnsignedShort(u + 8); - } - /* - * IMPORTANT! here we assume that the frames are ordered, as in - * the StackMapTable attribute, although this is not guaranteed - * by the attribute format. - */ - } else { - for (int j = 0; j < context.attrs.length; ++j) { - if (context.attrs[j].type.equals(attrName)) { - Attribute attr = context.attrs[j].read(this, u + 8, - readInt(u + 4), c, codeStart - 8, labels); - if (attr != null) { - attr.next = attributes; - attributes = attr; - } - } - } - } - u += 6 + readInt(u + 4); - } - u += 2; - - // generates the first (implicit) stack map frame - if (FRAMES && stackMap != 0) { - /* - * for the first explicit frame the offset is not offset_delta + 1 - * but only offset_delta; setting the implicit frame offset to -1 - * allow the use of the "offset_delta + 1" rule in all cases - */ - frame = context; - frame.offset = -1; - frame.mode = 0; - frame.localCount = 0; - frame.localDiff = 0; - frame.stackCount = 0; - frame.local = new Object[maxLocals]; - frame.stack = new Object[maxStack]; - if (unzip) { - getImplicitFrame(context); - } - /* - * Finds labels for UNINITIALIZED frame types. Instead of decoding - * each element of the stack map table, we look for 3 consecutive - * bytes that "look like" an UNINITIALIZED type (tag 8, offset - * within code bounds, NEW instruction at this offset). We may find - * false positives (i.e. not real UNINITIALIZED types), but this - * should be rare, and the only consequence will be the creation of - * an unneeded label. This is better than creating a label for each - * NEW instruction, and faster than fully decoding the whole stack - * map table. - */ - for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) { - if (b[i] == 8) { // UNINITIALIZED FRAME TYPE - int v = readUnsignedShort(i + 1); - if (v >= 0 && v < codeLength) { - if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) { - readLabel(v, labels); - } - } - } - } - } - - // visits the instructions - u = codeStart; - while (u < codeEnd) { - int offset = u - codeStart; - - // visits the label and line number for this offset, if any - Label l = labels[offset]; - if (l != null) { - mv.visitLabel(l); - if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) { - mv.visitLineNumber(l.line, l); - } - } - - // visits the frame for this offset, if any - while (FRAMES && frame != null - && (frame.offset == offset || frame.offset == -1)) { - // if there is a frame for this offset, makes the visitor visit - // it, and reads the next frame if there is one. - if (frame.offset != -1) { - if (!zip || unzip) { - mv.visitFrame(Opcodes.F_NEW, frame.localCount, - frame.local, frame.stackCount, frame.stack); - } else { - mv.visitFrame(frame.mode, frame.localDiff, frame.local, - frame.stackCount, frame.stack); - } - } - if (frameCount > 0) { - stackMap = readFrame(stackMap, zip, unzip, frame); - --frameCount; - } else { - frame = null; - } - } - - // visits the instruction at this offset - int opcode = b[u] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - mv.visitInsn(opcode); - u += 1; - break; - case ClassWriter.IMPLVAR_INSN: - if (opcode > Opcodes.ISTORE) { - opcode -= 59; // ISTORE_0 - mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), - opcode & 0x3); - } else { - opcode -= 26; // ILOAD_0 - mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3); - } - u += 1; - break; - case ClassWriter.LABEL_INSN: - mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]); - u += 3; - break; - case ClassWriter.LABELW_INSN: - mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]); - u += 5; - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4)); - u += 6; - } else { - mv.visitVarInsn(opcode, readUnsignedShort(u + 2)); - u += 4; - } - break; - case ClassWriter.TABL_INSN: { - // skips 0 to 3 padding bytes - u = u + 4 - (offset & 3); - // reads instruction - int label = offset + readInt(u); - int min = readInt(u + 4); - int max = readInt(u + 8); - Label[] table = new Label[max - min + 1]; - u += 12; - for (int i = 0; i < table.length; ++i) { - table[i] = labels[offset + readInt(u)]; - u += 4; - } - mv.visitTableSwitchInsn(min, max, labels[label], table); - break; - } - case ClassWriter.LOOK_INSN: { - // skips 0 to 3 padding bytes - u = u + 4 - (offset & 3); - // reads instruction - int label = offset + readInt(u); - int len = readInt(u + 4); - int[] keys = new int[len]; - Label[] values = new Label[len]; - u += 8; - for (int i = 0; i < len; ++i) { - keys[i] = readInt(u); - values[i] = labels[offset + readInt(u + 4)]; - u += 8; - } - mv.visitLookupSwitchInsn(labels[label], keys, values); - break; - } - case ClassWriter.VAR_INSN: - mv.visitVarInsn(opcode, b[u + 1] & 0xFF); - u += 2; - break; - case ClassWriter.SBYTE_INSN: - mv.visitIntInsn(opcode, b[u + 1]); - u += 2; - break; - case ClassWriter.SHORT_INSN: - mv.visitIntInsn(opcode, readShort(u + 1)); - u += 3; - break; - case ClassWriter.LDC_INSN: - mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c)); - u += 2; - break; - case ClassWriter.LDCW_INSN: - mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c)); - u += 3; - break; - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.ITFMETH_INSN: { - int cpIndex = items[readUnsignedShort(u + 1)]; - boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; - String iowner = readClass(cpIndex, c); - cpIndex = items[readUnsignedShort(cpIndex + 2)]; - String iname = readUTF8(cpIndex, c); - String idesc = readUTF8(cpIndex + 2, c); - if (opcode < Opcodes.INVOKEVIRTUAL) { - mv.visitFieldInsn(opcode, iowner, iname, idesc); - } else { - mv.visitMethodInsn(opcode, iowner, iname, idesc, itf); - } - if (opcode == Opcodes.INVOKEINTERFACE) { - u += 5; - } else { - u += 3; - } - break; - } - case ClassWriter.INDYMETH_INSN: { - int cpIndex = items[readUnsignedShort(u + 1)]; - int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)]; - Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c); - int bsmArgCount = readUnsignedShort(bsmIndex + 2); - Object[] bsmArgs = new Object[bsmArgCount]; - bsmIndex += 4; - for (int i = 0; i < bsmArgCount; i++) { - bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c); - bsmIndex += 2; - } - cpIndex = items[readUnsignedShort(cpIndex + 2)]; - String iname = readUTF8(cpIndex, c); - String idesc = readUTF8(cpIndex + 2, c); - mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs); - u += 5; - break; - } - case ClassWriter.TYPE_INSN: - mv.visitTypeInsn(opcode, readClass(u + 1, c)); - u += 3; - break; - case ClassWriter.IINC_INSN: - mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]); - u += 3; - break; - // case MANA_INSN: - default: - mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF); - u += 4; - break; - } - - // visit the instruction annotations, if any - while (tanns != null && tann < tanns.length && ntoff <= offset) { - if (ntoff == offset) { - int v = readAnnotationTarget(context, tanns[tann]); - readAnnotationValues(v + 2, c, true, - mv.visitInsnAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), true)); - } - ntoff = ++tann >= tanns.length || readByte(tanns[tann]) < 0x43 ? -1 - : readUnsignedShort(tanns[tann] + 1); - } - while (itanns != null && itann < itanns.length && nitoff <= offset) { - if (nitoff == offset) { - int v = readAnnotationTarget(context, itanns[itann]); - readAnnotationValues(v + 2, c, true, - mv.visitInsnAnnotation(context.typeRef, - context.typePath, readUTF8(v, c), false)); - } - nitoff = ++itann >= itanns.length - || readByte(itanns[itann]) < 0x43 ? -1 - : readUnsignedShort(itanns[itann] + 1); - } - } - if (labels[codeLength] != null) { - mv.visitLabel(labels[codeLength]); - } - - // visits the local variable tables - if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) { - int[] typeTable = null; - if (varTypeTable != 0) { - u = varTypeTable + 2; - typeTable = new int[readUnsignedShort(varTypeTable) * 3]; - for (int i = typeTable.length; i > 0;) { - typeTable[--i] = u + 6; // signature - typeTable[--i] = readUnsignedShort(u + 8); // index - typeTable[--i] = readUnsignedShort(u); // start - u += 10; - } - } - u = varTable + 2; - for (int i = readUnsignedShort(varTable); i > 0; --i) { - int start = readUnsignedShort(u); - int length = readUnsignedShort(u + 2); - int index = readUnsignedShort(u + 8); - String vsignature = null; - if (typeTable != null) { - for (int j = 0; j < typeTable.length; j += 3) { - if (typeTable[j] == start && typeTable[j + 1] == index) { - vsignature = readUTF8(typeTable[j + 2], c); - break; - } - } - } - mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c), - vsignature, labels[start], labels[start + length], - index); - u += 10; - } - } - - // visits the local variables type annotations - if (tanns != null) { - for (int i = 0; i < tanns.length; ++i) { - if ((readByte(tanns[i]) >> 1) == (0x40 >> 1)) { - int v = readAnnotationTarget(context, tanns[i]); - v = readAnnotationValues(v + 2, c, true, - mv.visitLocalVariableAnnotation(context.typeRef, - context.typePath, context.start, - context.end, context.index, readUTF8(v, c), - true)); - } - } - } - if (itanns != null) { - for (int i = 0; i < itanns.length; ++i) { - if ((readByte(itanns[i]) >> 1) == (0x40 >> 1)) { - int v = readAnnotationTarget(context, itanns[i]); - v = readAnnotationValues(v + 2, c, true, - mv.visitLocalVariableAnnotation(context.typeRef, - context.typePath, context.start, - context.end, context.index, readUTF8(v, c), - false)); - } - } - } - - // visits the code attributes - while (attributes != null) { - Attribute attr = attributes.next; - attributes.next = null; - mv.visitAttribute(attributes); - attributes = attr; - } - - // visits the max stack and max locals values - mv.visitMaxs(maxStack, maxLocals); - } - - /** - * Parses a type annotation table to find the labels, and to visit the try - * catch block annotations. - * - * @param u - * the start offset of a type annotation table. - * @param mv - * the method visitor to be used to visit the try catch block - * annotations. - * @param context - * information about the class being parsed. - * @param visible - * if the type annotation table to parse contains runtime visible - * annotations. - * @return the start offset of each type annotation in the parsed table. - */ - private int[] readTypeAnnotations(final MethodVisitor mv, - final Context context, int u, boolean visible) { - char[] c = context.buffer; - int[] offsets = new int[readUnsignedShort(u)]; - u += 2; - for (int i = 0; i < offsets.length; ++i) { - offsets[i] = u; - int target = readInt(u); - switch (target >>> 24) { - case 0x00: // CLASS_TYPE_PARAMETER - case 0x01: // METHOD_TYPE_PARAMETER - case 0x16: // METHOD_FORMAL_PARAMETER - u += 2; - break; - case 0x13: // FIELD - case 0x14: // METHOD_RETURN - case 0x15: // METHOD_RECEIVER - u += 1; - break; - case 0x40: // LOCAL_VARIABLE - case 0x41: // RESOURCE_VARIABLE - for (int j = readUnsignedShort(u + 1); j > 0; --j) { - int start = readUnsignedShort(u + 3); - int length = readUnsignedShort(u + 5); - readLabel(start, context.labels); - readLabel(start + length, context.labels); - u += 6; - } - u += 3; - break; - case 0x47: // CAST - case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT - case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT - u += 4; - break; - // case 0x10: // CLASS_EXTENDS - // case 0x11: // CLASS_TYPE_PARAMETER_BOUND - // case 0x12: // METHOD_TYPE_PARAMETER_BOUND - // case 0x17: // THROWS - // case 0x42: // EXCEPTION_PARAMETER - // case 0x43: // INSTANCEOF - // case 0x44: // NEW - // case 0x45: // CONSTRUCTOR_REFERENCE - // case 0x46: // METHOD_REFERENCE - default: - u += 3; - break; - } - int pathLength = readByte(u); - if ((target >>> 24) == 0x42) { - TypePath path = pathLength == 0 ? null : new TypePath(b, u); - u += 1 + 2 * pathLength; - u = readAnnotationValues(u + 2, c, true, - mv.visitTryCatchAnnotation(target, path, - readUTF8(u, c), visible)); - } else { - u = readAnnotationValues(u + 3 + 2 * pathLength, c, true, null); - } - } - return offsets; - } - - /** - * Parses the header of a type annotation to extract its target_type and - * target_path (the result is stored in the given context), and returns the - * start offset of the rest of the type_annotation structure (i.e. the - * offset to the type_index field, which is followed by - * num_element_value_pairs and then the name,value pairs). - * - * @param context - * information about the class being parsed. This is where the - * extracted target_type and target_path must be stored. - * @param u - * the start offset of a type_annotation structure. - * @return the start offset of the rest of the type_annotation structure. - */ - private int readAnnotationTarget(final Context context, int u) { - int target = readInt(u); - switch (target >>> 24) { - case 0x00: // CLASS_TYPE_PARAMETER - case 0x01: // METHOD_TYPE_PARAMETER - case 0x16: // METHOD_FORMAL_PARAMETER - target &= 0xFFFF0000; - u += 2; - break; - case 0x13: // FIELD - case 0x14: // METHOD_RETURN - case 0x15: // METHOD_RECEIVER - target &= 0xFF000000; - u += 1; - break; - case 0x40: // LOCAL_VARIABLE - case 0x41: { // RESOURCE_VARIABLE - target &= 0xFF000000; - int n = readUnsignedShort(u + 1); - context.start = new Label[n]; - context.end = new Label[n]; - context.index = new int[n]; - u += 3; - for (int i = 0; i < n; ++i) { - int start = readUnsignedShort(u); - int length = readUnsignedShort(u + 2); - context.start[i] = readLabel(start, context.labels); - context.end[i] = readLabel(start + length, context.labels); - context.index[i] = readUnsignedShort(u + 4); - u += 6; - } - break; - } - case 0x47: // CAST - case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT - case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT - target &= 0xFF0000FF; - u += 4; - break; - // case 0x10: // CLASS_EXTENDS - // case 0x11: // CLASS_TYPE_PARAMETER_BOUND - // case 0x12: // METHOD_TYPE_PARAMETER_BOUND - // case 0x17: // THROWS - // case 0x42: // EXCEPTION_PARAMETER - // case 0x43: // INSTANCEOF - // case 0x44: // NEW - // case 0x45: // CONSTRUCTOR_REFERENCE - // case 0x46: // METHOD_REFERENCE - default: - target &= (target >>> 24) < 0x43 ? 0xFFFFFF00 : 0xFF000000; - u += 3; - break; - } - int pathLength = readByte(u); - context.typeRef = target; - context.typePath = pathLength == 0 ? null : new TypePath(b, u); - return u + 1 + 2 * pathLength; - } - - /** - * Reads parameter annotations and makes the given visitor visit them. - * - * @param mv - * the visitor that must visit the annotations. - * @param context - * information about the class being parsed. - * @param v - * start offset in {@link #b b} of the annotations to be read. - * @param visible - * <tt>true</tt> if the annotations to be read are visible at - * runtime. - */ - private void readParameterAnnotations(final MethodVisitor mv, - final Context context, int v, final boolean visible) { - int i; - int n = b[v++] & 0xFF; - // workaround for a bug in javac (javac compiler generates a parameter - // annotation array whose size is equal to the number of parameters in - // the Java source file, while it should generate an array whose size is - // equal to the number of parameters in the method descriptor - which - // includes the synthetic parameters added by the compiler). This work- - // around supposes that the synthetic parameters are the first ones. - int synthetics = Type.getArgumentTypes(context.desc).length - n; - AnnotationVisitor av; - for (i = 0; i < synthetics; ++i) { - // virtual annotation to detect synthetic parameters in MethodWriter - av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false); - if (av != null) { - av.visitEnd(); - } - } - char[] c = context.buffer; - for (; i < n + synthetics; ++i) { - int j = readUnsignedShort(v); - v += 2; - for (; j > 0; --j) { - av = mv.visitParameterAnnotation(i, readUTF8(v, c), visible); - v = readAnnotationValues(v + 2, c, true, av); - } - } - } - - /** - * Reads the values of an annotation and makes the given visitor visit them. - * - * @param v - * the start offset in {@link #b b} of the values to be read - * (including the unsigned short that gives the number of - * values). - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param named - * if the annotation values are named or not. - * @param av - * the visitor that must visit the values. - * @return the end offset of the annotation values. - */ - private int readAnnotationValues(int v, final char[] buf, - final boolean named, final AnnotationVisitor av) { - int i = readUnsignedShort(v); - v += 2; - if (named) { - for (; i > 0; --i) { - v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av); - } - } else { - for (; i > 0; --i) { - v = readAnnotationValue(v, buf, null, av); - } - } - if (av != null) { - av.visitEnd(); - } - return v; - } - - /** - * Reads a value of an annotation and makes the given visitor visit it. - * - * @param v - * the start offset in {@link #b b} of the value to be read - * (<i>not including the value name constant pool index</i>). - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param name - * the name of the value to be read. - * @param av - * the visitor that must visit the value. - * @return the end offset of the annotation value. - */ - private int readAnnotationValue(int v, final char[] buf, final String name, - final AnnotationVisitor av) { - int i; - if (av == null) { - switch (b[v] & 0xFF) { - case 'e': // enum_const_value - return v + 5; - case '@': // annotation_value - return readAnnotationValues(v + 3, buf, true, null); - case '[': // array_value - return readAnnotationValues(v + 1, buf, false, null); - default: - return v + 3; - } - } - switch (b[v++] & 0xFF) { - case 'I': // pointer to CONSTANT_Integer - case 'J': // pointer to CONSTANT_Long - case 'F': // pointer to CONSTANT_Float - case 'D': // pointer to CONSTANT_Double - av.visit(name, readConst(readUnsignedShort(v), buf)); - v += 2; - break; - case 'B': // pointer to CONSTANT_Byte - av.visit(name, - new Byte((byte) readInt(items[readUnsignedShort(v)]))); - v += 2; - break; - case 'Z': // pointer to CONSTANT_Boolean - av.visit(name, - readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE - : Boolean.TRUE); - v += 2; - break; - case 'S': // pointer to CONSTANT_Short - av.visit(name, new Short( - (short) readInt(items[readUnsignedShort(v)]))); - v += 2; - break; - case 'C': // pointer to CONSTANT_Char - av.visit(name, new Character( - (char) readInt(items[readUnsignedShort(v)]))); - v += 2; - break; - case 's': // pointer to CONSTANT_Utf8 - av.visit(name, readUTF8(v, buf)); - v += 2; - break; - case 'e': // enum_const_value - av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf)); - v += 4; - break; - case 'c': // class_info - av.visit(name, Type.getType(readUTF8(v, buf))); - v += 2; - break; - case '@': // annotation_value - v = readAnnotationValues(v + 2, buf, true, - av.visitAnnotation(name, readUTF8(v, buf))); - break; - case '[': // array_value - int size = readUnsignedShort(v); - v += 2; - if (size == 0) { - return readAnnotationValues(v - 2, buf, false, - av.visitArray(name)); - } - switch (this.b[v++] & 0xFF) { - case 'B': - byte[] bv = new byte[size]; - for (i = 0; i < size; i++) { - bv[i] = (byte) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, bv); - --v; - break; - case 'Z': - boolean[] zv = new boolean[size]; - for (i = 0; i < size; i++) { - zv[i] = readInt(items[readUnsignedShort(v)]) != 0; - v += 3; - } - av.visit(name, zv); - --v; - break; - case 'S': - short[] sv = new short[size]; - for (i = 0; i < size; i++) { - sv[i] = (short) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, sv); - --v; - break; - case 'C': - char[] cv = new char[size]; - for (i = 0; i < size; i++) { - cv[i] = (char) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, cv); - --v; - break; - case 'I': - int[] iv = new int[size]; - for (i = 0; i < size; i++) { - iv[i] = readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, iv); - --v; - break; - case 'J': - long[] lv = new long[size]; - for (i = 0; i < size; i++) { - lv[i] = readLong(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, lv); - --v; - break; - case 'F': - float[] fv = new float[size]; - for (i = 0; i < size; i++) { - fv[i] = Float - .intBitsToFloat(readInt(items[readUnsignedShort(v)])); - v += 3; - } - av.visit(name, fv); - --v; - break; - case 'D': - double[] dv = new double[size]; - for (i = 0; i < size; i++) { - dv[i] = Double - .longBitsToDouble(readLong(items[readUnsignedShort(v)])); - v += 3; - } - av.visit(name, dv); - --v; - break; - default: - v = readAnnotationValues(v - 3, buf, false, av.visitArray(name)); - } - } - return v; - } - - /** - * Computes the implicit frame of the method currently being parsed (as - * defined in the given {@link Context}) and stores it in the given context. - * - * @param frame - * information about the class being parsed. - */ - private void getImplicitFrame(final Context frame) { - String desc = frame.desc; - Object[] locals = frame.local; - int local = 0; - if ((frame.access & Opcodes.ACC_STATIC) == 0) { - if ("<init>".equals(frame.name)) { - locals[local++] = Opcodes.UNINITIALIZED_THIS; - } else { - locals[local++] = readClass(header + 2, frame.buffer); - } - } - int i = 1; - loop: while (true) { - int j = i; - switch (desc.charAt(i++)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - locals[local++] = Opcodes.INTEGER; - break; - case 'F': - locals[local++] = Opcodes.FLOAT; - break; - case 'J': - locals[local++] = Opcodes.LONG; - break; - case 'D': - locals[local++] = Opcodes.DOUBLE; - break; - case '[': - while (desc.charAt(i) == '[') { - ++i; - } - if (desc.charAt(i) == 'L') { - ++i; - while (desc.charAt(i) != ';') { - ++i; - } - } - locals[local++] = desc.substring(j, ++i); - break; - case 'L': - while (desc.charAt(i) != ';') { - ++i; - } - locals[local++] = desc.substring(j + 1, i++); - break; - default: - break loop; - } - } - frame.localCount = local; - } - - /** - * Reads a stack map frame and stores the result in the given - * {@link Context} object. - * - * @param stackMap - * the start offset of a stack map frame in the class file. - * @param zip - * if the stack map frame at stackMap is compressed or not. - * @param unzip - * if the stack map frame must be uncompressed. - * @param frame - * where the parsed stack map frame must be stored. - * @return the offset of the first byte following the parsed frame. - */ - private int readFrame(int stackMap, boolean zip, boolean unzip, - Context frame) { - char[] c = frame.buffer; - Label[] labels = frame.labels; - int tag; - int delta; - if (zip) { - tag = b[stackMap++] & 0xFF; - } else { - tag = MethodWriter.FULL_FRAME; - frame.offset = -1; - } - frame.localDiff = 0; - if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) { - delta = tag; - frame.mode = Opcodes.F_SAME; - frame.stackCount = 0; - } else if (tag < MethodWriter.RESERVED) { - delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME; - stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); - frame.mode = Opcodes.F_SAME1; - frame.stackCount = 1; - } else { - delta = readUnsignedShort(stackMap); - stackMap += 2; - if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { - stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); - frame.mode = Opcodes.F_SAME1; - frame.stackCount = 1; - } else if (tag >= MethodWriter.CHOP_FRAME - && tag < MethodWriter.SAME_FRAME_EXTENDED) { - frame.mode = Opcodes.F_CHOP; - frame.localDiff = MethodWriter.SAME_FRAME_EXTENDED - tag; - frame.localCount -= frame.localDiff; - frame.stackCount = 0; - } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) { - frame.mode = Opcodes.F_SAME; - frame.stackCount = 0; - } else if (tag < MethodWriter.FULL_FRAME) { - int local = unzip ? frame.localCount : 0; - for (int i = tag - MethodWriter.SAME_FRAME_EXTENDED; i > 0; i--) { - stackMap = readFrameType(frame.local, local++, stackMap, c, - labels); - } - frame.mode = Opcodes.F_APPEND; - frame.localDiff = tag - MethodWriter.SAME_FRAME_EXTENDED; - frame.localCount += frame.localDiff; - frame.stackCount = 0; - } else { // if (tag == FULL_FRAME) { - frame.mode = Opcodes.F_FULL; - int n = readUnsignedShort(stackMap); - stackMap += 2; - frame.localDiff = n; - frame.localCount = n; - for (int local = 0; n > 0; n--) { - stackMap = readFrameType(frame.local, local++, stackMap, c, - labels); - } - n = readUnsignedShort(stackMap); - stackMap += 2; - frame.stackCount = n; - for (int stack = 0; n > 0; n--) { - stackMap = readFrameType(frame.stack, stack++, stackMap, c, - labels); - } - } - } - frame.offset += delta + 1; - readLabel(frame.offset, labels); - return stackMap; - } - - /** - * Reads a stack map frame type and stores it at the given index in the - * given array. - * - * @param frame - * the array where the parsed type must be stored. - * @param index - * the index in 'frame' where the parsed type must be stored. - * @param v - * the start offset of the stack map frame type to read. - * @param buf - * a buffer to read strings. - * @param labels - * the labels of the method currently being parsed, indexed by - * their offset. If the parsed type is an Uninitialized type, a - * new label for the corresponding NEW instruction is stored in - * this array if it does not already exist. - * @return the offset of the first byte after the parsed type. - */ - private int readFrameType(final Object[] frame, final int index, int v, - final char[] buf, final Label[] labels) { - int type = b[v++] & 0xFF; - switch (type) { - case 0: - frame[index] = Opcodes.TOP; - break; - case 1: - frame[index] = Opcodes.INTEGER; - break; - case 2: - frame[index] = Opcodes.FLOAT; - break; - case 3: - frame[index] = Opcodes.DOUBLE; - break; - case 4: - frame[index] = Opcodes.LONG; - break; - case 5: - frame[index] = Opcodes.NULL; - break; - case 6: - frame[index] = Opcodes.UNINITIALIZED_THIS; - break; - case 7: // Object - frame[index] = readClass(v, buf); - v += 2; - break; - default: // Uninitialized - frame[index] = readLabel(readUnsignedShort(v), labels); - v += 2; - } - return v; - } - - /** - * Returns the label corresponding to the given offset. The default - * implementation of this method creates a label for the given offset if it - * has not been already created. - * - * @param offset - * a bytecode offset in a method. - * @param labels - * the already created labels, indexed by their offset. If a - * label already exists for offset this method must not create a - * new one. Otherwise it must store the new label in this array. - * @return a non null Label, which must be equal to labels[offset]. - */ - protected Label readLabel(int offset, Label[] labels) { - if (labels[offset] == null) { - labels[offset] = new Label(); - } - return labels[offset]; - } - - /** - * Returns the start index of the attribute_info structure of this class. - * - * @return the start index of the attribute_info structure of this class. - */ - private int getAttributes() { - // skips the header - int u = header + 8 + readUnsignedShort(header + 6) * 2; - // skips fields and methods - for (int i = readUnsignedShort(u); i > 0; --i) { - for (int j = readUnsignedShort(u + 8); j > 0; --j) { - u += 6 + readInt(u + 12); - } - u += 8; - } - u += 2; - for (int i = readUnsignedShort(u); i > 0; --i) { - for (int j = readUnsignedShort(u + 8); j > 0; --j) { - u += 6 + readInt(u + 12); - } - u += 8; - } - // the attribute_info structure starts just after the methods - return u + 2; - } - - /** - * Reads an attribute in {@link #b b}. - * - * @param attrs - * prototypes of the attributes that must be parsed during the - * visit of the class. Any attribute whose type is not equal to - * the type of one the prototypes is ignored (i.e. an empty - * {@link Attribute} instance is returned). - * @param type - * the type of the attribute. - * @param off - * index of the first byte of the attribute's content in - * {@link #b b}. The 6 attribute header bytes, containing the - * type and the length of the attribute, are not taken into - * account here (they have already been read). - * @param len - * the length of the attribute's content. - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param codeOff - * index of the first byte of code's attribute content in - * {@link #b b}, or -1 if the attribute to be read is not a code - * attribute. The 6 attribute header bytes, containing the type - * and the length of the attribute, are not taken into account - * here. - * @param labels - * the labels of the method's code, or <tt>null</tt> if the - * attribute to be read is not a code attribute. - * @return the attribute that has been read, or <tt>null</tt> to skip this - * attribute. - */ - private Attribute readAttribute(final Attribute[] attrs, final String type, - final int off, final int len, final char[] buf, final int codeOff, - final Label[] labels) { - for (int i = 0; i < attrs.length; ++i) { - if (attrs[i].type.equals(type)) { - return attrs[i].read(this, off, len, buf, codeOff, labels); - } - } - return new Attribute(type).read(this, off, len, null, -1, null); - } - - // ------------------------------------------------------------------------ - // Utility methods: low level parsing - // ------------------------------------------------------------------------ - - /** - * Returns the number of constant pool items in {@link #b b}. - * - * @return the number of constant pool items in {@link #b b}. - */ - public int getItemCount() { - return items.length; - } - - /** - * Returns the start index of the constant pool item in {@link #b b}, plus - * one. <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> - * - * @param item - * the index a constant pool item. - * @return the start index of the constant pool item in {@link #b b}, plus - * one. - */ - public int getItem(final int item) { - return items[item]; - } - - /** - * Returns the maximum length of the strings contained in the constant pool - * of the class. - * - * @return the maximum length of the strings contained in the constant pool - * of the class. - */ - public int getMaxStringLength() { - return maxStringLength; - } - - /** - * Reads a byte value in {@link #b b}. <i>This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters.</i> - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public int readByte(final int index) { - return b[index] & 0xFF; - } - - /** - * Reads an unsigned short value in {@link #b b}. <i>This method is intended - * for {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters.</i> - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public int readUnsignedShort(final int index) { - byte[] b = this.b; - return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); - } - - /** - * Reads a signed short value in {@link #b b}. <i>This method is intended - * for {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters.</i> - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public short readShort(final int index) { - byte[] b = this.b; - return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); - } - - /** - * Reads a signed int value in {@link #b b}. <i>This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters.</i> - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public int readInt(final int index) { - byte[] b = this.b; - return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) - | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); - } - - /** - * Reads a signed long value in {@link #b b}. <i>This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters.</i> - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public long readLong(final int index) { - long l1 = readInt(index); - long l0 = readInt(index + 4) & 0xFFFFFFFFL; - return (l1 << 32) | l0; - } - - /** - * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method - * is intended for {@link Attribute} sub classes, and is normally not needed - * by class generators or adapters.</i> - * - * @param index - * the start index of an unsigned short value in {@link #b b}, - * whose value is the index of an UTF8 constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the String corresponding to the specified UTF8 item. - */ - public String readUTF8(int index, final char[] buf) { - int item = readUnsignedShort(index); - if (index == 0 || item == 0) { - return null; - } - String s = strings[item]; - if (s != null) { - return s; - } - index = items[item]; - return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf); - } - - /** - * Reads UTF8 string in {@link #b b}. - * - * @param index - * start offset of the UTF8 string to be read. - * @param utfLen - * length of the UTF8 string to be read. - * @param buf - * buffer to be used to read the string. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the String corresponding to the specified UTF8 string. - */ - private String readUTF(int index, final int utfLen, final char[] buf) { - int endIndex = index + utfLen; - byte[] b = this.b; - int strLen = 0; - int c; - int st = 0; - char cc = 0; - while (index < endIndex) { - c = b[index++]; - switch (st) { - case 0: - c = c & 0xFF; - if (c < 0x80) { // 0xxxxxxx - buf[strLen++] = (char) c; - } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx - cc = (char) (c & 0x1F); - st = 1; - } else { // 1110 xxxx 10xx xxxx 10xx xxxx - cc = (char) (c & 0x0F); - st = 2; - } - break; - - case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char - buf[strLen++] = (char) ((cc << 6) | (c & 0x3F)); - st = 0; - break; - - case 2: // byte 2 of 3-byte char - cc = (char) ((cc << 6) | (c & 0x3F)); - st = 1; - break; - } - } - return new String(buf, 0, strLen); - } - - /** - * Reads a class constant pool item in {@link #b b}. <i>This method is - * intended for {@link Attribute} sub classes, and is normally not needed by - * class generators or adapters.</i> - * - * @param index - * the start index of an unsigned short value in {@link #b b}, - * whose value is the index of a class constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the String corresponding to the specified class item. - */ - public String readClass(final int index, final char[] buf) { - // computes the start index of the CONSTANT_Class item in b - // and reads the CONSTANT_Utf8 item designated by - // the first two bytes of this CONSTANT_Class item - return readUTF8(items[readUnsignedShort(index)], buf); - } - - /** - * Reads a numeric or string constant pool item in {@link #b b}. <i>This - * method is intended for {@link Attribute} sub classes, and is normally not - * needed by class generators or adapters.</i> - * - * @param item - * the index of a constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, - * {@link String}, {@link Type} or {@link Handle} corresponding to - * the given constant pool item. - */ - public Object readConst(final int item, final char[] buf) { - int index = items[item]; - switch (b[index - 1]) { - case ClassWriter.INT: - return new Integer(readInt(index)); - case ClassWriter.FLOAT: - return new Float(Float.intBitsToFloat(readInt(index))); - case ClassWriter.LONG: - return new Long(readLong(index)); - case ClassWriter.DOUBLE: - return new Double(Double.longBitsToDouble(readLong(index))); - case ClassWriter.CLASS: - return Type.getObjectType(readUTF8(index, buf)); - case ClassWriter.STR: - return readUTF8(index, buf); - case ClassWriter.MTYPE: - return Type.getMethodType(readUTF8(index, buf)); - default: // case ClassWriter.HANDLE_BASE + [1..9]: - int tag = readByte(index); - int[] items = this.items; - int cpIndex = items[readUnsignedShort(index + 1)]; - String owner = readClass(cpIndex, buf); - cpIndex = items[readUnsignedShort(cpIndex + 2)]; - String name = readUTF8(cpIndex, buf); - String desc = readUTF8(cpIndex + 2, buf); - return new Handle(tag, owner, name, desc); - } - } -} diff --git a/src/asm/scala/tools/asm/ClassVisitor.java b/src/asm/scala/tools/asm/ClassVisitor.java deleted file mode 100644 index 48dc2ca6ae..0000000000 --- a/src/asm/scala/tools/asm/ClassVisitor.java +++ /dev/null @@ -1,320 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * A visitor to visit a Java class. The methods of this class must be called in - * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [ - * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | - * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* ( - * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )* - * <tt>visitEnd</tt>. - * - * @author Eric Bruneton - */ -public abstract class ClassVisitor { - - /** - * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected final int api; - - /** - * The class visitor to which this visitor must delegate method calls. May - * be null. - */ - protected ClassVisitor cv; - - /** - * Constructs a new {@link ClassVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public ClassVisitor(final int api) { - this(api, null); - } - - /** - * Constructs a new {@link ClassVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param cv - * the class visitor to which this visitor must delegate method - * calls. May be null. - */ - public ClassVisitor(final int api, final ClassVisitor cv) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { - throw new IllegalArgumentException(); - } - this.api = api; - this.cv = cv; - } - - /** - * Visits the header of the class. - * - * @param version - * the class version. - * @param access - * the class's access flags (see {@link Opcodes}). This parameter - * also indicates if the class is deprecated. - * @param name - * the internal name of the class (see - * {@link Type#getInternalName() getInternalName}). - * @param signature - * the signature of this class. May be <tt>null</tt> if the class - * is not a generic one, and does not extend or implement generic - * classes or interfaces. - * @param superName - * the internal of name of the super class (see - * {@link Type#getInternalName() getInternalName}). For - * interfaces, the super class is {@link Object}. May be - * <tt>null</tt>, but only for the {@link Object} class. - * @param interfaces - * the internal names of the class's interfaces (see - * {@link Type#getInternalName() getInternalName}). May be - * <tt>null</tt>. - */ - public void visit(int version, int access, String name, String signature, - String superName, String[] interfaces) { - if (cv != null) { - cv.visit(version, access, name, signature, superName, interfaces); - } - } - - /** - * Visits the source of the class. - * - * @param source - * the name of the source file from which the class was compiled. - * May be <tt>null</tt>. - * @param debug - * additional debug information to compute the correspondance - * between source and compiled elements of the class. May be - * <tt>null</tt>. - */ - public void visitSource(String source, String debug) { - if (cv != null) { - cv.visitSource(source, debug); - } - } - - /** - * Visits the enclosing class of the class. This method must be called only - * if the class has an enclosing class. - * - * @param owner - * internal name of the enclosing class of the class. - * @param name - * the name of the method that contains the class, or - * <tt>null</tt> if the class is not enclosed in a method of its - * enclosing class. - * @param desc - * the descriptor of the method that contains the class, or - * <tt>null</tt> if the class is not enclosed in a method of its - * enclosing class. - */ - public void visitOuterClass(String owner, String name, String desc) { - if (cv != null) { - cv.visitOuterClass(owner, name, desc); - } - } - - /** - * Visits an annotation of the class. - * - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or <tt>null</tt> if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - if (cv != null) { - return cv.visitAnnotation(desc, visible); - } - return null; - } - - /** - * Visits an annotation on a type in the class signature. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#CLASS_TYPE_PARAMETER - * CLASS_TYPE_PARAMETER}, - * {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND - * CLASS_TYPE_PARAMETER_BOUND} or - * {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See - * {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or <tt>null</tt> if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (cv != null) { - return cv.visitTypeAnnotation(typeRef, typePath, desc, visible); - } - return null; - } - - /** - * Visits a non standard attribute of the class. - * - * @param attr - * an attribute. - */ - public void visitAttribute(Attribute attr) { - if (cv != null) { - cv.visitAttribute(attr); - } - } - - /** - * Visits information about an inner class. This inner class is not - * necessarily a member of the class being visited. - * - * @param name - * the internal name of an inner class (see - * {@link Type#getInternalName() getInternalName}). - * @param outerName - * the internal name of the class to which the inner class - * belongs (see {@link Type#getInternalName() getInternalName}). - * May be <tt>null</tt> for not member classes. - * @param innerName - * the (simple) name of the inner class inside its enclosing - * class. May be <tt>null</tt> for anonymous inner classes. - * @param access - * the access flags of the inner class as originally declared in - * the enclosing class. - */ - public void visitInnerClass(String name, String outerName, - String innerName, int access) { - if (cv != null) { - cv.visitInnerClass(name, outerName, innerName, access); - } - } - - /** - * Visits a field of the class. - * - * @param access - * the field's access flags (see {@link Opcodes}). This parameter - * also indicates if the field is synthetic and/or deprecated. - * @param name - * the field's name. - * @param desc - * the field's descriptor (see {@link Type Type}). - * @param signature - * the field's signature. May be <tt>null</tt> if the field's - * type does not use generic types. - * @param value - * the field's initial value. This parameter, which may be - * <tt>null</tt> if the field does not have an initial value, - * must be an {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double} or a {@link String} (for <tt>int</tt>, - * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields - * respectively). <i>This parameter is only used for static - * fields</i>. Its value is ignored for non static fields, which - * must be initialized through bytecode instructions in - * constructors or methods. - * @return a visitor to visit field annotations and attributes, or - * <tt>null</tt> if this class visitor is not interested in visiting - * these annotations and attributes. - */ - public FieldVisitor visitField(int access, String name, String desc, - String signature, Object value) { - if (cv != null) { - return cv.visitField(access, name, desc, signature, value); - } - return null; - } - - /** - * Visits a method of the class. This method <i>must</i> return a new - * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called, - * i.e., it should not return a previously returned visitor. - * - * @param access - * the method's access flags (see {@link Opcodes}). This - * parameter also indicates if the method is synthetic and/or - * deprecated. - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type Type}). - * @param signature - * the method's signature. May be <tt>null</tt> if the method - * parameters, return type and exceptions do not use generic - * types. - * @param exceptions - * the internal names of the method's exception classes (see - * {@link Type#getInternalName() getInternalName}). May be - * <tt>null</tt>. - * @return an object to visit the byte code of the method, or <tt>null</tt> - * if this class visitor is not interested in visiting the code of - * this method. - */ - public MethodVisitor visitMethod(int access, String name, String desc, - String signature, String[] exceptions) { - if (cv != null) { - return cv.visitMethod(access, name, desc, signature, exceptions); - } - return null; - } - - /** - * Visits the end of the class. This method, which is the last one to be - * called, is used to inform the visitor that all the fields and methods of - * the class have been visited. - */ - public void visitEnd() { - if (cv != null) { - cv.visitEnd(); - } - } -} diff --git a/src/asm/scala/tools/asm/ClassWriter.java b/src/asm/scala/tools/asm/ClassWriter.java deleted file mode 100644 index 5c2de3f982..0000000000 --- a/src/asm/scala/tools/asm/ClassWriter.java +++ /dev/null @@ -1,1785 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * A {@link ClassVisitor} that generates classes in bytecode form. More - * precisely this visitor generates a byte array conforming to the Java class - * file format. It can be used alone, to generate a Java class "from scratch", - * or with one or more {@link ClassReader ClassReader} and adapter class visitor - * to generate a modified class from one or more existing Java classes. - * - * @author Eric Bruneton - */ -public class ClassWriter extends ClassVisitor { - - /** - * Flag to automatically compute the maximum stack size and the maximum - * number of local variables of methods. If this flag is set, then the - * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the - * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod} - * method will be ignored, and computed automatically from the signature and - * the bytecode of each method. - * - * @see #ClassWriter(int) - */ - public static final int COMPUTE_MAXS = 1; - - /** - * Flag to automatically compute the stack map frames of methods from - * scratch. If this flag is set, then the calls to the - * {@link MethodVisitor#visitFrame} method are ignored, and the stack map - * frames are recomputed from the methods bytecode. The arguments of the - * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and - * recomputed from the bytecode. In other words, computeFrames implies - * computeMaxs. - * - * @see #ClassWriter(int) - */ - public static final int COMPUTE_FRAMES = 2; - - /** - * Pseudo access flag to distinguish between the synthetic attribute and the - * synthetic access flag. - */ - static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000; - - /** - * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC. - */ - static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE - / Opcodes.ACC_SYNTHETIC; - - /** - * The type of instructions without any argument. - */ - static final int NOARG_INSN = 0; - - /** - * The type of instructions with an signed byte argument. - */ - static final int SBYTE_INSN = 1; - - /** - * The type of instructions with an signed short argument. - */ - static final int SHORT_INSN = 2; - - /** - * The type of instructions with a local variable index argument. - */ - static final int VAR_INSN = 3; - - /** - * The type of instructions with an implicit local variable index argument. - */ - static final int IMPLVAR_INSN = 4; - - /** - * The type of instructions with a type descriptor argument. - */ - static final int TYPE_INSN = 5; - - /** - * The type of field and method invocations instructions. - */ - static final int FIELDORMETH_INSN = 6; - - /** - * The type of the INVOKEINTERFACE/INVOKEDYNAMIC instruction. - */ - static final int ITFMETH_INSN = 7; - - /** - * The type of the INVOKEDYNAMIC instruction. - */ - static final int INDYMETH_INSN = 8; - - /** - * The type of instructions with a 2 bytes bytecode offset label. - */ - static final int LABEL_INSN = 9; - - /** - * The type of instructions with a 4 bytes bytecode offset label. - */ - static final int LABELW_INSN = 10; - - /** - * The type of the LDC instruction. - */ - static final int LDC_INSN = 11; - - /** - * The type of the LDC_W and LDC2_W instructions. - */ - static final int LDCW_INSN = 12; - - /** - * The type of the IINC instruction. - */ - static final int IINC_INSN = 13; - - /** - * The type of the TABLESWITCH instruction. - */ - static final int TABL_INSN = 14; - - /** - * The type of the LOOKUPSWITCH instruction. - */ - static final int LOOK_INSN = 15; - - /** - * The type of the MULTIANEWARRAY instruction. - */ - static final int MANA_INSN = 16; - - /** - * The type of the WIDE instruction. - */ - static final int WIDE_INSN = 17; - - /** - * The instruction types of all JVM opcodes. - */ - static final byte[] TYPE; - - /** - * The type of CONSTANT_Class constant pool items. - */ - static final int CLASS = 7; - - /** - * The type of CONSTANT_Fieldref constant pool items. - */ - static final int FIELD = 9; - - /** - * The type of CONSTANT_Methodref constant pool items. - */ - static final int METH = 10; - - /** - * The type of CONSTANT_InterfaceMethodref constant pool items. - */ - static final int IMETH = 11; - - /** - * The type of CONSTANT_String constant pool items. - */ - static final int STR = 8; - - /** - * The type of CONSTANT_Integer constant pool items. - */ - static final int INT = 3; - - /** - * The type of CONSTANT_Float constant pool items. - */ - static final int FLOAT = 4; - - /** - * The type of CONSTANT_Long constant pool items. - */ - static final int LONG = 5; - - /** - * The type of CONSTANT_Double constant pool items. - */ - static final int DOUBLE = 6; - - /** - * The type of CONSTANT_NameAndType constant pool items. - */ - static final int NAME_TYPE = 12; - - /** - * The type of CONSTANT_Utf8 constant pool items. - */ - static final int UTF8 = 1; - - /** - * The type of CONSTANT_MethodType constant pool items. - */ - static final int MTYPE = 16; - - /** - * The type of CONSTANT_MethodHandle constant pool items. - */ - static final int HANDLE = 15; - - /** - * The type of CONSTANT_InvokeDynamic constant pool items. - */ - static final int INDY = 18; - - /** - * The base value for all CONSTANT_MethodHandle constant pool items. - * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9 - * different items. - */ - static final int HANDLE_BASE = 20; - - /** - * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable}, - * instead of the constant pool, in order to avoid clashes with normal - * constant pool items in the ClassWriter constant pool's hash table. - */ - static final int TYPE_NORMAL = 30; - - /** - * Uninitialized type Item stored in the ClassWriter - * {@link ClassWriter#typeTable}, instead of the constant pool, in order to - * avoid clashes with normal constant pool items in the ClassWriter constant - * pool's hash table. - */ - static final int TYPE_UNINIT = 31; - - /** - * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable}, - * instead of the constant pool, in order to avoid clashes with normal - * constant pool items in the ClassWriter constant pool's hash table. - */ - static final int TYPE_MERGED = 32; - - /** - * The type of BootstrapMethods items. These items are stored in a special - * class attribute named BootstrapMethods and not in the constant pool. - */ - static final int BSM = 33; - - /** - * The class reader from which this class writer was constructed, if any. - */ - ClassReader cr; - - /** - * Minor and major version numbers of the class to be generated. - */ - int version; - - /** - * Index of the next item to be added in the constant pool. - */ - int index; - - /** - * The constant pool of this class. - */ - final ByteVector pool; - - /** - * The constant pool's hash table data. - */ - Item[] items; - - /** - * The threshold of the constant pool's hash table. - */ - int threshold; - - /** - * A reusable key used to look for items in the {@link #items} hash table. - */ - final Item key; - - /** - * A reusable key used to look for items in the {@link #items} hash table. - */ - final Item key2; - - /** - * A reusable key used to look for items in the {@link #items} hash table. - */ - final Item key3; - - /** - * A reusable key used to look for items in the {@link #items} hash table. - */ - final Item key4; - - /** - * A type table used to temporarily store internal names that will not - * necessarily be stored in the constant pool. This type table is used by - * the control flow and data flow analysis algorithm used to compute stack - * map frames from scratch. This array associates to each index <tt>i</tt> - * the Item whose index is <tt>i</tt>. All Item objects stored in this array - * are also stored in the {@link #items} hash table. These two arrays allow - * to retrieve an Item from its index or, conversely, to get the index of an - * Item from its value. Each Item stores an internal name in its - * {@link Item#strVal1} field. - */ - Item[] typeTable; - - /** - * Number of elements in the {@link #typeTable} array. - */ - private short typeCount; - - /** - * The access flags of this class. - */ - private int access; - - /** - * The constant pool item that contains the internal name of this class. - */ - private int name; - - /** - * The internal name of this class. - */ - String thisName; - - /** - * The constant pool item that contains the signature of this class. - */ - private int signature; - - /** - * The constant pool item that contains the internal name of the super class - * of this class. - */ - private int superName; - - /** - * Number of interfaces implemented or extended by this class or interface. - */ - private int interfaceCount; - - /** - * The interfaces implemented or extended by this class or interface. More - * precisely, this array contains the indexes of the constant pool items - * that contain the internal names of these interfaces. - */ - private int[] interfaces; - - /** - * The index of the constant pool item that contains the name of the source - * file from which this class was compiled. - */ - private int sourceFile; - - /** - * The SourceDebug attribute of this class. - */ - private ByteVector sourceDebug; - - /** - * The constant pool item that contains the name of the enclosing class of - * this class. - */ - private int enclosingMethodOwner; - - /** - * The constant pool item that contains the name and descriptor of the - * enclosing method of this class. - */ - private int enclosingMethod; - - /** - * The runtime visible annotations of this class. - */ - private AnnotationWriter anns; - - /** - * The runtime invisible annotations of this class. - */ - private AnnotationWriter ianns; - - /** - * The runtime visible type annotations of this class. - */ - private AnnotationWriter tanns; - - /** - * The runtime invisible type annotations of this class. - */ - private AnnotationWriter itanns; - - /** - * The non standard attributes of this class. - */ - private Attribute attrs; - - /** - * The number of entries in the InnerClasses attribute. - */ - private int innerClassesCount; - - /** - * The InnerClasses attribute. - */ - private ByteVector innerClasses; - - /** - * The number of entries in the BootstrapMethods attribute. - */ - int bootstrapMethodsCount; - - /** - * The BootstrapMethods attribute. - */ - ByteVector bootstrapMethods; - - /** - * The fields of this class. These fields are stored in a linked list of - * {@link FieldWriter} objects, linked to each other by their - * {@link FieldWriter#fv} field. This field stores the first element of this - * list. - */ - FieldWriter firstField; - - /** - * The fields of this class. These fields are stored in a linked list of - * {@link FieldWriter} objects, linked to each other by their - * {@link FieldWriter#fv} field. This field stores the last element of this - * list. - */ - FieldWriter lastField; - - /** - * The methods of this class. These methods are stored in a linked list of - * {@link MethodWriter} objects, linked to each other by their - * {@link MethodWriter#mv} field. This field stores the first element of - * this list. - */ - MethodWriter firstMethod; - - /** - * The methods of this class. These methods are stored in a linked list of - * {@link MethodWriter} objects, linked to each other by their - * {@link MethodWriter#mv} field. This field stores the last element of this - * list. - */ - MethodWriter lastMethod; - - /** - * <tt>true</tt> if the maximum stack size and number of local variables - * must be automatically computed. - */ - private boolean computeMaxs; - - /** - * <tt>true</tt> if the stack map frames must be recomputed from scratch. - */ - private boolean computeFrames; - - /** - * <tt>true</tt> if the stack map tables of this class are invalid. The - * {@link MethodWriter#resizeInstructions} method cannot transform existing - * stack map tables, and so produces potentially invalid classes when it is - * executed. In this case the class is reread and rewritten with the - * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize - * stack map tables when this option is used). - */ - boolean invalidFrames; - - // ------------------------------------------------------------------------ - // Static initializer - // ------------------------------------------------------------------------ - - /** - * Computes the instruction types of JVM opcodes. - */ - static { - int i; - byte[] b = new byte[220]; - String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" - + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA" - + "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ"; - for (i = 0; i < b.length; ++i) { - b[i] = (byte) (s.charAt(i) - 'A'); - } - TYPE = b; - - // code to generate the above string - // - // // SBYTE_INSN instructions - // b[Constants.NEWARRAY] = SBYTE_INSN; - // b[Constants.BIPUSH] = SBYTE_INSN; - // - // // SHORT_INSN instructions - // b[Constants.SIPUSH] = SHORT_INSN; - // - // // (IMPL)VAR_INSN instructions - // b[Constants.RET] = VAR_INSN; - // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) { - // b[i] = VAR_INSN; - // } - // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) { - // b[i] = VAR_INSN; - // } - // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3 - // b[i] = IMPLVAR_INSN; - // } - // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3 - // b[i] = IMPLVAR_INSN; - // } - // - // // TYPE_INSN instructions - // b[Constants.NEW] = TYPE_INSN; - // b[Constants.ANEWARRAY] = TYPE_INSN; - // b[Constants.CHECKCAST] = TYPE_INSN; - // b[Constants.INSTANCEOF] = TYPE_INSN; - // - // // (Set)FIELDORMETH_INSN instructions - // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) { - // b[i] = FIELDORMETH_INSN; - // } - // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN; - // b[Constants.INVOKEDYNAMIC] = INDYMETH_INSN; - // - // // LABEL(W)_INSN instructions - // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) { - // b[i] = LABEL_INSN; - // } - // b[Constants.IFNULL] = LABEL_INSN; - // b[Constants.IFNONNULL] = LABEL_INSN; - // b[200] = LABELW_INSN; // GOTO_W - // b[201] = LABELW_INSN; // JSR_W - // // temporary opcodes used internally by ASM - see Label and - // MethodWriter - // for (i = 202; i < 220; ++i) { - // b[i] = LABEL_INSN; - // } - // - // // LDC(_W) instructions - // b[Constants.LDC] = LDC_INSN; - // b[19] = LDCW_INSN; // LDC_W - // b[20] = LDCW_INSN; // LDC2_W - // - // // special instructions - // b[Constants.IINC] = IINC_INSN; - // b[Constants.TABLESWITCH] = TABL_INSN; - // b[Constants.LOOKUPSWITCH] = LOOK_INSN; - // b[Constants.MULTIANEWARRAY] = MANA_INSN; - // b[196] = WIDE_INSN; // WIDE - // - // for (i = 0; i < b.length; ++i) { - // System.err.print((char)('A' + b[i])); - // } - // System.err.println(); - } - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link ClassWriter} object. - * - * @param flags - * option flags that can be used to modify the default behavior - * of this class. See {@link #COMPUTE_MAXS}, - * {@link #COMPUTE_FRAMES}. - */ - public ClassWriter(final int flags) { - super(Opcodes.ASM5); - index = 1; - pool = new ByteVector(); - items = new Item[256]; - threshold = (int) (0.75d * items.length); - key = new Item(); - key2 = new Item(); - key3 = new Item(); - key4 = new Item(); - this.computeMaxs = (flags & COMPUTE_MAXS) != 0; - this.computeFrames = (flags & COMPUTE_FRAMES) != 0; - } - - /** - * Constructs a new {@link ClassWriter} object and enables optimizations for - * "mostly add" bytecode transformations. These optimizations are the - * following: - * - * <ul> - * <li>The constant pool from the original class is copied as is in the new - * class, which saves time. New constant pool entries will be added at the - * end if necessary, but unused constant pool entries <i>won't be - * removed</i>.</li> - * <li>Methods that are not transformed are copied as is in the new class, - * directly from the original class bytecode (i.e. without emitting visit - * events for all the method instructions), which saves a <i>lot</i> of - * time. Untransformed methods are detected by the fact that the - * {@link ClassReader} receives {@link MethodVisitor} objects that come from - * a {@link ClassWriter} (and not from any other {@link ClassVisitor} - * instance).</li> - * </ul> - * - * @param classReader - * the {@link ClassReader} used to read the original class. It - * will be used to copy the entire constant pool from the - * original class and also to copy other fragments of original - * bytecode where applicable. - * @param flags - * option flags that can be used to modify the default behavior - * of this class. <i>These option flags do not affect methods - * that are copied as is in the new class. This means that the - * maximum stack size nor the stack frames will be computed for - * these methods</i>. See {@link #COMPUTE_MAXS}, - * {@link #COMPUTE_FRAMES}. - */ - public ClassWriter(final ClassReader classReader, final int flags) { - this(flags); - classReader.copyPool(this); - this.cr = classReader; - } - - // ------------------------------------------------------------------------ - // Implementation of the ClassVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public final void visit(final int version, final int access, - final String name, final String signature, final String superName, - final String[] interfaces) { - this.version = version; - this.access = access; - this.name = newClass(name); - thisName = name; - if (ClassReader.SIGNATURES && signature != null) { - this.signature = newUTF8(signature); - } - this.superName = superName == null ? 0 : newClass(superName); - if (interfaces != null && interfaces.length > 0) { - interfaceCount = interfaces.length; - this.interfaces = new int[interfaceCount]; - for (int i = 0; i < interfaceCount; ++i) { - this.interfaces[i] = newClass(interfaces[i]); - } - } - } - - @Override - public final void visitSource(final String file, final String debug) { - if (file != null) { - sourceFile = newUTF8(file); - } - if (debug != null) { - sourceDebug = new ByteVector().encodeUTF8(debug, 0, - Integer.MAX_VALUE); - } - } - - @Override - public final void visitOuterClass(final String owner, final String name, - final String desc) { - enclosingMethodOwner = newClass(owner); - if (name != null && desc != null) { - enclosingMethod = newNameType(name, desc); - } - } - - @Override - public final AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write type, and reserve space for values count - bv.putShort(newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); - if (visible) { - aw.next = anns; - anns = aw; - } else { - aw.next = ianns; - ianns = aw; - } - return aw; - } - - @Override - public final AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - AnnotationWriter.putTarget(typeRef, typePath, bv); - // write type, and reserve space for values count - bv.putShort(newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = tanns; - tanns = aw; - } else { - aw.next = itanns; - itanns = aw; - } - return aw; - } - - @Override - public final void visitAttribute(final Attribute attr) { - attr.next = attrs; - attrs = attr; - } - - @Override - public final void visitInnerClass(final String name, - final String outerName, final String innerName, final int access) { - if (innerClasses == null) { - innerClasses = new ByteVector(); - } - // Sec. 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the - // constant_pool table which represents a class or interface C that is - // not a package member must have exactly one corresponding entry in the - // classes array". To avoid duplicates we keep track in the intVal field - // of the Item of each CONSTANT_Class_info entry C whether an inner - // class entry has already been added for C (this field is unused for - // class entries, and changing its value does not change the hashcode - // and equality tests). If so we store the index of this inner class - // entry (plus one) in intVal. This hack allows duplicate detection in - // O(1) time. - Item nameItem = newClassItem(name); - if (nameItem.intVal == 0) { - ++innerClassesCount; - innerClasses.putShort(nameItem.index); - innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); - innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); - innerClasses.putShort(access); - nameItem.intVal = innerClassesCount; - } else { - // Compare the inner classes entry nameItem.intVal - 1 with the - // arguments of this method and throw an exception if there is a - // difference? - } - } - - @Override - public final FieldVisitor visitField(final int access, final String name, - final String desc, final String signature, final Object value) { - return new FieldWriter(this, access, name, desc, signature, value); - } - - @Override - public final MethodVisitor visitMethod(final int access, final String name, - final String desc, final String signature, final String[] exceptions) { - return new MethodWriter(this, access, name, desc, signature, - exceptions, computeMaxs, computeFrames); - } - - @Override - public final void visitEnd() { - } - - // ------------------------------------------------------------------------ - // Other public methods - // ------------------------------------------------------------------------ - - /** - * Returns the bytecode of the class that was build with this class writer. - * - * @return the bytecode of the class that was build with this class writer. - */ - public byte[] toByteArray() { - if (index > 0xFFFF) { - throw new RuntimeException("Class file too large!"); - } - // computes the real size of the bytecode of this class - int size = 24 + 2 * interfaceCount; - int nbFields = 0; - FieldWriter fb = firstField; - while (fb != null) { - ++nbFields; - size += fb.getSize(); - fb = (FieldWriter) fb.fv; - } - int nbMethods = 0; - MethodWriter mb = firstMethod; - while (mb != null) { - ++nbMethods; - size += mb.getSize(); - mb = (MethodWriter) mb.mv; - } - int attributeCount = 0; - if (bootstrapMethods != null) { - // we put it as first attribute in order to improve a bit - // ClassReader.copyBootstrapMethods - ++attributeCount; - size += 8 + bootstrapMethods.length; - newUTF8("BootstrapMethods"); - } - if (ClassReader.SIGNATURES && signature != 0) { - ++attributeCount; - size += 8; - newUTF8("Signature"); - } - if (sourceFile != 0) { - ++attributeCount; - size += 8; - newUTF8("SourceFile"); - } - if (sourceDebug != null) { - ++attributeCount; - size += sourceDebug.length + 6; - newUTF8("SourceDebugExtension"); - } - if (enclosingMethodOwner != 0) { - ++attributeCount; - size += 10; - newUTF8("EnclosingMethod"); - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - ++attributeCount; - size += 6; - newUTF8("Deprecated"); - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((version & 0xFFFF) < Opcodes.V1_5 - || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) { - ++attributeCount; - size += 6; - newUTF8("Synthetic"); - } - } - if (innerClasses != null) { - ++attributeCount; - size += 8 + innerClasses.length; - newUTF8("InnerClasses"); - } - if (ClassReader.ANNOTATIONS && anns != null) { - ++attributeCount; - size += 8 + anns.getSize(); - newUTF8("RuntimeVisibleAnnotations"); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - ++attributeCount; - size += 8 + ianns.getSize(); - newUTF8("RuntimeInvisibleAnnotations"); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - ++attributeCount; - size += 8 + tanns.getSize(); - newUTF8("RuntimeVisibleTypeAnnotations"); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - ++attributeCount; - size += 8 + itanns.getSize(); - newUTF8("RuntimeInvisibleTypeAnnotations"); - } - if (attrs != null) { - attributeCount += attrs.getCount(); - size += attrs.getSize(this, null, 0, -1, -1); - } - size += pool.length; - // allocates a byte vector of this size, in order to avoid unnecessary - // arraycopy operations in the ByteVector.enlarge() method - ByteVector out = new ByteVector(size); - out.putInt(0xCAFEBABE).putInt(version); - out.putShort(index).putByteArray(pool.data, 0, pool.length); - int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE - | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC); - out.putShort(access & ~mask).putShort(name).putShort(superName); - out.putShort(interfaceCount); - for (int i = 0; i < interfaceCount; ++i) { - out.putShort(interfaces[i]); - } - out.putShort(nbFields); - fb = firstField; - while (fb != null) { - fb.put(out); - fb = (FieldWriter) fb.fv; - } - out.putShort(nbMethods); - mb = firstMethod; - while (mb != null) { - mb.put(out); - mb = (MethodWriter) mb.mv; - } - out.putShort(attributeCount); - if (bootstrapMethods != null) { - out.putShort(newUTF8("BootstrapMethods")); - out.putInt(bootstrapMethods.length + 2).putShort( - bootstrapMethodsCount); - out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length); - } - if (ClassReader.SIGNATURES && signature != 0) { - out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); - } - if (sourceFile != 0) { - out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); - } - if (sourceDebug != null) { - int len = sourceDebug.length; - out.putShort(newUTF8("SourceDebugExtension")).putInt(len); - out.putByteArray(sourceDebug.data, 0, len); - } - if (enclosingMethodOwner != 0) { - out.putShort(newUTF8("EnclosingMethod")).putInt(4); - out.putShort(enclosingMethodOwner).putShort(enclosingMethod); - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - out.putShort(newUTF8("Deprecated")).putInt(0); - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((version & 0xFFFF) < Opcodes.V1_5 - || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) { - out.putShort(newUTF8("Synthetic")).putInt(0); - } - } - if (innerClasses != null) { - out.putShort(newUTF8("InnerClasses")); - out.putInt(innerClasses.length + 2).putShort(innerClassesCount); - out.putByteArray(innerClasses.data, 0, innerClasses.length); - } - if (ClassReader.ANNOTATIONS && anns != null) { - out.putShort(newUTF8("RuntimeVisibleAnnotations")); - anns.put(out); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - out.putShort(newUTF8("RuntimeInvisibleAnnotations")); - ianns.put(out); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - out.putShort(newUTF8("RuntimeVisibleTypeAnnotations")); - tanns.put(out); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations")); - itanns.put(out); - } - if (attrs != null) { - attrs.put(this, null, 0, -1, -1, out); - } - if (invalidFrames) { - anns = null; - ianns = null; - attrs = null; - innerClassesCount = 0; - innerClasses = null; - bootstrapMethodsCount = 0; - bootstrapMethods = null; - firstField = null; - lastField = null; - firstMethod = null; - lastMethod = null; - computeMaxs = false; - computeFrames = true; - invalidFrames = false; - new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES); - return toByteArray(); - } - return out.data; - } - - // ------------------------------------------------------------------------ - // Utility methods: constant pool management - // ------------------------------------------------------------------------ - - /** - * Adds a number or string constant to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * - * @param cst - * the value of the constant to be added to the constant pool. - * This parameter must be an {@link Integer}, a {@link Float}, a - * {@link Long}, a {@link Double}, a {@link String} or a - * {@link Type}. - * @return a new or already existing constant item with the given value. - */ - Item newConstItem(final Object cst) { - if (cst instanceof Integer) { - int val = ((Integer) cst).intValue(); - return newInteger(val); - } else if (cst instanceof Byte) { - int val = ((Byte) cst).intValue(); - return newInteger(val); - } else if (cst instanceof Character) { - int val = ((Character) cst).charValue(); - return newInteger(val); - } else if (cst instanceof Short) { - int val = ((Short) cst).intValue(); - return newInteger(val); - } else if (cst instanceof Boolean) { - int val = ((Boolean) cst).booleanValue() ? 1 : 0; - return newInteger(val); - } else if (cst instanceof Float) { - float val = ((Float) cst).floatValue(); - return newFloat(val); - } else if (cst instanceof Long) { - long val = ((Long) cst).longValue(); - return newLong(val); - } else if (cst instanceof Double) { - double val = ((Double) cst).doubleValue(); - return newDouble(val); - } else if (cst instanceof String) { - return newString((String) cst); - } else if (cst instanceof Type) { - Type t = (Type) cst; - int s = t.getSort(); - if (s == Type.OBJECT) { - return newClassItem(t.getInternalName()); - } else if (s == Type.METHOD) { - return newMethodTypeItem(t.getDescriptor()); - } else { // s == primitive type or array - return newClassItem(t.getDescriptor()); - } - } else if (cst instanceof Handle) { - Handle h = (Handle) cst; - return newHandleItem(h.tag, h.owner, h.name, h.desc); - } else { - throw new IllegalArgumentException("value " + cst); - } - } - - /** - * Adds a number or string constant to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> - * - * @param cst - * the value of the constant to be added to the constant pool. - * This parameter must be an {@link Integer}, a {@link Float}, a - * {@link Long}, a {@link Double} or a {@link String}. - * @return the index of a new or already existing constant item with the - * given value. - */ - public int newConst(final Object cst) { - return newConstItem(cst).index; - } - - /** - * Adds an UTF8 string to the constant pool of the class being build. Does - * nothing if the constant pool already contains a similar item. <i>This - * method is intended for {@link Attribute} sub classes, and is normally not - * needed by class generators or adapters.</i> - * - * @param value - * the String value. - * @return the index of a new or already existing UTF8 item. - */ - public int newUTF8(final String value) { - key.set(UTF8, value, null, null); - Item result = get(key); - if (result == null) { - pool.putByte(UTF8).putUTF8(value); - result = new Item(index++, key); - put(result); - } - return result.index; - } - - /** - * Adds a class reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> - * - * @param value - * the internal name of the class. - * @return a new or already existing class reference item. - */ - Item newClassItem(final String value) { - key2.set(CLASS, value, null, null); - Item result = get(key2); - if (result == null) { - pool.put12(CLASS, newUTF8(value)); - result = new Item(index++, key2); - put(result); - } - return result; - } - - /** - * Adds a class reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> - * - * @param value - * the internal name of the class. - * @return the index of a new or already existing class reference item. - */ - public int newClass(final String value) { - return newClassItem(value).index; - } - - /** - * Adds a method type reference to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> - * - * @param methodDesc - * method descriptor of the method type. - * @return a new or already existing method type reference item. - */ - Item newMethodTypeItem(final String methodDesc) { - key2.set(MTYPE, methodDesc, null, null); - Item result = get(key2); - if (result == null) { - pool.put12(MTYPE, newUTF8(methodDesc)); - result = new Item(index++, key2); - put(result); - } - return result; - } - - /** - * Adds a method type reference to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> - * - * @param methodDesc - * method descriptor of the method type. - * @return the index of a new or already existing method type reference - * item. - */ - public int newMethodType(final String methodDesc) { - return newMethodTypeItem(methodDesc).index; - } - - /** - * Adds a handle to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. <i>This method is - * intended for {@link Attribute} sub classes, and is normally not needed by - * class generators or adapters.</i> - * - * @param tag - * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, - * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, - * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, - * {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - * @param owner - * the internal name of the field or method owner class. - * @param name - * the name of the field or method. - * @param desc - * the descriptor of the field or method. - * @return a new or an already existing method type reference item. - */ - Item newHandleItem(final int tag, final String owner, final String name, - final String desc) { - key4.set(HANDLE_BASE + tag, owner, name, desc); - Item result = get(key4); - if (result == null) { - if (tag <= Opcodes.H_PUTSTATIC) { - put112(HANDLE, tag, newField(owner, name, desc)); - } else { - put112(HANDLE, - tag, - newMethod(owner, name, desc, - tag == Opcodes.H_INVOKEINTERFACE)); - } - result = new Item(index++, key4); - put(result); - } - return result; - } - - /** - * Adds a handle to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. <i>This method is - * intended for {@link Attribute} sub classes, and is normally not needed by - * class generators or adapters.</i> - * - * @param tag - * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, - * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, - * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, - * {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - * @param owner - * the internal name of the field or method owner class. - * @param name - * the name of the field or method. - * @param desc - * the descriptor of the field or method. - * @return the index of a new or already existing method type reference - * item. - */ - public int newHandle(final int tag, final String owner, final String name, - final String desc) { - return newHandleItem(tag, owner, name, desc).index; - } - - /** - * Adds an invokedynamic reference to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> - * - * @param name - * name of the invoked method. - * @param desc - * descriptor of the invoke method. - * @param bsm - * the bootstrap method. - * @param bsmArgs - * the bootstrap method constant arguments. - * - * @return a new or an already existing invokedynamic type reference item. - */ - Item newInvokeDynamicItem(final String name, final String desc, - final Handle bsm, final Object... bsmArgs) { - // cache for performance - ByteVector bootstrapMethods = this.bootstrapMethods; - if (bootstrapMethods == null) { - bootstrapMethods = this.bootstrapMethods = new ByteVector(); - } - - int position = bootstrapMethods.length; // record current position - - int hashCode = bsm.hashCode(); - bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name, - bsm.desc)); - - int argsLength = bsmArgs.length; - bootstrapMethods.putShort(argsLength); - - for (int i = 0; i < argsLength; i++) { - Object bsmArg = bsmArgs[i]; - hashCode ^= bsmArg.hashCode(); - bootstrapMethods.putShort(newConst(bsmArg)); - } - - byte[] data = bootstrapMethods.data; - int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments) - hashCode &= 0x7FFFFFFF; - Item result = items[hashCode % items.length]; - loop: while (result != null) { - if (result.type != BSM || result.hashCode != hashCode) { - result = result.next; - continue; - } - - // because the data encode the size of the argument - // we don't need to test if these size are equals - int resultPosition = result.intVal; - for (int p = 0; p < length; p++) { - if (data[position + p] != data[resultPosition + p]) { - result = result.next; - continue loop; - } - } - break; - } - - int bootstrapMethodIndex; - if (result != null) { - bootstrapMethodIndex = result.index; - bootstrapMethods.length = position; // revert to old position - } else { - bootstrapMethodIndex = bootstrapMethodsCount++; - result = new Item(bootstrapMethodIndex); - result.set(position, hashCode); - put(result); - } - - // now, create the InvokeDynamic constant - key3.set(name, desc, bootstrapMethodIndex); - result = get(key3); - if (result == null) { - put122(INDY, bootstrapMethodIndex, newNameType(name, desc)); - result = new Item(index++, key3); - put(result); - } - return result; - } - - /** - * Adds an invokedynamic reference to the constant pool of the class being - * build. Does nothing if the constant pool already contains a similar item. - * <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> - * - * @param name - * name of the invoked method. - * @param desc - * descriptor of the invoke method. - * @param bsm - * the bootstrap method. - * @param bsmArgs - * the bootstrap method constant arguments. - * - * @return the index of a new or already existing invokedynamic reference - * item. - */ - public int newInvokeDynamic(final String name, final String desc, - final Handle bsm, final Object... bsmArgs) { - return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index; - } - - /** - * Adds a field reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * - * @param owner - * the internal name of the field's owner class. - * @param name - * the field's name. - * @param desc - * the field's descriptor. - * @return a new or already existing field reference item. - */ - Item newFieldItem(final String owner, final String name, final String desc) { - key3.set(FIELD, owner, name, desc); - Item result = get(key3); - if (result == null) { - put122(FIELD, newClass(owner), newNameType(name, desc)); - result = new Item(index++, key3); - put(result); - } - return result; - } - - /** - * Adds a field reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> - * - * @param owner - * the internal name of the field's owner class. - * @param name - * the field's name. - * @param desc - * the field's descriptor. - * @return the index of a new or already existing field reference item. - */ - public int newField(final String owner, final String name, final String desc) { - return newFieldItem(owner, name, desc).index; - } - - /** - * Adds a method reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * - * @param owner - * the internal name of the method's owner class. - * @param name - * the method's name. - * @param desc - * the method's descriptor. - * @param itf - * <tt>true</tt> if <tt>owner</tt> is an interface. - * @return a new or already existing method reference item. - */ - Item newMethodItem(final String owner, final String name, - final String desc, final boolean itf) { - int type = itf ? IMETH : METH; - key3.set(type, owner, name, desc); - Item result = get(key3); - if (result == null) { - put122(type, newClass(owner), newNameType(name, desc)); - result = new Item(index++, key3); - put(result); - } - return result; - } - - /** - * Adds a method reference to the constant pool of the class being build. - * Does nothing if the constant pool already contains a similar item. - * <i>This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters.</i> - * - * @param owner - * the internal name of the method's owner class. - * @param name - * the method's name. - * @param desc - * the method's descriptor. - * @param itf - * <tt>true</tt> if <tt>owner</tt> is an interface. - * @return the index of a new or already existing method reference item. - */ - public int newMethod(final String owner, final String name, - final String desc, final boolean itf) { - return newMethodItem(owner, name, desc, itf).index; - } - - /** - * Adds an integer to the constant pool of the class being build. Does - * nothing if the constant pool already contains a similar item. - * - * @param value - * the int value. - * @return a new or already existing int item. - */ - Item newInteger(final int value) { - key.set(value); - Item result = get(key); - if (result == null) { - pool.putByte(INT).putInt(value); - result = new Item(index++, key); - put(result); - } - return result; - } - - /** - * Adds a float to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. - * - * @param value - * the float value. - * @return a new or already existing float item. - */ - Item newFloat(final float value) { - key.set(value); - Item result = get(key); - if (result == null) { - pool.putByte(FLOAT).putInt(key.intVal); - result = new Item(index++, key); - put(result); - } - return result; - } - - /** - * Adds a long to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. - * - * @param value - * the long value. - * @return a new or already existing long item. - */ - Item newLong(final long value) { - key.set(value); - Item result = get(key); - if (result == null) { - pool.putByte(LONG).putLong(value); - result = new Item(index, key); - index += 2; - put(result); - } - return result; - } - - /** - * Adds a double to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. - * - * @param value - * the double value. - * @return a new or already existing double item. - */ - Item newDouble(final double value) { - key.set(value); - Item result = get(key); - if (result == null) { - pool.putByte(DOUBLE).putLong(key.longVal); - result = new Item(index, key); - index += 2; - put(result); - } - return result; - } - - /** - * Adds a string to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. - * - * @param value - * the String value. - * @return a new or already existing string item. - */ - private Item newString(final String value) { - key2.set(STR, value, null, null); - Item result = get(key2); - if (result == null) { - pool.put12(STR, newUTF8(value)); - result = new Item(index++, key2); - put(result); - } - return result; - } - - /** - * Adds a name and type to the constant pool of the class being build. Does - * nothing if the constant pool already contains a similar item. <i>This - * method is intended for {@link Attribute} sub classes, and is normally not - * needed by class generators or adapters.</i> - * - * @param name - * a name. - * @param desc - * a type descriptor. - * @return the index of a new or already existing name and type item. - */ - public int newNameType(final String name, final String desc) { - return newNameTypeItem(name, desc).index; - } - - /** - * Adds a name and type to the constant pool of the class being build. Does - * nothing if the constant pool already contains a similar item. - * - * @param name - * a name. - * @param desc - * a type descriptor. - * @return a new or already existing name and type item. - */ - Item newNameTypeItem(final String name, final String desc) { - key2.set(NAME_TYPE, name, desc, null); - Item result = get(key2); - if (result == null) { - put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); - result = new Item(index++, key2); - put(result); - } - return result; - } - - /** - * Adds the given internal name to {@link #typeTable} and returns its index. - * Does nothing if the type table already contains this internal name. - * - * @param type - * the internal name to be added to the type table. - * @return the index of this internal name in the type table. - */ - int addType(final String type) { - key.set(TYPE_NORMAL, type, null, null); - Item result = get(key); - if (result == null) { - result = addType(key); - } - return result.index; - } - - /** - * Adds the given "uninitialized" type to {@link #typeTable} and returns its - * index. This method is used for UNINITIALIZED types, made of an internal - * name and a bytecode offset. - * - * @param type - * the internal name to be added to the type table. - * @param offset - * the bytecode offset of the NEW instruction that created this - * UNINITIALIZED type value. - * @return the index of this internal name in the type table. - */ - int addUninitializedType(final String type, final int offset) { - key.type = TYPE_UNINIT; - key.intVal = offset; - key.strVal1 = type; - key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset); - Item result = get(key); - if (result == null) { - result = addType(key); - } - return result.index; - } - - /** - * Adds the given Item to {@link #typeTable}. - * - * @param item - * the value to be added to the type table. - * @return the added Item, which a new Item instance with the same value as - * the given Item. - */ - private Item addType(final Item item) { - ++typeCount; - Item result = new Item(typeCount, key); - put(result); - if (typeTable == null) { - typeTable = new Item[16]; - } - if (typeCount == typeTable.length) { - Item[] newTable = new Item[2 * typeTable.length]; - System.arraycopy(typeTable, 0, newTable, 0, typeTable.length); - typeTable = newTable; - } - typeTable[typeCount] = result; - return result; - } - - /** - * Returns the index of the common super type of the two given types. This - * method calls {@link #getCommonSuperClass} and caches the result in the - * {@link #items} hash table to speedup future calls with the same - * parameters. - * - * @param type1 - * index of an internal name in {@link #typeTable}. - * @param type2 - * index of an internal name in {@link #typeTable}. - * @return the index of the common super type of the two given types. - */ - int getMergedType(final int type1, final int type2) { - key2.type = TYPE_MERGED; - key2.longVal = type1 | (((long) type2) << 32); - key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2); - Item result = get(key2); - if (result == null) { - String t = typeTable[type1].strVal1; - String u = typeTable[type2].strVal1; - key2.intVal = addType(getCommonSuperClass(t, u)); - result = new Item((short) 0, key2); - put(result); - } - return result.intVal; - } - - /** - * Returns the common super type of the two given types. The default - * implementation of this method <i>loads</i> the two given classes and uses - * the java.lang.Class methods to find the common super class. It can be - * overridden to compute this common super type in other ways, in particular - * without actually loading any class, or to take into account the class - * that is currently being generated by this ClassWriter, which can of - * course not be loaded since it is under construction. - * - * @param type1 - * the internal name of a class. - * @param type2 - * the internal name of another class. - * @return the internal name of the common super class of the two given - * classes. - */ - protected String getCommonSuperClass(final String type1, final String type2) { - Class<?> c, d; - ClassLoader classLoader = getClass().getClassLoader(); - try { - c = Class.forName(type1.replace('/', '.'), false, classLoader); - d = Class.forName(type2.replace('/', '.'), false, classLoader); - } catch (Exception e) { - throw new RuntimeException(e.toString()); - } - if (c.isAssignableFrom(d)) { - return type1; - } - if (d.isAssignableFrom(c)) { - return type2; - } - if (c.isInterface() || d.isInterface()) { - return "java/lang/Object"; - } else { - do { - c = c.getSuperclass(); - } while (!c.isAssignableFrom(d)); - return c.getName().replace('.', '/'); - } - } - - /** - * Returns the constant pool's hash table item which is equal to the given - * item. - * - * @param key - * a constant pool item. - * @return the constant pool's hash table item which is equal to the given - * item, or <tt>null</tt> if there is no such item. - */ - private Item get(final Item key) { - Item i = items[key.hashCode % items.length]; - while (i != null && (i.type != key.type || !key.isEqualTo(i))) { - i = i.next; - } - return i; - } - - /** - * Puts the given item in the constant pool's hash table. The hash table - * <i>must</i> not already contains this item. - * - * @param i - * the item to be added to the constant pool's hash table. - */ - private void put(final Item i) { - if (index + typeCount > threshold) { - int ll = items.length; - int nl = ll * 2 + 1; - Item[] newItems = new Item[nl]; - for (int l = ll - 1; l >= 0; --l) { - Item j = items[l]; - while (j != null) { - int index = j.hashCode % newItems.length; - Item k = j.next; - j.next = newItems[index]; - newItems[index] = j; - j = k; - } - } - items = newItems; - threshold = (int) (nl * 0.75); - } - int index = i.hashCode % items.length; - i.next = items[index]; - items[index] = i; - } - - /** - * Find item that whose index is `index`. - */ - public Item findItemByIndex(int index) { - int i = 0; - while (i < items.length && (items[i] == null || items[i].index != index)) i++; - return items[i]; - } - - /** - * Puts one byte and two shorts into the constant pool. - * - * @param b - * a byte. - * @param s1 - * a short. - * @param s2 - * another short. - */ - private void put122(final int b, final int s1, final int s2) { - pool.put12(b, s1).putShort(s2); - } - - /** - * Puts two bytes and one short into the constant pool. - * - * @param b1 - * a byte. - * @param b2 - * another byte. - * @param s - * a short. - */ - private void put112(final int b1, final int b2, final int s) { - pool.put11(b1, b2).putShort(s); - } -} diff --git a/src/asm/scala/tools/asm/Context.java b/src/asm/scala/tools/asm/Context.java deleted file mode 100644 index 24546969e3..0000000000 --- a/src/asm/scala/tools/asm/Context.java +++ /dev/null @@ -1,145 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package scala.tools.asm; - -/** - * Information about a class being parsed in a {@link ClassReader}. - * - * @author Eric Bruneton - */ -class Context { - - /** - * Prototypes of the attributes that must be parsed for this class. - */ - Attribute[] attrs; - - /** - * The {@link ClassReader} option flags for the parsing of this class. - */ - int flags; - - /** - * The buffer used to read strings. - */ - char[] buffer; - - /** - * The start index of each bootstrap method. - */ - int[] bootstrapMethods; - - /** - * The access flags of the method currently being parsed. - */ - int access; - - /** - * The name of the method currently being parsed. - */ - String name; - - /** - * The descriptor of the method currently being parsed. - */ - String desc; - - /** - * The label objects, indexed by bytecode offset, of the method currently - * being parsed (only bytecode offsets for which a label is needed have a - * non null associated Label object). - */ - Label[] labels; - - /** - * The target of the type annotation currently being parsed. - */ - int typeRef; - - /** - * The path of the type annotation currently being parsed. - */ - TypePath typePath; - - /** - * The offset of the latest stack map frame that has been parsed. - */ - int offset; - - /** - * The labels corresponding to the start of the local variable ranges in the - * local variable type annotation currently being parsed. - */ - Label[] start; - - /** - * The labels corresponding to the end of the local variable ranges in the - * local variable type annotation currently being parsed. - */ - Label[] end; - - /** - * The local variable indices for each local variable range in the local - * variable type annotation currently being parsed. - */ - int[] index; - - /** - * The encoding of the latest stack map frame that has been parsed. - */ - int mode; - - /** - * The number of locals in the latest stack map frame that has been parsed. - */ - int localCount; - - /** - * The number locals in the latest stack map frame that has been parsed, - * minus the number of locals in the previous frame. - */ - int localDiff; - - /** - * The local values of the latest stack map frame that has been parsed. - */ - Object[] local; - - /** - * The stack size of the latest stack map frame that has been parsed. - */ - int stackCount; - - /** - * The stack values of the latest stack map frame that has been parsed. - */ - Object[] stack; -} diff --git a/src/asm/scala/tools/asm/CustomAttr.java b/src/asm/scala/tools/asm/CustomAttr.java deleted file mode 100644 index 5ecfd283d0..0000000000 --- a/src/asm/scala/tools/asm/CustomAttr.java +++ /dev/null @@ -1,20 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2012 LAMP/EPFL - */ - -package scala.tools.asm; - -import scala.tools.asm.Attribute; - -/** - * A subclass of ASM's Attribute for the sole purpose of accessing a protected field there. - * - */ -public class CustomAttr extends Attribute { - - public CustomAttr(final String type, final byte[] value) { - super(type); - super.value = value; - } - -} diff --git a/src/asm/scala/tools/asm/Edge.java b/src/asm/scala/tools/asm/Edge.java deleted file mode 100644 index daac1f7bb0..0000000000 --- a/src/asm/scala/tools/asm/Edge.java +++ /dev/null @@ -1,75 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * An edge in the control flow graph of a method body. See {@link Label Label}. - * - * @author Eric Bruneton - */ -class Edge { - - /** - * Denotes a normal control flow graph edge. - */ - static final int NORMAL = 0; - - /** - * Denotes a control flow graph edge corresponding to an exception handler. - * More precisely any {@link Edge} whose {@link #info} is strictly positive - * corresponds to an exception handler. The actual value of {@link #info} is - * the index, in the {@link ClassWriter} type table, of the exception that - * is catched. - */ - static final int EXCEPTION = 0x7FFFFFFF; - - /** - * Information about this control flow graph edge. If - * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative) - * stack size in the basic block from which this edge originates. This size - * is equal to the stack size at the "jump" instruction to which this edge - * corresponds, relatively to the stack size at the beginning of the - * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used, - * this field is the kind of this control flow graph edge (i.e. NORMAL or - * EXCEPTION). - */ - int info; - - /** - * The successor block of the basic block from which this edge originates. - */ - Label successor; - - /** - * The next edge in the list of successors of the originating basic block. - * See {@link Label#successors successors}. - */ - Edge next; -} diff --git a/src/asm/scala/tools/asm/FieldVisitor.java b/src/asm/scala/tools/asm/FieldVisitor.java deleted file mode 100644 index 708c1d322e..0000000000 --- a/src/asm/scala/tools/asm/FieldVisitor.java +++ /dev/null @@ -1,150 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * A visitor to visit a Java field. The methods of this class must be called in - * the following order: ( <tt>visitAnnotation</tt> | - * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>. - * - * @author Eric Bruneton - */ -public abstract class FieldVisitor { - - /** - * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected final int api; - - /** - * The field visitor to which this visitor must delegate method calls. May - * be null. - */ - protected FieldVisitor fv; - - /** - * Constructs a new {@link FieldVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public FieldVisitor(final int api) { - this(api, null); - } - - /** - * Constructs a new {@link FieldVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param fv - * the field visitor to which this visitor must delegate method - * calls. May be null. - */ - public FieldVisitor(final int api, final FieldVisitor fv) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { - throw new IllegalArgumentException(); - } - this.api = api; - this.fv = fv; - } - - /** - * Visits an annotation of the field. - * - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or <tt>null</tt> if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - if (fv != null) { - return fv.visitAnnotation(desc, visible); - } - return null; - } - - /** - * Visits an annotation on the type of the field. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#FIELD FIELD}. See - * {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or <tt>null</tt> if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (fv != null) { - return fv.visitTypeAnnotation(typeRef, typePath, desc, visible); - } - return null; - } - - /** - * Visits a non standard attribute of the field. - * - * @param attr - * an attribute. - */ - public void visitAttribute(Attribute attr) { - if (fv != null) { - fv.visitAttribute(attr); - } - } - - /** - * Visits the end of the field. This method, which is the last one to be - * called, is used to inform the visitor that all the annotations and - * attributes of the field have been visited. - */ - public void visitEnd() { - if (fv != null) { - fv.visitEnd(); - } - } -} diff --git a/src/asm/scala/tools/asm/FieldWriter.java b/src/asm/scala/tools/asm/FieldWriter.java deleted file mode 100644 index e640a8d406..0000000000 --- a/src/asm/scala/tools/asm/FieldWriter.java +++ /dev/null @@ -1,329 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * An {@link FieldVisitor} that generates Java fields in bytecode form. - * - * @author Eric Bruneton - */ -final class FieldWriter extends FieldVisitor { - - /** - * The class writer to which this field must be added. - */ - private final ClassWriter cw; - - /** - * Access flags of this field. - */ - private final int access; - - /** - * The index of the constant pool item that contains the name of this - * method. - */ - private final int name; - - /** - * The index of the constant pool item that contains the descriptor of this - * field. - */ - private final int desc; - - /** - * The index of the constant pool item that contains the signature of this - * field. - */ - private int signature; - - /** - * The index of the constant pool item that contains the constant value of - * this field. - */ - private int value; - - /** - * The runtime visible annotations of this field. May be <tt>null</tt>. - */ - private AnnotationWriter anns; - - /** - * The runtime invisible annotations of this field. May be <tt>null</tt>. - */ - private AnnotationWriter ianns; - - /** - * The runtime visible type annotations of this field. May be <tt>null</tt>. - */ - private AnnotationWriter tanns; - - /** - * The runtime invisible type annotations of this field. May be - * <tt>null</tt>. - */ - private AnnotationWriter itanns; - - /** - * The non standard attributes of this field. May be <tt>null</tt>. - */ - private Attribute attrs; - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link FieldWriter}. - * - * @param cw - * the class writer to which this field must be added. - * @param access - * the field's access flags (see {@link Opcodes}). - * @param name - * the field's name. - * @param desc - * the field's descriptor (see {@link Type}). - * @param signature - * the field's signature. May be <tt>null</tt>. - * @param value - * the field's constant value. May be <tt>null</tt>. - */ - FieldWriter(final ClassWriter cw, final int access, final String name, - final String desc, final String signature, final Object value) { - super(Opcodes.ASM5); - if (cw.firstField == null) { - cw.firstField = this; - } else { - cw.lastField.fv = this; - } - cw.lastField = this; - this.cw = cw; - this.access = access; - this.name = cw.newUTF8(name); - this.desc = cw.newUTF8(desc); - if (ClassReader.SIGNATURES && signature != null) { - this.signature = cw.newUTF8(signature); - } - if (value != null) { - this.value = cw.newConstItem(value).index; - } - } - - // ------------------------------------------------------------------------ - // Implementation of the FieldVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); - if (visible) { - aw.next = anns; - anns = aw; - } else { - aw.next = ianns; - ianns = aw; - } - return aw; - } - - @Override - public AnnotationVisitor visitTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - AnnotationWriter.putTarget(typeRef, typePath, bv); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = tanns; - tanns = aw; - } else { - aw.next = itanns; - itanns = aw; - } - return aw; - } - - @Override - public void visitAttribute(final Attribute attr) { - attr.next = attrs; - attrs = attr; - } - - @Override - public void visitEnd() { - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - /** - * Returns the size of this field. - * - * @return the size of this field. - */ - int getSize() { - int size = 8; - if (value != 0) { - cw.newUTF8("ConstantValue"); - size += 8; - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - cw.newUTF8("Synthetic"); - size += 6; - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - cw.newUTF8("Deprecated"); - size += 6; - } - if (ClassReader.SIGNATURES && signature != 0) { - cw.newUTF8("Signature"); - size += 8; - } - if (ClassReader.ANNOTATIONS && anns != null) { - cw.newUTF8("RuntimeVisibleAnnotations"); - size += 8 + anns.getSize(); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - cw.newUTF8("RuntimeInvisibleAnnotations"); - size += 8 + ianns.getSize(); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - cw.newUTF8("RuntimeVisibleTypeAnnotations"); - size += 8 + tanns.getSize(); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - cw.newUTF8("RuntimeInvisibleTypeAnnotations"); - size += 8 + itanns.getSize(); - } - if (attrs != null) { - size += attrs.getSize(cw, null, 0, -1, -1); - } - return size; - } - - /** - * Puts the content of this field into the given byte vector. - * - * @param out - * where the content of this field must be put. - */ - void put(final ByteVector out) { - final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; - int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); - out.putShort(access & ~mask).putShort(name).putShort(desc); - int attributeCount = 0; - if (value != 0) { - ++attributeCount; - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - ++attributeCount; - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - ++attributeCount; - } - if (ClassReader.SIGNATURES && signature != 0) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && anns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && ianns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && tanns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && itanns != null) { - ++attributeCount; - } - if (attrs != null) { - attributeCount += attrs.getCount(); - } - out.putShort(attributeCount); - if (value != 0) { - out.putShort(cw.newUTF8("ConstantValue")); - out.putInt(2).putShort(value); - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - out.putShort(cw.newUTF8("Synthetic")).putInt(0); - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - out.putShort(cw.newUTF8("Deprecated")).putInt(0); - } - if (ClassReader.SIGNATURES && signature != 0) { - out.putShort(cw.newUTF8("Signature")); - out.putInt(2).putShort(signature); - } - if (ClassReader.ANNOTATIONS && anns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); - anns.put(out); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); - ianns.put(out); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); - tanns.put(out); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); - itanns.put(out); - } - if (attrs != null) { - attrs.put(cw, null, 0, -1, -1, out); - } - } -} diff --git a/src/asm/scala/tools/asm/Frame.java b/src/asm/scala/tools/asm/Frame.java deleted file mode 100644 index 85ad3269ab..0000000000 --- a/src/asm/scala/tools/asm/Frame.java +++ /dev/null @@ -1,1462 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * Information about the input and output stack map frames of a basic block. - * - * @author Eric Bruneton - */ -final class Frame { - - /* - * Frames are computed in a two steps process: during the visit of each - * instruction, the state of the frame at the end of current basic block is - * updated by simulating the action of the instruction on the previous state - * of this so called "output frame". In visitMaxs, a fix point algorithm is - * used to compute the "input frame" of each basic block, i.e. the stack map - * frame at the beginning of the basic block, starting from the input frame - * of the first basic block (which is computed from the method descriptor), - * and by using the previously computed output frames to compute the input - * state of the other blocks. - * - * All output and input frames are stored as arrays of integers. Reference - * and array types are represented by an index into a type table (which is - * not the same as the constant pool of the class, in order to avoid adding - * unnecessary constants in the pool - not all computed frames will end up - * being stored in the stack map table). This allows very fast type - * comparisons. - * - * Output stack map frames are computed relatively to the input frame of the - * basic block, which is not yet known when output frames are computed. It - * is therefore necessary to be able to represent abstract types such as - * "the type at position x in the input frame locals" or "the type at - * position x from the top of the input frame stack" or even "the type at - * position x in the input frame, with y more (or less) array dimensions". - * This explains the rather complicated type format used in output frames. - * - * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a - * signed number of array dimensions (from -8 to 7). KIND is either BASE, - * LOCAL or STACK. BASE is used for types that are not relative to the input - * frame. LOCAL is used for types that are relative to the input local - * variable types. STACK is used for types that are relative to the input - * stack types. VALUE depends on KIND. For LOCAL types, it is an index in - * the input local variable types. For STACK types, it is a position - * relatively to the top of input frame stack. For BASE types, it is either - * one of the constants defined below, or for OBJECT and UNINITIALIZED - * types, a tag and an index in the type table. - * - * Output frames can contain types of any kind and with a positive or - * negative dimension (and even unassigned types, represented by 0 - which - * does not correspond to any valid type value). Input frames can only - * contain BASE types of positive or null dimension. In all cases the type - * table contains only internal type names (array type descriptors are - * forbidden - dimensions must be represented through the DIM field). - * - * The LONG and DOUBLE types are always represented by using two slots (LONG - * + TOP or DOUBLE + TOP), for local variable types as well as in the - * operand stack. This is necessary to be able to simulate DUPx_y - * instructions, whose effect would be dependent on the actual type values - * if types were always represented by a single slot in the stack (and this - * is not possible, since actual type values are not always known - cf LOCAL - * and STACK type kinds). - */ - - /** - * Mask to get the dimension of a frame type. This dimension is a signed - * integer between -8 and 7. - */ - static final int DIM = 0xF0000000; - - /** - * Constant to be added to a type to get a type with one more dimension. - */ - static final int ARRAY_OF = 0x10000000; - - /** - * Constant to be added to a type to get a type with one less dimension. - */ - static final int ELEMENT_OF = 0xF0000000; - - /** - * Mask to get the kind of a frame type. - * - * @see #BASE - * @see #LOCAL - * @see #STACK - */ - static final int KIND = 0xF000000; - - /** - * Flag used for LOCAL and STACK types. Indicates that if this type happens - * to be a long or double type (during the computations of input frames), - * then it must be set to TOP because the second word of this value has been - * reused to store other data in the basic block. Hence the first word no - * longer stores a valid long or double value. - */ - static final int TOP_IF_LONG_OR_DOUBLE = 0x800000; - - /** - * Mask to get the value of a frame type. - */ - static final int VALUE = 0x7FFFFF; - - /** - * Mask to get the kind of base types. - */ - static final int BASE_KIND = 0xFF00000; - - /** - * Mask to get the value of base types. - */ - static final int BASE_VALUE = 0xFFFFF; - - /** - * Kind of the types that are not relative to an input stack map frame. - */ - static final int BASE = 0x1000000; - - /** - * Base kind of the base reference types. The BASE_VALUE of such types is an - * index into the type table. - */ - static final int OBJECT = BASE | 0x700000; - - /** - * Base kind of the uninitialized base types. The BASE_VALUE of such types - * in an index into the type table (the Item at that index contains both an - * instruction offset and an internal class name). - */ - static final int UNINITIALIZED = BASE | 0x800000; - - /** - * Kind of the types that are relative to the local variable types of an - * input stack map frame. The value of such types is a local variable index. - */ - private static final int LOCAL = 0x2000000; - - /** - * Kind of the the types that are relative to the stack of an input stack - * map frame. The value of such types is a position relatively to the top of - * this stack. - */ - private static final int STACK = 0x3000000; - - /** - * The TOP type. This is a BASE type. - */ - static final int TOP = BASE | 0; - - /** - * The BOOLEAN type. This is a BASE type mainly used for array types. - */ - static final int BOOLEAN = BASE | 9; - - /** - * The BYTE type. This is a BASE type mainly used for array types. - */ - static final int BYTE = BASE | 10; - - /** - * The CHAR type. This is a BASE type mainly used for array types. - */ - static final int CHAR = BASE | 11; - - /** - * The SHORT type. This is a BASE type mainly used for array types. - */ - static final int SHORT = BASE | 12; - - /** - * The INTEGER type. This is a BASE type. - */ - static final int INTEGER = BASE | 1; - - /** - * The FLOAT type. This is a BASE type. - */ - static final int FLOAT = BASE | 2; - - /** - * The DOUBLE type. This is a BASE type. - */ - static final int DOUBLE = BASE | 3; - - /** - * The LONG type. This is a BASE type. - */ - static final int LONG = BASE | 4; - - /** - * The NULL type. This is a BASE type. - */ - static final int NULL = BASE | 5; - - /** - * The UNINITIALIZED_THIS type. This is a BASE type. - */ - static final int UNINITIALIZED_THIS = BASE | 6; - - /** - * The stack size variation corresponding to each JVM instruction. This - * stack variation is equal to the size of the values produced by an - * instruction, minus the size of the values consumed by this instruction. - */ - static final int[] SIZE; - - /** - * Computes the stack size variation corresponding to each JVM instruction. - */ - static { - int i; - int[] b = new int[202]; - String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD" - + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD" - + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED" - + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE"; - for (i = 0; i < b.length; ++i) { - b[i] = s.charAt(i) - 'E'; - } - SIZE = b; - - // code to generate the above string - // - // int NA = 0; // not applicable (unused opcode or variable size opcode) - // - // b = new int[] { - // 0, //NOP, // visitInsn - // 1, //ACONST_NULL, // - - // 1, //ICONST_M1, // - - // 1, //ICONST_0, // - - // 1, //ICONST_1, // - - // 1, //ICONST_2, // - - // 1, //ICONST_3, // - - // 1, //ICONST_4, // - - // 1, //ICONST_5, // - - // 2, //LCONST_0, // - - // 2, //LCONST_1, // - - // 1, //FCONST_0, // - - // 1, //FCONST_1, // - - // 1, //FCONST_2, // - - // 2, //DCONST_0, // - - // 2, //DCONST_1, // - - // 1, //BIPUSH, // visitIntInsn - // 1, //SIPUSH, // - - // 1, //LDC, // visitLdcInsn - // NA, //LDC_W, // - - // NA, //LDC2_W, // - - // 1, //ILOAD, // visitVarInsn - // 2, //LLOAD, // - - // 1, //FLOAD, // - - // 2, //DLOAD, // - - // 1, //ALOAD, // - - // NA, //ILOAD_0, // - - // NA, //ILOAD_1, // - - // NA, //ILOAD_2, // - - // NA, //ILOAD_3, // - - // NA, //LLOAD_0, // - - // NA, //LLOAD_1, // - - // NA, //LLOAD_2, // - - // NA, //LLOAD_3, // - - // NA, //FLOAD_0, // - - // NA, //FLOAD_1, // - - // NA, //FLOAD_2, // - - // NA, //FLOAD_3, // - - // NA, //DLOAD_0, // - - // NA, //DLOAD_1, // - - // NA, //DLOAD_2, // - - // NA, //DLOAD_3, // - - // NA, //ALOAD_0, // - - // NA, //ALOAD_1, // - - // NA, //ALOAD_2, // - - // NA, //ALOAD_3, // - - // -1, //IALOAD, // visitInsn - // 0, //LALOAD, // - - // -1, //FALOAD, // - - // 0, //DALOAD, // - - // -1, //AALOAD, // - - // -1, //BALOAD, // - - // -1, //CALOAD, // - - // -1, //SALOAD, // - - // -1, //ISTORE, // visitVarInsn - // -2, //LSTORE, // - - // -1, //FSTORE, // - - // -2, //DSTORE, // - - // -1, //ASTORE, // - - // NA, //ISTORE_0, // - - // NA, //ISTORE_1, // - - // NA, //ISTORE_2, // - - // NA, //ISTORE_3, // - - // NA, //LSTORE_0, // - - // NA, //LSTORE_1, // - - // NA, //LSTORE_2, // - - // NA, //LSTORE_3, // - - // NA, //FSTORE_0, // - - // NA, //FSTORE_1, // - - // NA, //FSTORE_2, // - - // NA, //FSTORE_3, // - - // NA, //DSTORE_0, // - - // NA, //DSTORE_1, // - - // NA, //DSTORE_2, // - - // NA, //DSTORE_3, // - - // NA, //ASTORE_0, // - - // NA, //ASTORE_1, // - - // NA, //ASTORE_2, // - - // NA, //ASTORE_3, // - - // -3, //IASTORE, // visitInsn - // -4, //LASTORE, // - - // -3, //FASTORE, // - - // -4, //DASTORE, // - - // -3, //AASTORE, // - - // -3, //BASTORE, // - - // -3, //CASTORE, // - - // -3, //SASTORE, // - - // -1, //POP, // - - // -2, //POP2, // - - // 1, //DUP, // - - // 1, //DUP_X1, // - - // 1, //DUP_X2, // - - // 2, //DUP2, // - - // 2, //DUP2_X1, // - - // 2, //DUP2_X2, // - - // 0, //SWAP, // - - // -1, //IADD, // - - // -2, //LADD, // - - // -1, //FADD, // - - // -2, //DADD, // - - // -1, //ISUB, // - - // -2, //LSUB, // - - // -1, //FSUB, // - - // -2, //DSUB, // - - // -1, //IMUL, // - - // -2, //LMUL, // - - // -1, //FMUL, // - - // -2, //DMUL, // - - // -1, //IDIV, // - - // -2, //LDIV, // - - // -1, //FDIV, // - - // -2, //DDIV, // - - // -1, //IREM, // - - // -2, //LREM, // - - // -1, //FREM, // - - // -2, //DREM, // - - // 0, //INEG, // - - // 0, //LNEG, // - - // 0, //FNEG, // - - // 0, //DNEG, // - - // -1, //ISHL, // - - // -1, //LSHL, // - - // -1, //ISHR, // - - // -1, //LSHR, // - - // -1, //IUSHR, // - - // -1, //LUSHR, // - - // -1, //IAND, // - - // -2, //LAND, // - - // -1, //IOR, // - - // -2, //LOR, // - - // -1, //IXOR, // - - // -2, //LXOR, // - - // 0, //IINC, // visitIincInsn - // 1, //I2L, // visitInsn - // 0, //I2F, // - - // 1, //I2D, // - - // -1, //L2I, // - - // -1, //L2F, // - - // 0, //L2D, // - - // 0, //F2I, // - - // 1, //F2L, // - - // 1, //F2D, // - - // -1, //D2I, // - - // 0, //D2L, // - - // -1, //D2F, // - - // 0, //I2B, // - - // 0, //I2C, // - - // 0, //I2S, // - - // -3, //LCMP, // - - // -1, //FCMPL, // - - // -1, //FCMPG, // - - // -3, //DCMPL, // - - // -3, //DCMPG, // - - // -1, //IFEQ, // visitJumpInsn - // -1, //IFNE, // - - // -1, //IFLT, // - - // -1, //IFGE, // - - // -1, //IFGT, // - - // -1, //IFLE, // - - // -2, //IF_ICMPEQ, // - - // -2, //IF_ICMPNE, // - - // -2, //IF_ICMPLT, // - - // -2, //IF_ICMPGE, // - - // -2, //IF_ICMPGT, // - - // -2, //IF_ICMPLE, // - - // -2, //IF_ACMPEQ, // - - // -2, //IF_ACMPNE, // - - // 0, //GOTO, // - - // 1, //JSR, // - - // 0, //RET, // visitVarInsn - // -1, //TABLESWITCH, // visiTableSwitchInsn - // -1, //LOOKUPSWITCH, // visitLookupSwitch - // -1, //IRETURN, // visitInsn - // -2, //LRETURN, // - - // -1, //FRETURN, // - - // -2, //DRETURN, // - - // -1, //ARETURN, // - - // 0, //RETURN, // - - // NA, //GETSTATIC, // visitFieldInsn - // NA, //PUTSTATIC, // - - // NA, //GETFIELD, // - - // NA, //PUTFIELD, // - - // NA, //INVOKEVIRTUAL, // visitMethodInsn - // NA, //INVOKESPECIAL, // - - // NA, //INVOKESTATIC, // - - // NA, //INVOKEINTERFACE, // - - // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn - // 1, //NEW, // visitTypeInsn - // 0, //NEWARRAY, // visitIntInsn - // 0, //ANEWARRAY, // visitTypeInsn - // 0, //ARRAYLENGTH, // visitInsn - // NA, //ATHROW, // - - // 0, //CHECKCAST, // visitTypeInsn - // 0, //INSTANCEOF, // - - // -1, //MONITORENTER, // visitInsn - // -1, //MONITOREXIT, // - - // NA, //WIDE, // NOT VISITED - // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn - // -1, //IFNULL, // visitJumpInsn - // -1, //IFNONNULL, // - - // NA, //GOTO_W, // - - // NA, //JSR_W, // - - // }; - // for (i = 0; i < b.length; ++i) { - // System.err.print((char)('E' + b[i])); - // } - // System.err.println(); - } - - /** - * The label (i.e. basic block) to which these input and output stack map - * frames correspond. - */ - Label owner; - - /** - * The input stack map frame locals. - */ - int[] inputLocals; - - /** - * The input stack map frame stack. - */ - int[] inputStack; - - /** - * The output stack map frame locals. - */ - private int[] outputLocals; - - /** - * The output stack map frame stack. - */ - private int[] outputStack; - - /** - * Relative size of the output stack. The exact semantics of this field - * depends on the algorithm that is used. - * - * When only the maximum stack size is computed, this field is the size of - * the output stack relatively to the top of the input stack. - * - * When the stack map frames are completely computed, this field is the - * actual number of types in {@link #outputStack}. - */ - private int outputStackTop; - - /** - * Number of types that are initialized in the basic block. - * - * @see #initializations - */ - private int initializationCount; - - /** - * The types that are initialized in the basic block. A constructor - * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace - * <i>every occurence</i> of this type in the local variables and in the - * operand stack. This cannot be done during the first phase of the - * algorithm since, during this phase, the local variables and the operand - * stack are not completely computed. It is therefore necessary to store the - * types on which constructors are invoked in the basic block, in order to - * do this replacement during the second phase of the algorithm, where the - * frames are fully computed. Note that this array can contain types that - * are relative to input locals or to the input stack (see below for the - * description of the algorithm). - */ - private int[] initializations; - - /** - * Returns the output frame local variable type at the given index. - * - * @param local - * the index of the local that must be returned. - * @return the output frame local variable type at the given index. - */ - private int get(final int local) { - if (outputLocals == null || local >= outputLocals.length) { - // this local has never been assigned in this basic block, - // so it is still equal to its value in the input frame - return LOCAL | local; - } else { - int type = outputLocals[local]; - if (type == 0) { - // this local has never been assigned in this basic block, - // so it is still equal to its value in the input frame - type = outputLocals[local] = LOCAL | local; - } - return type; - } - } - - /** - * Sets the output frame local variable type at the given index. - * - * @param local - * the index of the local that must be set. - * @param type - * the value of the local that must be set. - */ - private void set(final int local, final int type) { - // creates and/or resizes the output local variables array if necessary - if (outputLocals == null) { - outputLocals = new int[10]; - } - int n = outputLocals.length; - if (local >= n) { - int[] t = new int[Math.max(local + 1, 2 * n)]; - System.arraycopy(outputLocals, 0, t, 0, n); - outputLocals = t; - } - // sets the local variable - outputLocals[local] = type; - } - - /** - * Pushes a new type onto the output frame stack. - * - * @param type - * the type that must be pushed. - */ - private void push(final int type) { - // creates and/or resizes the output stack array if necessary - if (outputStack == null) { - outputStack = new int[10]; - } - int n = outputStack.length; - if (outputStackTop >= n) { - int[] t = new int[Math.max(outputStackTop + 1, 2 * n)]; - System.arraycopy(outputStack, 0, t, 0, n); - outputStack = t; - } - // pushes the type on the output stack - outputStack[outputStackTop++] = type; - // updates the maximun height reached by the output stack, if needed - int top = owner.inputStackTop + outputStackTop; - if (top > owner.outputStackMax) { - owner.outputStackMax = top; - } - } - - /** - * Pushes a new type onto the output frame stack. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param desc - * the descriptor of the type to be pushed. Can also be a method - * descriptor (in this case this method pushes its return type - * onto the output frame stack). - */ - private void push(final ClassWriter cw, final String desc) { - int type = type(cw, desc); - if (type != 0) { - push(type); - if (type == LONG || type == DOUBLE) { - push(TOP); - } - } - } - - /** - * Returns the int encoding of the given type. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param desc - * a type descriptor. - * @return the int encoding of the given type. - */ - private static int type(final ClassWriter cw, final String desc) { - String t; - int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; - switch (desc.charAt(index)) { - case 'V': - return 0; - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - return INTEGER; - case 'F': - return FLOAT; - case 'J': - return LONG; - case 'D': - return DOUBLE; - case 'L': - // stores the internal name, not the descriptor! - t = desc.substring(index + 1, desc.length() - 1); - return OBJECT | cw.addType(t); - // case '[': - default: - // extracts the dimensions and the element type - int data; - int dims = index + 1; - while (desc.charAt(dims) == '[') { - ++dims; - } - switch (desc.charAt(dims)) { - case 'Z': - data = BOOLEAN; - break; - case 'C': - data = CHAR; - break; - case 'B': - data = BYTE; - break; - case 'S': - data = SHORT; - break; - case 'I': - data = INTEGER; - break; - case 'F': - data = FLOAT; - break; - case 'J': - data = LONG; - break; - case 'D': - data = DOUBLE; - break; - // case 'L': - default: - // stores the internal name, not the descriptor - t = desc.substring(dims + 1, desc.length() - 1); - data = OBJECT | cw.addType(t); - } - return (dims - index) << 28 | data; - } - } - - /** - * Pops a type from the output frame stack and returns its value. - * - * @return the type that has been popped from the output frame stack. - */ - private int pop() { - if (outputStackTop > 0) { - return outputStack[--outputStackTop]; - } else { - // if the output frame stack is empty, pops from the input stack - return STACK | -(--owner.inputStackTop); - } - } - - /** - * Pops the given number of types from the output frame stack. - * - * @param elements - * the number of types that must be popped. - */ - private void pop(final int elements) { - if (outputStackTop >= elements) { - outputStackTop -= elements; - } else { - // if the number of elements to be popped is greater than the number - // of elements in the output stack, clear it, and pops the remaining - // elements from the input stack. - owner.inputStackTop -= elements - outputStackTop; - outputStackTop = 0; - } - } - - /** - * Pops a type from the output frame stack. - * - * @param desc - * the descriptor of the type to be popped. Can also be a method - * descriptor (in this case this method pops the types - * corresponding to the method arguments). - */ - private void pop(final String desc) { - char c = desc.charAt(0); - if (c == '(') { - pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1); - } else if (c == 'J' || c == 'D') { - pop(2); - } else { - pop(1); - } - } - - /** - * Adds a new type to the list of types on which a constructor is invoked in - * the basic block. - * - * @param var - * a type on a which a constructor is invoked. - */ - private void init(final int var) { - // creates and/or resizes the initializations array if necessary - if (initializations == null) { - initializations = new int[2]; - } - int n = initializations.length; - if (initializationCount >= n) { - int[] t = new int[Math.max(initializationCount + 1, 2 * n)]; - System.arraycopy(initializations, 0, t, 0, n); - initializations = t; - } - // stores the type to be initialized - initializations[initializationCount++] = var; - } - - /** - * Replaces the given type with the appropriate type if it is one of the - * types on which a constructor is invoked in the basic block. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param t - * a type - * @return t or, if t is one of the types on which a constructor is invoked - * in the basic block, the type corresponding to this constructor. - */ - private int init(final ClassWriter cw, final int t) { - int s; - if (t == UNINITIALIZED_THIS) { - s = OBJECT | cw.addType(cw.thisName); - } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) { - String type = cw.typeTable[t & BASE_VALUE].strVal1; - s = OBJECT | cw.addType(type); - } else { - return t; - } - for (int j = 0; j < initializationCount; ++j) { - int u = initializations[j]; - int dim = u & DIM; - int kind = u & KIND; - if (kind == LOCAL) { - u = dim + inputLocals[u & VALUE]; - } else if (kind == STACK) { - u = dim + inputStack[inputStack.length - (u & VALUE)]; - } - if (t == u) { - return s; - } - } - return t; - } - - /** - * Initializes the input frame of the first basic block from the method - * descriptor. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param access - * the access flags of the method to which this label belongs. - * @param args - * the formal parameter types of this method. - * @param maxLocals - * the maximum number of local variables of this method. - */ - void initInputFrame(final ClassWriter cw, final int access, - final Type[] args, final int maxLocals) { - inputLocals = new int[maxLocals]; - inputStack = new int[0]; - int i = 0; - if ((access & Opcodes.ACC_STATIC) == 0) { - if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) { - inputLocals[i++] = OBJECT | cw.addType(cw.thisName); - } else { - inputLocals[i++] = UNINITIALIZED_THIS; - } - } - for (int j = 0; j < args.length; ++j) { - int t = type(cw, args[j].getDescriptor()); - inputLocals[i++] = t; - if (t == LONG || t == DOUBLE) { - inputLocals[i++] = TOP; - } - } - while (i < maxLocals) { - inputLocals[i++] = TOP; - } - } - - /** - * Simulates the action of the given instruction on the output stack frame. - * - * @param opcode - * the opcode of the instruction. - * @param arg - * the operand of the instruction, if any. - * @param cw - * the class writer to which this label belongs. - * @param item - * the operand of the instructions, if any. - */ - void execute(final int opcode, final int arg, final ClassWriter cw, - final Item item) { - int t1, t2, t3, t4; - switch (opcode) { - case Opcodes.NOP: - case Opcodes.INEG: - case Opcodes.LNEG: - case Opcodes.FNEG: - case Opcodes.DNEG: - case Opcodes.I2B: - case Opcodes.I2C: - case Opcodes.I2S: - case Opcodes.GOTO: - case Opcodes.RETURN: - break; - case Opcodes.ACONST_NULL: - push(NULL); - break; - case Opcodes.ICONST_M1: - case Opcodes.ICONST_0: - case Opcodes.ICONST_1: - case Opcodes.ICONST_2: - case Opcodes.ICONST_3: - case Opcodes.ICONST_4: - case Opcodes.ICONST_5: - case Opcodes.BIPUSH: - case Opcodes.SIPUSH: - case Opcodes.ILOAD: - push(INTEGER); - break; - case Opcodes.LCONST_0: - case Opcodes.LCONST_1: - case Opcodes.LLOAD: - push(LONG); - push(TOP); - break; - case Opcodes.FCONST_0: - case Opcodes.FCONST_1: - case Opcodes.FCONST_2: - case Opcodes.FLOAD: - push(FLOAT); - break; - case Opcodes.DCONST_0: - case Opcodes.DCONST_1: - case Opcodes.DLOAD: - push(DOUBLE); - push(TOP); - break; - case Opcodes.LDC: - switch (item.type) { - case ClassWriter.INT: - push(INTEGER); - break; - case ClassWriter.LONG: - push(LONG); - push(TOP); - break; - case ClassWriter.FLOAT: - push(FLOAT); - break; - case ClassWriter.DOUBLE: - push(DOUBLE); - push(TOP); - break; - case ClassWriter.CLASS: - push(OBJECT | cw.addType("java/lang/Class")); - break; - case ClassWriter.STR: - push(OBJECT | cw.addType("java/lang/String")); - break; - case ClassWriter.MTYPE: - push(OBJECT | cw.addType("java/lang/invoke/MethodType")); - break; - // case ClassWriter.HANDLE_BASE + [1..9]: - default: - push(OBJECT | cw.addType("java/lang/invoke/MethodHandle")); - } - break; - case Opcodes.ALOAD: - push(get(arg)); - break; - case Opcodes.IALOAD: - case Opcodes.BALOAD: - case Opcodes.CALOAD: - case Opcodes.SALOAD: - pop(2); - push(INTEGER); - break; - case Opcodes.LALOAD: - case Opcodes.D2L: - pop(2); - push(LONG); - push(TOP); - break; - case Opcodes.FALOAD: - pop(2); - push(FLOAT); - break; - case Opcodes.DALOAD: - case Opcodes.L2D: - pop(2); - push(DOUBLE); - push(TOP); - break; - case Opcodes.AALOAD: - pop(1); - t1 = pop(); - push(ELEMENT_OF + t1); - break; - case Opcodes.ISTORE: - case Opcodes.FSTORE: - case Opcodes.ASTORE: - t1 = pop(); - set(arg, t1); - if (arg > 0) { - t2 = get(arg - 1); - // if t2 is of kind STACK or LOCAL we cannot know its size! - if (t2 == LONG || t2 == DOUBLE) { - set(arg - 1, TOP); - } else if ((t2 & KIND) != BASE) { - set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); - } - } - break; - case Opcodes.LSTORE: - case Opcodes.DSTORE: - pop(1); - t1 = pop(); - set(arg, t1); - set(arg + 1, TOP); - if (arg > 0) { - t2 = get(arg - 1); - // if t2 is of kind STACK or LOCAL we cannot know its size! - if (t2 == LONG || t2 == DOUBLE) { - set(arg - 1, TOP); - } else if ((t2 & KIND) != BASE) { - set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); - } - } - break; - case Opcodes.IASTORE: - case Opcodes.BASTORE: - case Opcodes.CASTORE: - case Opcodes.SASTORE: - case Opcodes.FASTORE: - case Opcodes.AASTORE: - pop(3); - break; - case Opcodes.LASTORE: - case Opcodes.DASTORE: - pop(4); - break; - case Opcodes.POP: - case Opcodes.IFEQ: - case Opcodes.IFNE: - case Opcodes.IFLT: - case Opcodes.IFGE: - case Opcodes.IFGT: - case Opcodes.IFLE: - case Opcodes.IRETURN: - case Opcodes.FRETURN: - case Opcodes.ARETURN: - case Opcodes.TABLESWITCH: - case Opcodes.LOOKUPSWITCH: - case Opcodes.ATHROW: - case Opcodes.MONITORENTER: - case Opcodes.MONITOREXIT: - case Opcodes.IFNULL: - case Opcodes.IFNONNULL: - pop(1); - break; - case Opcodes.POP2: - case Opcodes.IF_ICMPEQ: - case Opcodes.IF_ICMPNE: - case Opcodes.IF_ICMPLT: - case Opcodes.IF_ICMPGE: - case Opcodes.IF_ICMPGT: - case Opcodes.IF_ICMPLE: - case Opcodes.IF_ACMPEQ: - case Opcodes.IF_ACMPNE: - case Opcodes.LRETURN: - case Opcodes.DRETURN: - pop(2); - break; - case Opcodes.DUP: - t1 = pop(); - push(t1); - push(t1); - break; - case Opcodes.DUP_X1: - t1 = pop(); - t2 = pop(); - push(t1); - push(t2); - push(t1); - break; - case Opcodes.DUP_X2: - t1 = pop(); - t2 = pop(); - t3 = pop(); - push(t1); - push(t3); - push(t2); - push(t1); - break; - case Opcodes.DUP2: - t1 = pop(); - t2 = pop(); - push(t2); - push(t1); - push(t2); - push(t1); - break; - case Opcodes.DUP2_X1: - t1 = pop(); - t2 = pop(); - t3 = pop(); - push(t2); - push(t1); - push(t3); - push(t2); - push(t1); - break; - case Opcodes.DUP2_X2: - t1 = pop(); - t2 = pop(); - t3 = pop(); - t4 = pop(); - push(t2); - push(t1); - push(t4); - push(t3); - push(t2); - push(t1); - break; - case Opcodes.SWAP: - t1 = pop(); - t2 = pop(); - push(t1); - push(t2); - break; - case Opcodes.IADD: - case Opcodes.ISUB: - case Opcodes.IMUL: - case Opcodes.IDIV: - case Opcodes.IREM: - case Opcodes.IAND: - case Opcodes.IOR: - case Opcodes.IXOR: - case Opcodes.ISHL: - case Opcodes.ISHR: - case Opcodes.IUSHR: - case Opcodes.L2I: - case Opcodes.D2I: - case Opcodes.FCMPL: - case Opcodes.FCMPG: - pop(2); - push(INTEGER); - break; - case Opcodes.LADD: - case Opcodes.LSUB: - case Opcodes.LMUL: - case Opcodes.LDIV: - case Opcodes.LREM: - case Opcodes.LAND: - case Opcodes.LOR: - case Opcodes.LXOR: - pop(4); - push(LONG); - push(TOP); - break; - case Opcodes.FADD: - case Opcodes.FSUB: - case Opcodes.FMUL: - case Opcodes.FDIV: - case Opcodes.FREM: - case Opcodes.L2F: - case Opcodes.D2F: - pop(2); - push(FLOAT); - break; - case Opcodes.DADD: - case Opcodes.DSUB: - case Opcodes.DMUL: - case Opcodes.DDIV: - case Opcodes.DREM: - pop(4); - push(DOUBLE); - push(TOP); - break; - case Opcodes.LSHL: - case Opcodes.LSHR: - case Opcodes.LUSHR: - pop(3); - push(LONG); - push(TOP); - break; - case Opcodes.IINC: - set(arg, INTEGER); - break; - case Opcodes.I2L: - case Opcodes.F2L: - pop(1); - push(LONG); - push(TOP); - break; - case Opcodes.I2F: - pop(1); - push(FLOAT); - break; - case Opcodes.I2D: - case Opcodes.F2D: - pop(1); - push(DOUBLE); - push(TOP); - break; - case Opcodes.F2I: - case Opcodes.ARRAYLENGTH: - case Opcodes.INSTANCEOF: - pop(1); - push(INTEGER); - break; - case Opcodes.LCMP: - case Opcodes.DCMPL: - case Opcodes.DCMPG: - pop(4); - push(INTEGER); - break; - case Opcodes.JSR: - case Opcodes.RET: - throw new RuntimeException( - "JSR/RET are not supported with computeFrames option"); - case Opcodes.GETSTATIC: - push(cw, item.strVal3); - break; - case Opcodes.PUTSTATIC: - pop(item.strVal3); - break; - case Opcodes.GETFIELD: - pop(1); - push(cw, item.strVal3); - break; - case Opcodes.PUTFIELD: - pop(item.strVal3); - pop(); - break; - case Opcodes.INVOKEVIRTUAL: - case Opcodes.INVOKESPECIAL: - case Opcodes.INVOKESTATIC: - case Opcodes.INVOKEINTERFACE: - pop(item.strVal3); - if (opcode != Opcodes.INVOKESTATIC) { - t1 = pop(); - if (opcode == Opcodes.INVOKESPECIAL - && item.strVal2.charAt(0) == '<') { - init(t1); - } - } - push(cw, item.strVal3); - break; - case Opcodes.INVOKEDYNAMIC: - pop(item.strVal2); - push(cw, item.strVal2); - break; - case Opcodes.NEW: - push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg)); - break; - case Opcodes.NEWARRAY: - pop(); - switch (arg) { - case Opcodes.T_BOOLEAN: - push(ARRAY_OF | BOOLEAN); - break; - case Opcodes.T_CHAR: - push(ARRAY_OF | CHAR); - break; - case Opcodes.T_BYTE: - push(ARRAY_OF | BYTE); - break; - case Opcodes.T_SHORT: - push(ARRAY_OF | SHORT); - break; - case Opcodes.T_INT: - push(ARRAY_OF | INTEGER); - break; - case Opcodes.T_FLOAT: - push(ARRAY_OF | FLOAT); - break; - case Opcodes.T_DOUBLE: - push(ARRAY_OF | DOUBLE); - break; - // case Opcodes.T_LONG: - default: - push(ARRAY_OF | LONG); - break; - } - break; - case Opcodes.ANEWARRAY: - String s = item.strVal1; - pop(); - if (s.charAt(0) == '[') { - push(cw, '[' + s); - } else { - push(ARRAY_OF | OBJECT | cw.addType(s)); - } - break; - case Opcodes.CHECKCAST: - s = item.strVal1; - pop(); - if (s.charAt(0) == '[') { - push(cw, s); - } else { - push(OBJECT | cw.addType(s)); - } - break; - // case Opcodes.MULTIANEWARRAY: - default: - pop(arg); - push(cw, item.strVal1); - break; - } - } - - /** - * Merges the input frame of the given basic block with the input and output - * frames of this basic block. Returns <tt>true</tt> if the input frame of - * the given label has been changed by this operation. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param frame - * the basic block whose input frame must be updated. - * @param edge - * the kind of the {@link Edge} between this label and 'label'. - * See {@link Edge#info}. - * @return <tt>true</tt> if the input frame of the given label has been - * changed by this operation. - */ - boolean merge(final ClassWriter cw, final Frame frame, final int edge) { - boolean changed = false; - int i, s, dim, kind, t; - - int nLocal = inputLocals.length; - int nStack = inputStack.length; - if (frame.inputLocals == null) { - frame.inputLocals = new int[nLocal]; - changed = true; - } - - for (i = 0; i < nLocal; ++i) { - if (outputLocals != null && i < outputLocals.length) { - s = outputLocals[i]; - if (s == 0) { - t = inputLocals[i]; - } else { - dim = s & DIM; - kind = s & KIND; - if (kind == BASE) { - t = s; - } else { - if (kind == LOCAL) { - t = dim + inputLocals[s & VALUE]; - } else { - t = dim + inputStack[nStack - (s & VALUE)]; - } - if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 - && (t == LONG || t == DOUBLE)) { - t = TOP; - } - } - } - } else { - t = inputLocals[i]; - } - if (initializations != null) { - t = init(cw, t); - } - changed |= merge(cw, t, frame.inputLocals, i); - } - - if (edge > 0) { - for (i = 0; i < nLocal; ++i) { - t = inputLocals[i]; - changed |= merge(cw, t, frame.inputLocals, i); - } - if (frame.inputStack == null) { - frame.inputStack = new int[1]; - changed = true; - } - changed |= merge(cw, edge, frame.inputStack, 0); - return changed; - } - - int nInputStack = inputStack.length + owner.inputStackTop; - if (frame.inputStack == null) { - frame.inputStack = new int[nInputStack + outputStackTop]; - changed = true; - } - - for (i = 0; i < nInputStack; ++i) { - t = inputStack[i]; - if (initializations != null) { - t = init(cw, t); - } - changed |= merge(cw, t, frame.inputStack, i); - } - for (i = 0; i < outputStackTop; ++i) { - s = outputStack[i]; - dim = s & DIM; - kind = s & KIND; - if (kind == BASE) { - t = s; - } else { - if (kind == LOCAL) { - t = dim + inputLocals[s & VALUE]; - } else { - t = dim + inputStack[nStack - (s & VALUE)]; - } - if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 - && (t == LONG || t == DOUBLE)) { - t = TOP; - } - } - if (initializations != null) { - t = init(cw, t); - } - changed |= merge(cw, t, frame.inputStack, nInputStack + i); - } - return changed; - } - - /** - * Merges the type at the given index in the given type array with the given - * type. Returns <tt>true</tt> if the type array has been modified by this - * operation. - * - * @param cw - * the ClassWriter to which this label belongs. - * @param t - * the type with which the type array element must be merged. - * @param types - * an array of types. - * @param index - * the index of the type that must be merged in 'types'. - * @return <tt>true</tt> if the type array has been modified by this - * operation. - */ - private static boolean merge(final ClassWriter cw, int t, - final int[] types, final int index) { - int u = types[index]; - if (u == t) { - // if the types are equal, merge(u,t)=u, so there is no change - return false; - } - if ((t & ~DIM) == NULL) { - if (u == NULL) { - return false; - } - t = NULL; - } - if (u == 0) { - // if types[index] has never been assigned, merge(u,t)=t - types[index] = t; - return true; - } - int v; - if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) { - // if u is a reference type of any dimension - if (t == NULL) { - // if t is the NULL type, merge(u,t)=u, so there is no change - return false; - } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) { - // if t and u have the same dimension and same base kind - if ((u & BASE_KIND) == OBJECT) { - // if t is also a reference type, and if u and t have the - // same dimension merge(u,t) = dim(t) | common parent of the - // element types of u and t - v = (t & DIM) | OBJECT - | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE); - } else { - // if u and t are array types, but not with the same element - // type, merge(u,t) = dim(u) - 1 | java/lang/Object - int vdim = ELEMENT_OF + (u & DIM); - v = vdim | OBJECT | cw.addType("java/lang/Object"); - } - } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) { - // if t is any other reference or array type, the merged type - // is min(udim, tdim) | java/lang/Object, where udim is the - // array dimension of u, minus 1 if u is an array type with a - // primitive element type (and similarly for tdim). - int tdim = (((t & DIM) == 0 || (t & BASE_KIND) == OBJECT) ? 0 - : ELEMENT_OF) + (t & DIM); - int udim = (((u & DIM) == 0 || (u & BASE_KIND) == OBJECT) ? 0 - : ELEMENT_OF) + (u & DIM); - v = Math.min(tdim, udim) | OBJECT - | cw.addType("java/lang/Object"); - } else { - // if t is any other type, merge(u,t)=TOP - v = TOP; - } - } else if (u == NULL) { - // if u is the NULL type, merge(u,t)=t, - // or TOP if t is not a reference type - v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP; - } else { - // if u is any other type, merge(u,t)=TOP whatever t - v = TOP; - } - if (u != v) { - types[index] = v; - return true; - } - return false; - } -} diff --git a/src/asm/scala/tools/asm/Handle.java b/src/asm/scala/tools/asm/Handle.java deleted file mode 100644 index cf12bb7613..0000000000 --- a/src/asm/scala/tools/asm/Handle.java +++ /dev/null @@ -1,170 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package scala.tools.asm; - -/** - * A reference to a field or a method. - * - * @author Remi Forax - * @author Eric Bruneton - */ -public final class Handle { - - /** - * The kind of field or method designated by this Handle. Should be - * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, - * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, - * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - */ - final int tag; - - /** - * The internal name of the class that owns the field or method designated - * by this handle. - */ - final String owner; - - /** - * The name of the field or method designated by this handle. - */ - final String name; - - /** - * The descriptor of the field or method designated by this handle. - */ - final String desc; - - /** - * Constructs a new field or method handle. - * - * @param tag - * the kind of field or method designated by this Handle. Must be - * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, - * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, - * {@link Opcodes#H_INVOKEVIRTUAL}, - * {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - * @param owner - * the internal name of the class that owns the field or method - * designated by this handle. - * @param name - * the name of the field or method designated by this handle. - * @param desc - * the descriptor of the field or method designated by this - * handle. - */ - public Handle(int tag, String owner, String name, String desc) { - this.tag = tag; - this.owner = owner; - this.name = name; - this.desc = desc; - } - - /** - * Returns the kind of field or method designated by this handle. - * - * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, - * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, - * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, - * {@link Opcodes#H_INVOKESPECIAL}, - * {@link Opcodes#H_NEWINVOKESPECIAL} or - * {@link Opcodes#H_INVOKEINTERFACE}. - */ - public int getTag() { - return tag; - } - - /** - * Returns the internal name of the class that owns the field or method - * designated by this handle. - * - * @return the internal name of the class that owns the field or method - * designated by this handle. - */ - public String getOwner() { - return owner; - } - - /** - * Returns the name of the field or method designated by this handle. - * - * @return the name of the field or method designated by this handle. - */ - public String getName() { - return name; - } - - /** - * Returns the descriptor of the field or method designated by this handle. - * - * @return the descriptor of the field or method designated by this handle. - */ - public String getDesc() { - return desc; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof Handle)) { - return false; - } - Handle h = (Handle) obj; - return tag == h.tag && owner.equals(h.owner) && name.equals(h.name) - && desc.equals(h.desc); - } - - @Override - public int hashCode() { - return tag + owner.hashCode() * name.hashCode() * desc.hashCode(); - } - - /** - * Returns the textual representation of this handle. The textual - * representation is: - * - * <pre> - * owner '.' name desc ' ' '(' tag ')' - * </pre> - * - * . As this format is unambiguous, it can be parsed if necessary. - */ - @Override - public String toString() { - return owner + '.' + name + desc + " (" + tag + ')'; - } -} diff --git a/src/asm/scala/tools/asm/Handler.java b/src/asm/scala/tools/asm/Handler.java deleted file mode 100644 index a06cb8152a..0000000000 --- a/src/asm/scala/tools/asm/Handler.java +++ /dev/null @@ -1,121 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * Information about an exception handler block. - * - * @author Eric Bruneton - */ -class Handler { - - /** - * Beginning of the exception handler's scope (inclusive). - */ - Label start; - - /** - * End of the exception handler's scope (exclusive). - */ - Label end; - - /** - * Beginning of the exception handler's code. - */ - Label handler; - - /** - * Internal name of the type of exceptions handled by this handler, or - * <tt>null</tt> to catch any exceptions. - */ - String desc; - - /** - * Constant pool index of the internal name of the type of exceptions - * handled by this handler, or 0 to catch any exceptions. - */ - int type; - - /** - * Next exception handler block info. - */ - Handler next; - - /** - * Removes the range between start and end from the given exception - * handlers. - * - * @param h - * an exception handler list. - * @param start - * the start of the range to be removed. - * @param end - * the end of the range to be removed. Maybe null. - * @return the exception handler list with the start-end range removed. - */ - static Handler remove(Handler h, Label start, Label end) { - if (h == null) { - return null; - } else { - h.next = remove(h.next, start, end); - } - int hstart = h.start.position; - int hend = h.end.position; - int s = start.position; - int e = end == null ? Integer.MAX_VALUE : end.position; - // if [hstart,hend[ and [s,e[ intervals intersect... - if (s < hend && e > hstart) { - if (s <= hstart) { - if (e >= hend) { - // [hstart,hend[ fully included in [s,e[, h removed - h = h.next; - } else { - // [hstart,hend[ minus [s,e[ = [e,hend[ - h.start = end; - } - } else if (e >= hend) { - // [hstart,hend[ minus [s,e[ = [hstart,s[ - h.end = start; - } else { - // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[ - Handler g = new Handler(); - g.start = end; - g.end = h.end; - g.handler = h.handler; - g.desc = h.desc; - g.type = h.type; - g.next = h.next; - h.end = start; - h.next = g; - } - } - return h; - } -} diff --git a/src/asm/scala/tools/asm/Item.java b/src/asm/scala/tools/asm/Item.java deleted file mode 100644 index 4693f5ae99..0000000000 --- a/src/asm/scala/tools/asm/Item.java +++ /dev/null @@ -1,312 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * A constant pool item. Constant pool items can be created with the 'newXXX' - * methods in the {@link ClassWriter} class. - * - * @author Eric Bruneton - */ -final class Item { - - /** - * Index of this item in the constant pool. - */ - int index; - - /** - * Type of this constant pool item. A single class is used to represent all - * constant pool item types, in order to minimize the bytecode size of this - * package. The value of this field is one of {@link ClassWriter#INT}, - * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT}, - * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8}, - * {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, - * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD}, - * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, - * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}. - * - * MethodHandle constant 9 variations are stored using a range of 9 values - * from {@link ClassWriter#HANDLE_BASE} + 1 to - * {@link ClassWriter#HANDLE_BASE} + 9. - * - * Special Item types are used for Items that are stored in the ClassWriter - * {@link ClassWriter#typeTable}, instead of the constant pool, in order to - * avoid clashes with normal constant pool items in the ClassWriter constant - * pool's hash table. These special item types are - * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and - * {@link ClassWriter#TYPE_MERGED}. - */ - int type; - - /** - * Value of this item, for an integer item. - */ - int intVal; - - /** - * Value of this item, for a long item. - */ - long longVal; - - /** - * First part of the value of this item, for items that do not hold a - * primitive value. - */ - String strVal1; - - /** - * Second part of the value of this item, for items that do not hold a - * primitive value. - */ - String strVal2; - - /** - * Third part of the value of this item, for items that do not hold a - * primitive value. - */ - String strVal3; - - /** - * The hash code value of this constant pool item. - */ - int hashCode; - - /** - * Link to another constant pool item, used for collision lists in the - * constant pool's hash table. - */ - Item next; - - /** - * Constructs an uninitialized {@link Item}. - */ - Item() { - } - - /** - * Constructs an uninitialized {@link Item} for constant pool element at - * given position. - * - * @param index - * index of the item to be constructed. - */ - Item(final int index) { - this.index = index; - } - - /** - * Constructs a copy of the given item. - * - * @param index - * index of the item to be constructed. - * @param i - * the item that must be copied into the item to be constructed. - */ - Item(final int index, final Item i) { - this.index = index; - type = i.type; - intVal = i.intVal; - longVal = i.longVal; - strVal1 = i.strVal1; - strVal2 = i.strVal2; - strVal3 = i.strVal3; - hashCode = i.hashCode; - } - - /** - * Sets this item to an integer item. - * - * @param intVal - * the value of this item. - */ - void set(final int intVal) { - this.type = ClassWriter.INT; - this.intVal = intVal; - this.hashCode = 0x7FFFFFFF & (type + intVal); - } - - /** - * Sets this item to a long item. - * - * @param longVal - * the value of this item. - */ - void set(final long longVal) { - this.type = ClassWriter.LONG; - this.longVal = longVal; - this.hashCode = 0x7FFFFFFF & (type + (int) longVal); - } - - /** - * Sets this item to a float item. - * - * @param floatVal - * the value of this item. - */ - void set(final float floatVal) { - this.type = ClassWriter.FLOAT; - this.intVal = Float.floatToRawIntBits(floatVal); - this.hashCode = 0x7FFFFFFF & (type + (int) floatVal); - } - - /** - * Sets this item to a double item. - * - * @param doubleVal - * the value of this item. - */ - void set(final double doubleVal) { - this.type = ClassWriter.DOUBLE; - this.longVal = Double.doubleToRawLongBits(doubleVal); - this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal); - } - - /** - * Sets this item to an item that do not hold a primitive value. - * - * @param type - * the type of this item. - * @param strVal1 - * first part of the value of this item. - * @param strVal2 - * second part of the value of this item. - * @param strVal3 - * third part of the value of this item. - */ - void set(final int type, final String strVal1, final String strVal2, - final String strVal3) { - this.type = type; - this.strVal1 = strVal1; - this.strVal2 = strVal2; - this.strVal3 = strVal3; - switch (type) { - case ClassWriter.CLASS: - this.intVal = 0; // intVal of a class must be zero, see visitInnerClass - case ClassWriter.UTF8: - case ClassWriter.STR: - case ClassWriter.MTYPE: - case ClassWriter.TYPE_NORMAL: - hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); - return; - case ClassWriter.NAME_TYPE: { - hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() - * strVal2.hashCode()); - return; - } - // ClassWriter.FIELD: - // ClassWriter.METH: - // ClassWriter.IMETH: - // ClassWriter.HANDLE_BASE + 1..9 - default: - hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() - * strVal2.hashCode() * strVal3.hashCode()); - } - } - - /** - * Sets the item to an InvokeDynamic item. - * - * @param name - * invokedynamic's name. - * @param desc - * invokedynamic's desc. - * @param bsmIndex - * zero based index into the class attribute BootrapMethods. - */ - void set(String name, String desc, int bsmIndex) { - this.type = ClassWriter.INDY; - this.longVal = bsmIndex; - this.strVal1 = name; - this.strVal2 = desc; - this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex - * strVal1.hashCode() * strVal2.hashCode()); - } - - /** - * Sets the item to a BootstrapMethod item. - * - * @param position - * position in byte in the class attribute BootrapMethods. - * @param hashCode - * hashcode of the item. This hashcode is processed from the - * hashcode of the bootstrap method and the hashcode of all - * bootstrap arguments. - */ - void set(int position, int hashCode) { - this.type = ClassWriter.BSM; - this.intVal = position; - this.hashCode = hashCode; - } - - /** - * Indicates if the given item is equal to this one. <i>This method assumes - * that the two items have the same {@link #type}</i>. - * - * @param i - * the item to be compared to this one. Both items must have the - * same {@link #type}. - * @return <tt>true</tt> if the given item if equal to this one, - * <tt>false</tt> otherwise. - */ - boolean isEqualTo(final Item i) { - switch (type) { - case ClassWriter.UTF8: - case ClassWriter.STR: - case ClassWriter.CLASS: - case ClassWriter.MTYPE: - case ClassWriter.TYPE_NORMAL: - return i.strVal1.equals(strVal1); - case ClassWriter.TYPE_MERGED: - case ClassWriter.LONG: - case ClassWriter.DOUBLE: - return i.longVal == longVal; - case ClassWriter.INT: - case ClassWriter.FLOAT: - return i.intVal == intVal; - case ClassWriter.TYPE_UNINIT: - return i.intVal == intVal && i.strVal1.equals(strVal1); - case ClassWriter.NAME_TYPE: - return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2); - case ClassWriter.INDY: { - return i.longVal == longVal && i.strVal1.equals(strVal1) - && i.strVal2.equals(strVal2); - } - // case ClassWriter.FIELD: - // case ClassWriter.METH: - // case ClassWriter.IMETH: - // case ClassWriter.HANDLE_BASE + 1..9 - default: - return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2) - && i.strVal3.equals(strVal3); - } - } - -} diff --git a/src/asm/scala/tools/asm/Label.java b/src/asm/scala/tools/asm/Label.java deleted file mode 100644 index 22b6798fb5..0000000000 --- a/src/asm/scala/tools/asm/Label.java +++ /dev/null @@ -1,560 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * A label represents a position in the bytecode of a method. Labels are used - * for jump, goto, and switch instructions, and for try catch blocks. A label - * designates the <i>instruction</i> that is just after. Note however that there - * can be other elements between a label and the instruction it designates (such - * as other labels, stack map frames, line numbers, etc.). - * - * @author Eric Bruneton - */ -public class Label { - - /** - * Indicates if this label is only used for debug attributes. Such a label - * is not the start of a basic block, the target of a jump instruction, or - * an exception handler. It can be safely ignored in control flow graph - * analysis algorithms (for optimization purposes). - */ - static final int DEBUG = 1; - - /** - * Indicates if the position of this label is known. - */ - static final int RESOLVED = 2; - - /** - * Indicates if this label has been updated, after instruction resizing. - */ - static final int RESIZED = 4; - - /** - * Indicates if this basic block has been pushed in the basic block stack. - * See {@link MethodWriter#visitMaxs visitMaxs}. - */ - static final int PUSHED = 8; - - /** - * Indicates if this label is the target of a jump instruction, or the start - * of an exception handler. - */ - static final int TARGET = 16; - - /** - * Indicates if a stack map frame must be stored for this label. - */ - static final int STORE = 32; - - /** - * Indicates if this label corresponds to a reachable basic block. - */ - static final int REACHABLE = 64; - - /** - * Indicates if this basic block ends with a JSR instruction. - */ - static final int JSR = 128; - - /** - * Indicates if this basic block ends with a RET instruction. - */ - static final int RET = 256; - - /** - * Indicates if this basic block is the start of a subroutine. - */ - static final int SUBROUTINE = 512; - - /** - * Indicates if this subroutine basic block has been visited by a - * visitSubroutine(null, ...) call. - */ - static final int VISITED = 1024; - - /** - * Indicates if this subroutine basic block has been visited by a - * visitSubroutine(!null, ...) call. - */ - static final int VISITED2 = 2048; - - /** - * Field used to associate user information to a label. Warning: this field - * is used by the ASM tree package. In order to use it with the ASM tree - * package you must override the - * {@link scala.tools.asm.tree.MethodNode#getLabelNode} method. - */ - public Object info; - - /** - * Flags that indicate the status of this label. - * - * @see #DEBUG - * @see #RESOLVED - * @see #RESIZED - * @see #PUSHED - * @see #TARGET - * @see #STORE - * @see #REACHABLE - * @see #JSR - * @see #RET - */ - int status; - - /** - * The line number corresponding to this label, if known. - */ - int line; - - /** - * The position of this label in the code, if known. - */ - int position; - - /** - * Number of forward references to this label, times two. - */ - private int referenceCount; - - /** - * Informations about forward references. Each forward reference is - * described by two consecutive integers in this array: the first one is the - * position of the first byte of the bytecode instruction that contains the - * forward reference, while the second is the position of the first byte of - * the forward reference itself. In fact the sign of the first integer - * indicates if this reference uses 2 or 4 bytes, and its absolute value - * gives the position of the bytecode instruction. This array is also used - * as a bitset to store the subroutines to which a basic block belongs. This - * information is needed in {@linked MethodWriter#visitMaxs}, after all - * forward references have been resolved. Hence the same array can be used - * for both purposes without problems. - */ - private int[] srcAndRefPositions; - - // ------------------------------------------------------------------------ - - /* - * Fields for the control flow and data flow graph analysis algorithms (used - * to compute the maximum stack size or the stack map frames). A control - * flow graph contains one node per "basic block", and one edge per "jump" - * from one basic block to another. Each node (i.e., each basic block) is - * represented by the Label object that corresponds to the first instruction - * of this basic block. Each node also stores the list of its successors in - * the graph, as a linked list of Edge objects. - * - * The control flow analysis algorithms used to compute the maximum stack - * size or the stack map frames are similar and use two steps. The first - * step, during the visit of each instruction, builds information about the - * state of the local variables and the operand stack at the end of each - * basic block, called the "output frame", <i>relatively</i> to the frame - * state at the beginning of the basic block, which is called the "input - * frame", and which is <i>unknown</i> during this step. The second step, in - * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes - * information about the input frame of each basic block, from the input - * state of the first basic block (known from the method signature), and by - * the using the previously computed relative output frames. - * - * The algorithm used to compute the maximum stack size only computes the - * relative output and absolute input stack heights, while the algorithm - * used to compute stack map frames computes relative output frames and - * absolute input frames. - */ - - /** - * Start of the output stack relatively to the input stack. The exact - * semantics of this field depends on the algorithm that is used. - * - * When only the maximum stack size is computed, this field is the number of - * elements in the input stack. - * - * When the stack map frames are completely computed, this field is the - * offset of the first output stack element relatively to the top of the - * input stack. This offset is always negative or null. A null offset means - * that the output stack must be appended to the input stack. A -n offset - * means that the first n output stack elements must replace the top n input - * stack elements, and that the other elements must be appended to the input - * stack. - */ - int inputStackTop; - - /** - * Maximum height reached by the output stack, relatively to the top of the - * input stack. This maximum is always positive or null. - */ - int outputStackMax; - - /** - * Information about the input and output stack map frames of this basic - * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES} - * option is used. - */ - Frame frame; - - /** - * The successor of this label, in the order they are visited. This linked - * list does not include labels used for debug info only. If - * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it - * does not contain successive labels that denote the same bytecode position - * (in this case only the first label appears in this list). - */ - Label successor; - - /** - * The successors of this node in the control flow graph. These successors - * are stored in a linked list of {@link Edge Edge} objects, linked to each - * other by their {@link Edge#next} field. - */ - Edge successors; - - /** - * The next basic block in the basic block stack. This stack is used in the - * main loop of the fix point algorithm used in the second step of the - * control flow analysis algorithms. It is also used in - * {@link #visitSubroutine} to avoid using a recursive method. - * - * @see MethodWriter#visitMaxs - */ - Label next; - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new label. - */ - public Label() { - } - - // ------------------------------------------------------------------------ - // Methods to compute offsets and to manage forward references - // ------------------------------------------------------------------------ - - /** - * Returns the offset corresponding to this label. This offset is computed - * from the start of the method's bytecode. <i>This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters.</i> - * - * @return the offset corresponding to this label. - * @throws IllegalStateException - * if this label is not resolved yet. - */ - public int getOffset() { - if ((status & RESOLVED) == 0) { - throw new IllegalStateException( - "Label offset position has not been resolved yet"); - } - return position; - } - - /** - * Puts a reference to this label in the bytecode of a method. If the - * position of the label is known, the offset is computed and written - * directly. Otherwise, a null offset is written and a new forward reference - * is declared for this label. - * - * @param owner - * the code writer that calls this method. - * @param out - * the bytecode of the method. - * @param source - * the position of first byte of the bytecode instruction that - * contains this label. - * @param wideOffset - * <tt>true</tt> if the reference must be stored in 4 bytes, or - * <tt>false</tt> if it must be stored with 2 bytes. - * @throws IllegalArgumentException - * if this label has not been created by the given code writer. - */ - void put(final MethodWriter owner, final ByteVector out, final int source, - final boolean wideOffset) { - if ((status & RESOLVED) == 0) { - if (wideOffset) { - addReference(-1 - source, out.length); - out.putInt(-1); - } else { - addReference(source, out.length); - out.putShort(-1); - } - } else { - if (wideOffset) { - out.putInt(position - source); - } else { - out.putShort(position - source); - } - } - } - - /** - * Adds a forward reference to this label. This method must be called only - * for a true forward reference, i.e. only if this label is not resolved - * yet. For backward references, the offset of the reference can be, and - * must be, computed and stored directly. - * - * @param sourcePosition - * the position of the referencing instruction. This position - * will be used to compute the offset of this forward reference. - * @param referencePosition - * the position where the offset for this forward reference must - * be stored. - */ - private void addReference(final int sourcePosition, - final int referencePosition) { - if (srcAndRefPositions == null) { - srcAndRefPositions = new int[6]; - } - if (referenceCount >= srcAndRefPositions.length) { - int[] a = new int[srcAndRefPositions.length + 6]; - System.arraycopy(srcAndRefPositions, 0, a, 0, - srcAndRefPositions.length); - srcAndRefPositions = a; - } - srcAndRefPositions[referenceCount++] = sourcePosition; - srcAndRefPositions[referenceCount++] = referencePosition; - } - - /** - * Resolves all forward references to this label. This method must be called - * when this label is added to the bytecode of the method, i.e. when its - * position becomes known. This method fills in the blanks that where left - * in the bytecode by each forward reference previously added to this label. - * - * @param owner - * the code writer that calls this method. - * @param position - * the position of this label in the bytecode. - * @param data - * the bytecode of the method. - * @return <tt>true</tt> if a blank that was left for this label was to - * small to store the offset. In such a case the corresponding jump - * instruction is replaced with a pseudo instruction (using unused - * opcodes) using an unsigned two bytes offset. These pseudo - * instructions will need to be replaced with true instructions with - * wider offsets (4 bytes instead of 2). This is done in - * {@link MethodWriter#resizeInstructions}. - * @throws IllegalArgumentException - * if this label has already been resolved, or if it has not - * been created by the given code writer. - */ - boolean resolve(final MethodWriter owner, final int position, - final byte[] data) { - boolean needUpdate = false; - this.status |= RESOLVED; - this.position = position; - int i = 0; - while (i < referenceCount) { - int source = srcAndRefPositions[i++]; - int reference = srcAndRefPositions[i++]; - int offset; - if (source >= 0) { - offset = position - source; - if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) { - /* - * changes the opcode of the jump instruction, in order to - * be able to find it later (see resizeInstructions in - * MethodWriter). These temporary opcodes are similar to - * jump instruction opcodes, except that the 2 bytes offset - * is unsigned (and can therefore represent values from 0 to - * 65535, which is sufficient since the size of a method is - * limited to 65535 bytes). - */ - int opcode = data[reference - 1] & 0xFF; - if (opcode <= Opcodes.JSR) { - // changes IFEQ ... JSR to opcodes 202 to 217 - data[reference - 1] = (byte) (opcode + 49); - } else { - // changes IFNULL and IFNONNULL to opcodes 218 and 219 - data[reference - 1] = (byte) (opcode + 20); - } - needUpdate = true; - } - data[reference++] = (byte) (offset >>> 8); - data[reference] = (byte) offset; - } else { - offset = position + source + 1; - data[reference++] = (byte) (offset >>> 24); - data[reference++] = (byte) (offset >>> 16); - data[reference++] = (byte) (offset >>> 8); - data[reference] = (byte) offset; - } - } - return needUpdate; - } - - /** - * Returns the first label of the series to which this label belongs. For an - * isolated label or for the first label in a series of successive labels, - * this method returns the label itself. For other labels it returns the - * first label of the series. - * - * @return the first label of the series to which this label belongs. - */ - Label getFirst() { - return !ClassReader.FRAMES || frame == null ? this : frame.owner; - } - - // ------------------------------------------------------------------------ - // Methods related to subroutines - // ------------------------------------------------------------------------ - - /** - * Returns true is this basic block belongs to the given subroutine. - * - * @param id - * a subroutine id. - * @return true is this basic block belongs to the given subroutine. - */ - boolean inSubroutine(final long id) { - if ((status & Label.VISITED) != 0) { - return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0; - } - return false; - } - - /** - * Returns true if this basic block and the given one belong to a common - * subroutine. - * - * @param block - * another basic block. - * @return true if this basic block and the given one belong to a common - * subroutine. - */ - boolean inSameSubroutine(final Label block) { - if ((status & VISITED) == 0 || (block.status & VISITED) == 0) { - return false; - } - for (int i = 0; i < srcAndRefPositions.length; ++i) { - if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) { - return true; - } - } - return false; - } - - /** - * Marks this basic block as belonging to the given subroutine. - * - * @param id - * a subroutine id. - * @param nbSubroutines - * the total number of subroutines in the method. - */ - void addToSubroutine(final long id, final int nbSubroutines) { - if ((status & VISITED) == 0) { - status |= VISITED; - srcAndRefPositions = new int[nbSubroutines / 32 + 1]; - } - srcAndRefPositions[(int) (id >>> 32)] |= (int) id; - } - - /** - * Finds the basic blocks that belong to a given subroutine, and marks these - * blocks as belonging to this subroutine. This method follows the control - * flow graph to find all the blocks that are reachable from the current - * block WITHOUT following any JSR target. - * - * @param JSR - * a JSR block that jumps to this subroutine. If this JSR is not - * null it is added to the successor of the RET blocks found in - * the subroutine. - * @param id - * the id of this subroutine. - * @param nbSubroutines - * the total number of subroutines in the method. - */ - void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) { - // user managed stack of labels, to avoid using a recursive method - // (recursivity can lead to stack overflow with very large methods) - Label stack = this; - while (stack != null) { - // removes a label l from the stack - Label l = stack; - stack = l.next; - l.next = null; - - if (JSR != null) { - if ((l.status & VISITED2) != 0) { - continue; - } - l.status |= VISITED2; - // adds JSR to the successors of l, if it is a RET block - if ((l.status & RET) != 0) { - if (!l.inSameSubroutine(JSR)) { - Edge e = new Edge(); - e.info = l.inputStackTop; - e.successor = JSR.successors.successor; - e.next = l.successors; - l.successors = e; - } - } - } else { - // if the l block already belongs to subroutine 'id', continue - if (l.inSubroutine(id)) { - continue; - } - // marks the l block as belonging to subroutine 'id' - l.addToSubroutine(id, nbSubroutines); - } - // pushes each successor of l on the stack, except JSR targets - Edge e = l.successors; - while (e != null) { - // if the l block is a JSR block, then 'l.successors.next' leads - // to the JSR target (see {@link #visitJumpInsn}) and must - // therefore not be followed - if ((l.status & Label.JSR) == 0 || e != l.successors.next) { - // pushes e.successor on the stack if it not already added - if (e.successor.next == null) { - e.successor.next = stack; - stack = e.successor; - } - } - e = e.next; - } - } - } - - // ------------------------------------------------------------------------ - // Overridden Object methods - // ------------------------------------------------------------------------ - - /** - * Returns a string representation of this label. - * - * @return a string representation of this label. - */ - @Override - public String toString() { - return "L" + System.identityHashCode(this); - } -} diff --git a/src/asm/scala/tools/asm/MethodVisitor.java b/src/asm/scala/tools/asm/MethodVisitor.java deleted file mode 100644 index bddc325020..0000000000 --- a/src/asm/scala/tools/asm/MethodVisitor.java +++ /dev/null @@ -1,880 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * A visitor to visit a Java method. The methods of this class must be called in - * the following order: ( <tt>visitParameter</tt> )* [ - * <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> | - * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* [ - * <tt>visitCode</tt> ( <tt>visitFrame</tt> | <tt>visit<i>X</i>Insn</tt> | - * <tt>visitLabel</tt> | <tt>visitInsnAnnotation</tt> | - * <tt>visitTryCatchBlock</tt> | <tt>visitTryCatchBlockAnnotation</tt> | - * <tt>visitLocalVariable</tt> | <tt>visitLocalVariableAnnotation</tt> | - * <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In - * addition, the <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt> methods must - * be called in the sequential order of the bytecode instructions of the visited - * code, <tt>visitInsnAnnotation</tt> must be called <i>after</i> the annotated - * instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the - * labels passed as arguments have been visited, - * <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the - * corresponding try catch block has been visited, and the - * <tt>visitLocalVariable</tt>, <tt>visitLocalVariableAnnotation</tt> and - * <tt>visitLineNumber</tt> methods must be called <i>after</i> the labels - * passed as arguments have been visited. - * - * @author Eric Bruneton - */ -public abstract class MethodVisitor { - - /** - * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected final int api; - - /** - * The method visitor to which this visitor must delegate method calls. May - * be null. - */ - protected MethodVisitor mv; - - /** - * Constructs a new {@link MethodVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public MethodVisitor(final int api) { - this(api, null); - } - - /** - * Constructs a new {@link MethodVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param mv - * the method visitor to which this visitor must delegate method - * calls. May be null. - */ - public MethodVisitor(final int api, final MethodVisitor mv) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { - throw new IllegalArgumentException(); - } - this.api = api; - this.mv = mv; - } - - // ------------------------------------------------------------------------- - // Parameters, annotations and non standard attributes - // ------------------------------------------------------------------------- - - /** - * Visits a parameter of this method. - * - * @param name - * parameter name or null if none is provided. - * @param access - * the parameter's access flags, only <tt>ACC_FINAL</tt>, - * <tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are - * allowed (see {@link Opcodes}). - */ - public void visitParameter(String name, int access) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (mv != null) { - mv.visitParameter(name, access); - } - } - - /** - * Visits the default value of this annotation interface method. - * - * @return a visitor to the visit the actual default value of this - * annotation interface method, or <tt>null</tt> if this visitor is - * not interested in visiting this default value. The 'name' - * parameters passed to the methods of this annotation visitor are - * ignored. Moreover, exacly one visit method must be called on this - * annotation visitor, followed by visitEnd. - */ - public AnnotationVisitor visitAnnotationDefault() { - if (mv != null) { - return mv.visitAnnotationDefault(); - } - return null; - } - - /** - * Visits an annotation of this method. - * - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or <tt>null</tt> if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - if (mv != null) { - return mv.visitAnnotation(desc, visible); - } - return null; - } - - /** - * Visits an annotation on a type in the method signature. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#METHOD_TYPE_PARAMETER - * METHOD_TYPE_PARAMETER}, - * {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND - * METHOD_TYPE_PARAMETER_BOUND}, - * {@link TypeReference#METHOD_RETURN METHOD_RETURN}, - * {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER}, - * {@link TypeReference#METHOD_FORMAL_PARAMETER - * METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS - * THROWS}. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or <tt>null</tt> if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (mv != null) { - return mv.visitTypeAnnotation(typeRef, typePath, desc, visible); - } - return null; - } - - /** - * Visits an annotation of a parameter this method. - * - * @param parameter - * the parameter index. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or <tt>null</tt> if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitParameterAnnotation(int parameter, - String desc, boolean visible) { - if (mv != null) { - return mv.visitParameterAnnotation(parameter, desc, visible); - } - return null; - } - - /** - * Visits a non standard attribute of this method. - * - * @param attr - * an attribute. - */ - public void visitAttribute(Attribute attr) { - if (mv != null) { - mv.visitAttribute(attr); - } - } - - /** - * Starts the visit of the method's code, if any (i.e. non abstract method). - */ - public void visitCode() { - if (mv != null) { - mv.visitCode(); - } - } - - /** - * Visits the current state of the local variables and operand stack - * elements. This method must(*) be called <i>just before</i> any - * instruction <b>i</b> that follows an unconditional branch instruction - * such as GOTO or THROW, that is the target of a jump instruction, or that - * starts an exception handler block. The visited types must describe the - * values of the local variables and of the operand stack elements <i>just - * before</i> <b>i</b> is executed.<br> - * <br> - * (*) this is mandatory only for classes whose version is greater than or - * equal to {@link Opcodes#V1_6 V1_6}. <br> - * <br> - * The frames of a method must be given either in expanded form, or in - * compressed form (all frames must use the same format, i.e. you must not - * mix expanded and compressed frames within a single method): - * <ul> - * <li>In expanded form, all frames must have the F_NEW type.</li> - * <li>In compressed form, frames are basically "deltas" from the state of - * the previous frame: - * <ul> - * <li>{@link Opcodes#F_SAME} representing frame with exactly the same - * locals as the previous frame and with the empty stack.</li> - * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same - * locals as the previous frame and with single value on the stack ( - * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the - * type of the stack item).</li> - * <li>{@link Opcodes#F_APPEND} representing frame with current locals are - * the same as the locals in the previous frame, except that additional - * locals are defined (<code>nLocal</code> is 1, 2 or 3 and - * <code>local</code> elements contains values representing added types).</li> - * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the - * same as the locals in the previous frame, except that the last 1-3 locals - * are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li> - * <li>{@link Opcodes#F_FULL} representing complete frame data.</li> - * </ul> - * </li> - * </ul> - * <br> - * In both cases the first frame, corresponding to the method's parameters - * and access flags, is implicit and must not be visited. Also, it is - * illegal to visit two or more frames for the same code location (i.e., at - * least one instruction must be visited between two calls to visitFrame). - * - * @param type - * the type of this stack map frame. Must be - * {@link Opcodes#F_NEW} for expanded frames, or - * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, - * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or - * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for - * compressed frames. - * @param nLocal - * the number of local variables in the visited frame. - * @param local - * the local variable types in this frame. This array must not be - * modified. Primitive types are represented by - * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, - * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, - * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or - * {@link Opcodes#UNINITIALIZED_THIS} (long and double are - * represented by a single element). Reference types are - * represented by String objects (representing internal names), - * and uninitialized types by Label objects (this label - * designates the NEW instruction that created this uninitialized - * value). - * @param nStack - * the number of operand stack elements in the visited frame. - * @param stack - * the operand stack types in this frame. This array must not be - * modified. Its content has the same format as the "local" - * array. - * @throws IllegalStateException - * if a frame is visited just after another one, without any - * instruction between the two (unless this frame is a - * Opcodes#F_SAME frame, in which case it is silently ignored). - */ - public void visitFrame(int type, int nLocal, Object[] local, int nStack, - Object[] stack) { - if (mv != null) { - mv.visitFrame(type, nLocal, local, nStack, stack); - } - } - - // ------------------------------------------------------------------------- - // Normal instructions - // ------------------------------------------------------------------------- - - /** - * Visits a zero operand instruction. - * - * @param opcode - * the opcode of the instruction to be visited. This opcode is - * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, - * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, - * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, - * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, - * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, - * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, - * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, - * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, - * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, - * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, - * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, - * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, - * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, - * or MONITOREXIT. - */ - public void visitInsn(int opcode) { - if (mv != null) { - mv.visitInsn(opcode); - } - } - - /** - * Visits an instruction with a single int operand. - * - * @param opcode - * the opcode of the instruction to be visited. This opcode is - * either BIPUSH, SIPUSH or NEWARRAY. - * @param operand - * the operand of the instruction to be visited.<br> - * When opcode is BIPUSH, operand value should be between - * Byte.MIN_VALUE and Byte.MAX_VALUE.<br> - * When opcode is SIPUSH, operand value should be between - * Short.MIN_VALUE and Short.MAX_VALUE.<br> - * When opcode is NEWARRAY, operand value should be one of - * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, - * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, - * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, - * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. - */ - public void visitIntInsn(int opcode, int operand) { - if (mv != null) { - mv.visitIntInsn(opcode, operand); - } - } - - /** - * Visits a local variable instruction. A local variable instruction is an - * instruction that loads or stores the value of a local variable. - * - * @param opcode - * the opcode of the local variable instruction to be visited. - * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, - * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. - * @param var - * the operand of the instruction to be visited. This operand is - * the index of a local variable. - */ - public void visitVarInsn(int opcode, int var) { - if (mv != null) { - mv.visitVarInsn(opcode, var); - } - } - - /** - * Visits a type instruction. A type instruction is an instruction that - * takes the internal name of a class as parameter. - * - * @param opcode - * the opcode of the type instruction to be visited. This opcode - * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. - * @param type - * the operand of the instruction to be visited. This operand - * must be the internal name of an object or array class (see - * {@link Type#getInternalName() getInternalName}). - */ - public void visitTypeInsn(int opcode, String type) { - if (mv != null) { - mv.visitTypeInsn(opcode, type); - } - } - - /** - * Visits a field instruction. A field instruction is an instruction that - * loads or stores the value of a field of an object. - * - * @param opcode - * the opcode of the type instruction to be visited. This opcode - * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. - * @param owner - * the internal name of the field's owner class (see - * {@link Type#getInternalName() getInternalName}). - * @param name - * the field's name. - * @param desc - * the field's descriptor (see {@link Type Type}). - */ - public void visitFieldInsn(int opcode, String owner, String name, - String desc) { - if (mv != null) { - mv.visitFieldInsn(opcode, owner, name, desc); - } - } - - /** - * Visits a method instruction. A method instruction is an instruction that - * invokes a method. - * - * @param opcode - * the opcode of the type instruction to be visited. This opcode - * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or - * INVOKEINTERFACE. - * @param owner - * the internal name of the method's owner class (see - * {@link Type#getInternalName() getInternalName}). - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type Type}). - */ - @Deprecated - public void visitMethodInsn(int opcode, String owner, String name, - String desc) { - if (api >= Opcodes.ASM5) { - boolean itf = opcode == Opcodes.INVOKEINTERFACE; - visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc); - } - } - - /** - * Visits a method instruction. A method instruction is an instruction that - * invokes a method. - * - * @param opcode - * the opcode of the type instruction to be visited. This opcode - * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or - * INVOKEINTERFACE. - * @param owner - * the internal name of the method's owner class (see - * {@link Type#getInternalName() getInternalName}). - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type Type}). - * @param itf - * if the method's owner class is an interface. - */ - public void visitMethodInsn(int opcode, String owner, String name, - String desc, boolean itf) { - if (api < Opcodes.ASM5) { - if (itf != (opcode == Opcodes.INVOKEINTERFACE)) { - throw new IllegalArgumentException( - "INVOKESPECIAL/STATIC on interfaces require ASM 5"); - } - visitMethodInsn(opcode, owner, name, desc); - return; - } - if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc, itf); - } - } - - /** - * Visits an invokedynamic instruction. - * - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type Type}). - * @param bsm - * the bootstrap method. - * @param bsmArgs - * the bootstrap method constant arguments. Each argument must be - * an {@link Integer}, {@link Float}, {@link Long}, - * {@link Double}, {@link String}, {@link Type} or {@link Handle} - * value. This method is allowed to modify the content of the - * array so a caller should expect that this array may change. - */ - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, - Object... bsmArgs) { - if (mv != null) { - mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); - } - } - - /** - * Visits a jump instruction. A jump instruction is an instruction that may - * jump to another instruction. - * - * @param opcode - * the opcode of the type instruction to be visited. This opcode - * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, - * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, - * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. - * @param label - * the operand of the instruction to be visited. This operand is - * a label that designates the instruction to which the jump - * instruction may jump. - */ - public void visitJumpInsn(int opcode, Label label) { - if (mv != null) { - mv.visitJumpInsn(opcode, label); - } - } - - /** - * Visits a label. A label designates the instruction that will be visited - * just after it. - * - * @param label - * a {@link Label Label} object. - */ - public void visitLabel(Label label) { - if (mv != null) { - mv.visitLabel(label); - } - } - - // ------------------------------------------------------------------------- - // Special instructions - // ------------------------------------------------------------------------- - - /** - * Visits a LDC instruction. Note that new constant types may be added in - * future versions of the Java Virtual Machine. To easily detect new - * constant types, implementations of this method should check for - * unexpected constant types, like this: - * - * <pre> - * if (cst instanceof Integer) { - * // ... - * } else if (cst instanceof Float) { - * // ... - * } else if (cst instanceof Long) { - * // ... - * } else if (cst instanceof Double) { - * // ... - * } else if (cst instanceof String) { - * // ... - * } else if (cst instanceof Type) { - * int sort = ((Type) cst).getSort(); - * if (sort == Type.OBJECT) { - * // ... - * } else if (sort == Type.ARRAY) { - * // ... - * } else if (sort == Type.METHOD) { - * // ... - * } else { - * // throw an exception - * } - * } else if (cst instanceof Handle) { - * // ... - * } else { - * // throw an exception - * } - * </pre> - * - * @param cst - * the constant to be loaded on the stack. This parameter must be - * a non null {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double}, a {@link String}, a {@link Type} of OBJECT or - * ARRAY sort for <tt>.class</tt> constants, for classes whose - * version is 49.0, a {@link Type} of METHOD sort or a - * {@link Handle} for MethodType and MethodHandle constants, for - * classes whose version is 51.0. - */ - public void visitLdcInsn(Object cst) { - if (mv != null) { - mv.visitLdcInsn(cst); - } - } - - /** - * Visits an IINC instruction. - * - * @param var - * index of the local variable to be incremented. - * @param increment - * amount to increment the local variable by. - */ - public void visitIincInsn(int var, int increment) { - if (mv != null) { - mv.visitIincInsn(var, increment); - } - } - - /** - * Visits a TABLESWITCH instruction. - * - * @param min - * the minimum key value. - * @param max - * the maximum key value. - * @param dflt - * beginning of the default handler block. - * @param labels - * beginnings of the handler blocks. <tt>labels[i]</tt> is the - * beginning of the handler block for the <tt>min + i</tt> key. - */ - public void visitTableSwitchInsn(int min, int max, Label dflt, - Label... labels) { - if (mv != null) { - mv.visitTableSwitchInsn(min, max, dflt, labels); - } - } - - /** - * Visits a LOOKUPSWITCH instruction. - * - * @param dflt - * beginning of the default handler block. - * @param keys - * the values of the keys. - * @param labels - * beginnings of the handler blocks. <tt>labels[i]</tt> is the - * beginning of the handler block for the <tt>keys[i]</tt> key. - */ - public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { - if (mv != null) { - mv.visitLookupSwitchInsn(dflt, keys, labels); - } - } - - /** - * Visits a MULTIANEWARRAY instruction. - * - * @param desc - * an array type descriptor (see {@link Type Type}). - * @param dims - * number of dimensions of the array to allocate. - */ - public void visitMultiANewArrayInsn(String desc, int dims) { - if (mv != null) { - mv.visitMultiANewArrayInsn(desc, dims); - } - } - - /** - * Visits an annotation on an instruction. This method must be called just - * <i>after</i> the annotated instruction. It can be called several times - * for the same instruction. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#INSTANCEOF INSTANCEOF}, - * {@link TypeReference#NEW NEW}, - * {@link TypeReference#CONSTRUCTOR_REFERENCE - * CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE - * METHOD_REFERENCE}, {@link TypeReference#CAST CAST}, - * {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT - * METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT - * METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or <tt>null</tt> if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitInsnAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (mv != null) { - return mv.visitInsnAnnotation(typeRef, typePath, desc, visible); - } - return null; - } - - // ------------------------------------------------------------------------- - // Exceptions table entries, debug information, max stack and max locals - // ------------------------------------------------------------------------- - - /** - * Visits a try catch block. - * - * @param start - * beginning of the exception handler's scope (inclusive). - * @param end - * end of the exception handler's scope (exclusive). - * @param handler - * beginning of the exception handler's code. - * @param type - * internal name of the type of exceptions handled by the - * handler, or <tt>null</tt> to catch any exceptions (for - * "finally" blocks). - * @throws IllegalArgumentException - * if one of the labels has already been visited by this visitor - * (by the {@link #visitLabel visitLabel} method). - */ - public void visitTryCatchBlock(Label start, Label end, Label handler, - String type) { - if (mv != null) { - mv.visitTryCatchBlock(start, end, handler, type); - } - } - - /** - * Visits an annotation on an exception handler type. This method must be - * called <i>after</i> the {@link #visitTryCatchBlock} for the annotated - * exception handler. It can be called several times for the same exception - * handler. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#EXCEPTION_PARAMETER - * EXCEPTION_PARAMETER}. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or <tt>null</tt> if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitTryCatchAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (mv != null) { - return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible); - } - return null; - } - - /** - * Visits a local variable declaration. - * - * @param name - * the name of a local variable. - * @param desc - * the type descriptor of this local variable. - * @param signature - * the type signature of this local variable. May be - * <tt>null</tt> if the local variable type does not use generic - * types. - * @param start - * the first instruction corresponding to the scope of this local - * variable (inclusive). - * @param end - * the last instruction corresponding to the scope of this local - * variable (exclusive). - * @param index - * the local variable's index. - * @throws IllegalArgumentException - * if one of the labels has not already been visited by this - * visitor (by the {@link #visitLabel visitLabel} method). - */ - public void visitLocalVariable(String name, String desc, String signature, - Label start, Label end, int index) { - if (mv != null) { - mv.visitLocalVariable(name, desc, signature, start, end, index); - } - } - - /** - * Visits an annotation on a local variable type. - * - * @param typeRef - * a reference to the annotated type. The sort of this type - * reference must be {@link TypeReference#LOCAL_VARIABLE - * LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE - * RESOURCE_VARIABLE}. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param start - * the fist instructions corresponding to the continuous ranges - * that make the scope of this local variable (inclusive). - * @param end - * the last instructions corresponding to the continuous ranges - * that make the scope of this local variable (exclusive). This - * array must have the same size as the 'start' array. - * @param index - * the local variable's index in each range. This array must have - * the same size as the 'start' array. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values, or <tt>null</tt> if - * this visitor is not interested in visiting this annotation. - */ - public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, - TypePath typePath, Label[] start, Label[] end, int[] index, - String desc, boolean visible) { - if (api < Opcodes.ASM5) { - throw new RuntimeException(); - } - if (mv != null) { - return mv.visitLocalVariableAnnotation(typeRef, typePath, start, - end, index, desc, visible); - } - return null; - } - - /** - * Visits a line number declaration. - * - * @param line - * a line number. This number refers to the source file from - * which the class was compiled. - * @param start - * the first instruction corresponding to this line number. - * @throws IllegalArgumentException - * if <tt>start</tt> has not already been visited by this - * visitor (by the {@link #visitLabel visitLabel} method). - */ - public void visitLineNumber(int line, Label start) { - if (mv != null) { - mv.visitLineNumber(line, start); - } - } - - /** - * Visits the maximum stack size and the maximum number of local variables - * of the method. - * - * @param maxStack - * maximum stack size of the method. - * @param maxLocals - * maximum number of local variables for the method. - */ - public void visitMaxs(int maxStack, int maxLocals) { - if (mv != null) { - mv.visitMaxs(maxStack, maxLocals); - } - } - - /** - * Visits the end of the method. This method, which is the last one to be - * called, is used to inform the visitor that all the annotations and - * attributes of the method have been visited. - */ - public void visitEnd() { - if (mv != null) { - mv.visitEnd(); - } - } -} diff --git a/src/asm/scala/tools/asm/MethodWriter.java b/src/asm/scala/tools/asm/MethodWriter.java deleted file mode 100644 index 9c72ead61d..0000000000 --- a/src/asm/scala/tools/asm/MethodWriter.java +++ /dev/null @@ -1,2924 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * A {@link MethodVisitor} that generates methods in bytecode form. Each visit - * method of this class appends the bytecode corresponding to the visited - * instruction to a byte vector, in the order these methods are called. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public class MethodWriter extends MethodVisitor { - - /** - * Pseudo access flag used to denote constructors. - */ - static final int ACC_CONSTRUCTOR = 0x80000; - - /** - * Frame has exactly the same locals as the previous stack map frame and - * number of stack items is zero. - */ - static final int SAME_FRAME = 0; // to 63 (0-3f) - - /** - * Frame has exactly the same locals as the previous stack map frame and - * number of stack items is 1 - */ - static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f) - - /** - * Reserved for future use - */ - static final int RESERVED = 128; - - /** - * Frame has exactly the same locals as the previous stack map frame and - * number of stack items is 1. Offset is bigger then 63; - */ - static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7 - - /** - * Frame where current locals are the same as the locals in the previous - * frame, except that the k last locals are absent. The value of k is given - * by the formula 251-frame_type. - */ - static final int CHOP_FRAME = 248; // to 250 (f8-fA) - - /** - * Frame has exactly the same locals as the previous stack map frame and - * number of stack items is zero. Offset is bigger then 63; - */ - static final int SAME_FRAME_EXTENDED = 251; // fb - - /** - * Frame where current locals are the same as the locals in the previous - * frame, except that k additional locals are defined. The value of k is - * given by the formula frame_type-251. - */ - static final int APPEND_FRAME = 252; // to 254 // fc-fe - - /** - * Full frame - */ - static final int FULL_FRAME = 255; // ff - - /** - * Indicates that the stack map frames must be recomputed from scratch. In - * this case the maximum stack size and number of local variables is also - * recomputed from scratch. - * - * @see #compute - */ - private static final int FRAMES = 0; - - /** - * Indicates that the maximum stack size and number of local variables must - * be automatically computed. - * - * @see #compute - */ - private static final int MAXS = 1; - - /** - * Indicates that nothing must be automatically computed. - * - * @see #compute - */ - private static final int NOTHING = 2; - - /** - * The class writer to which this method must be added. - */ - final ClassWriter cw; - - /** - * Access flags of this method. - */ - private int access; - - /** - * The index of the constant pool item that contains the name of this - * method. - */ - private final int name; - - /** - * The index of the constant pool item that contains the descriptor of this - * method. - */ - private final int desc; - - /** - * The descriptor of this method. - */ - private final String descriptor; - - /** - * The signature of this method. - */ - String signature; - - /** - * If not zero, indicates that the code of this method must be copied from - * the ClassReader associated to this writer in <code>cw.cr</code>. More - * precisely, this field gives the index of the first byte to copied from - * <code>cw.cr.b</code>. - */ - int classReaderOffset; - - /** - * If not zero, indicates that the code of this method must be copied from - * the ClassReader associated to this writer in <code>cw.cr</code>. More - * precisely, this field gives the number of bytes to copied from - * <code>cw.cr.b</code>. - */ - int classReaderLength; - - /** - * Number of exceptions that can be thrown by this method. - */ - int exceptionCount; - - /** - * The exceptions that can be thrown by this method. More precisely, this - * array contains the indexes of the constant pool items that contain the - * internal names of these exception classes. - */ - int[] exceptions; - - /** - * The annotation default attribute of this method. May be <tt>null</tt>. - */ - private ByteVector annd; - - /** - * The runtime visible annotations of this method. May be <tt>null</tt>. - */ - private AnnotationWriter anns; - - /** - * The runtime invisible annotations of this method. May be <tt>null</tt>. - */ - private AnnotationWriter ianns; - - /** - * The runtime visible type annotations of this method. May be <tt>null</tt> - * . - */ - private AnnotationWriter tanns; - - /** - * The runtime invisible type annotations of this method. May be - * <tt>null</tt>. - */ - private AnnotationWriter itanns; - - /** - * The runtime visible parameter annotations of this method. May be - * <tt>null</tt>. - */ - private AnnotationWriter[] panns; - - /** - * The runtime invisible parameter annotations of this method. May be - * <tt>null</tt>. - */ - private AnnotationWriter[] ipanns; - - /** - * The number of synthetic parameters of this method. - */ - private int synthetics; - - /** - * The non standard attributes of the method. - */ - private Attribute attrs; - - /** - * The bytecode of this method. - */ - private ByteVector code = new ByteVector(); - - /** - * Maximum stack size of this method. - */ - private int maxStack; - - public int getMaxStack() { - return maxStack; - } - - /** - * Maximum number of local variables for this method. - */ - private int maxLocals; - - public int getMaxLocals() { - return maxLocals; - } - - /** - * Number of local variables in the current stack map frame. - */ - private int currentLocals; - - /** - * Number of stack map frames in the StackMapTable attribute. - */ - private int frameCount; - - /** - * The StackMapTable attribute. - */ - private ByteVector stackMap; - - /** - * The offset of the last frame that was written in the StackMapTable - * attribute. - */ - private int previousFrameOffset; - - /** - * The last frame that was written in the StackMapTable attribute. - * - * @see #frame - */ - private int[] previousFrame; - - /** - * The current stack map frame. The first element contains the offset of the - * instruction to which the frame corresponds, the second element is the - * number of locals and the third one is the number of stack elements. The - * local variables start at index 3 and are followed by the operand stack - * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] = - * nStack, frame[3] = nLocal. All types are encoded as integers, with the - * same format as the one used in {@link Label}, but limited to BASE types. - */ - private int[] frame; - - /** - * Number of elements in the exception handler list. - */ - private int handlerCount; - - /** - * The first element in the exception handler list. - */ - private Handler firstHandler; - - /** - * The last element in the exception handler list. - */ - private Handler lastHandler; - - /** - * Number of entries in the MethodParameters attribute. - */ - private int methodParametersCount; - - /** - * The MethodParameters attribute. - */ - private ByteVector methodParameters; - - /** - * Number of entries in the LocalVariableTable attribute. - */ - private int localVarCount; - - /** - * The LocalVariableTable attribute. - */ - private ByteVector localVar; - - /** - * Number of entries in the LocalVariableTypeTable attribute. - */ - private int localVarTypeCount; - - /** - * The LocalVariableTypeTable attribute. - */ - private ByteVector localVarType; - - /** - * Number of entries in the LineNumberTable attribute. - */ - private int lineNumberCount; - - /** - * The LineNumberTable attribute. - */ - private ByteVector lineNumber; - - /** - * The start offset of the last visited instruction. - */ - private int lastCodeOffset; - - /** - * The runtime visible type annotations of the code. May be <tt>null</tt>. - */ - private AnnotationWriter ctanns; - - /** - * The runtime invisible type annotations of the code. May be <tt>null</tt>. - */ - private AnnotationWriter ictanns; - - /** - * The non standard attributes of the method's code. - */ - private Attribute cattrs; - - /** - * Indicates if some jump instructions are too small and need to be resized. - */ - private boolean resize; - - /** - * The number of subroutines in this method. - */ - private int subroutines; - - // ------------------------------------------------------------------------ - - /* - * Fields for the control flow graph analysis algorithm (used to compute the - * maximum stack size). A control flow graph contains one node per "basic - * block", and one edge per "jump" from one basic block to another. Each - * node (i.e., each basic block) is represented by the Label object that - * corresponds to the first instruction of this basic block. Each node also - * stores the list of its successors in the graph, as a linked list of Edge - * objects. - */ - - /** - * Indicates what must be automatically computed. - * - * @see #FRAMES - * @see #MAXS - * @see #NOTHING - */ - private final int compute; - - /** - * A list of labels. This list is the list of basic blocks in the method, - * i.e. a list of Label objects linked to each other by their - * {@link Label#successor} field, in the order they are visited by - * {@link MethodVisitor#visitLabel}, and starting with the first basic - * block. - */ - private Label labels; - - /** - * The previous basic block. - */ - private Label previousBlock; - - /** - * The current basic block. - */ - private Label currentBlock; - - /** - * The (relative) stack size after the last visited instruction. This size - * is relative to the beginning of the current basic block, i.e., the true - * stack size after the last visited instruction is equal to the - * {@link Label#inputStackTop beginStackSize} of the current basic block - * plus <tt>stackSize</tt>. - */ - private int stackSize; - - /** - * The (relative) maximum stack size after the last visited instruction. - * This size is relative to the beginning of the current basic block, i.e., - * the true maximum stack size after the last visited instruction is equal - * to the {@link Label#inputStackTop beginStackSize} of the current basic - * block plus <tt>stackSize</tt>. - */ - private int maxStackSize; - - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link MethodWriter}. - * - * @param cw - * the class writer in which the method must be added. - * @param access - * the method's access flags (see {@link Opcodes}). - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type}). - * @param signature - * the method's signature. May be <tt>null</tt>. - * @param exceptions - * the internal names of the method's exceptions. May be - * <tt>null</tt>. - * @param computeMaxs - * <tt>true</tt> if the maximum stack size and number of local - * variables must be automatically computed. - * @param computeFrames - * <tt>true</tt> if the stack map tables must be recomputed from - * scratch. - */ - MethodWriter(final ClassWriter cw, final int access, final String name, - final String desc, final String signature, - final String[] exceptions, final boolean computeMaxs, - final boolean computeFrames) { - super(Opcodes.ASM5); - if (cw.firstMethod == null) { - cw.firstMethod = this; - } else { - cw.lastMethod.mv = this; - } - cw.lastMethod = this; - this.cw = cw; - this.access = access; - if ("<init>".equals(name)) { - this.access |= ACC_CONSTRUCTOR; - } - this.name = cw.newUTF8(name); - this.desc = cw.newUTF8(desc); - this.descriptor = desc; - if (ClassReader.SIGNATURES) { - this.signature = signature; - } - if (exceptions != null && exceptions.length > 0) { - exceptionCount = exceptions.length; - this.exceptions = new int[exceptionCount]; - for (int i = 0; i < exceptionCount; ++i) { - this.exceptions[i] = cw.newClass(exceptions[i]); - } - } - this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING); - if (computeMaxs || computeFrames) { - // updates maxLocals - int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2; - if ((access & Opcodes.ACC_STATIC) != 0) { - --size; - } - maxLocals = size; - currentLocals = size; - // creates and visits the label for the first basic block - labels = new Label(); - labels.status |= Label.PUSHED; - visitLabel(labels); - } - } - - // ------------------------------------------------------------------------ - // Implementation of the MethodVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public void visitParameter(String name, int access) { - if (methodParameters == null) { - methodParameters = new ByteVector(); - } - ++methodParametersCount; - methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name)) - .putShort(access); - } - - @Override - public AnnotationVisitor visitAnnotationDefault() { - if (!ClassReader.ANNOTATIONS) { - return null; - } - annd = new ByteVector(); - return new AnnotationWriter(cw, false, annd, null, 0); - } - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); - if (visible) { - aw.next = anns; - anns = aw; - } else { - aw.next = ianns; - ianns = aw; - } - return aw; - } - - @Override - public AnnotationVisitor visitTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - AnnotationWriter.putTarget(typeRef, typePath, bv); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = tanns; - tanns = aw; - } else { - aw.next = itanns; - itanns = aw; - } - return aw; - } - - @Override - public AnnotationVisitor visitParameterAnnotation(final int parameter, - final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - if ("Ljava/lang/Synthetic;".equals(desc)) { - // workaround for a bug in javac with synthetic parameters - // see ClassReader.readParameterAnnotations - synthetics = Math.max(synthetics, parameter + 1); - return new AnnotationWriter(cw, false, bv, null, 0); - } - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); - if (visible) { - if (panns == null) { - panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; - } - aw.next = panns[parameter]; - panns[parameter] = aw; - } else { - if (ipanns == null) { - ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; - } - aw.next = ipanns[parameter]; - ipanns[parameter] = aw; - } - return aw; - } - - @Override - public void visitAttribute(final Attribute attr) { - if (attr.isCodeAttribute()) { - attr.next = cattrs; - cattrs = attr; - } else { - attr.next = attrs; - attrs = attr; - } - } - - @Override - public void visitCode() { - } - - @Override - public void visitFrame(final int type, final int nLocal, - final Object[] local, final int nStack, final Object[] stack) { - if (!ClassReader.FRAMES || compute == FRAMES) { - return; - } - - if (type == Opcodes.F_NEW) { - if (previousFrame == null) { - visitImplicitFirstFrame(); - } - currentLocals = nLocal; - int frameIndex = startFrame(code.length, nLocal, nStack); - for (int i = 0; i < nLocal; ++i) { - if (local[i] instanceof String) { - frame[frameIndex++] = Frame.OBJECT - | cw.addType((String) local[i]); - } else if (local[i] instanceof Integer) { - frame[frameIndex++] = ((Integer) local[i]).intValue(); - } else { - frame[frameIndex++] = Frame.UNINITIALIZED - | cw.addUninitializedType("", - ((Label) local[i]).position); - } - } - for (int i = 0; i < nStack; ++i) { - if (stack[i] instanceof String) { - frame[frameIndex++] = Frame.OBJECT - | cw.addType((String) stack[i]); - } else if (stack[i] instanceof Integer) { - frame[frameIndex++] = ((Integer) stack[i]).intValue(); - } else { - frame[frameIndex++] = Frame.UNINITIALIZED - | cw.addUninitializedType("", - ((Label) stack[i]).position); - } - } - endFrame(); - } else { - int delta; - if (stackMap == null) { - stackMap = new ByteVector(); - delta = code.length; - } else { - delta = code.length - previousFrameOffset - 1; - if (delta < 0) { - if (type == Opcodes.F_SAME) { - return; - } else { - throw new IllegalStateException(); - } - } - } - - switch (type) { - case Opcodes.F_FULL: - currentLocals = nLocal; - stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal); - for (int i = 0; i < nLocal; ++i) { - writeFrameType(local[i]); - } - stackMap.putShort(nStack); - for (int i = 0; i < nStack; ++i) { - writeFrameType(stack[i]); - } - break; - case Opcodes.F_APPEND: - currentLocals += nLocal; - stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta); - for (int i = 0; i < nLocal; ++i) { - writeFrameType(local[i]); - } - break; - case Opcodes.F_CHOP: - currentLocals -= nLocal; - stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta); - break; - case Opcodes.F_SAME: - if (delta < 64) { - stackMap.putByte(delta); - } else { - stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); - } - break; - case Opcodes.F_SAME1: - if (delta < 64) { - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); - } else { - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) - .putShort(delta); - } - writeFrameType(stack[0]); - break; - } - - previousFrameOffset = code.length; - ++frameCount; - } - - maxStack = Math.max(maxStack, nStack); - maxLocals = Math.max(maxLocals, currentLocals); - } - - @Override - public void visitInsn(final int opcode) { - lastCodeOffset = code.length; - // adds the instruction to the bytecode of the method - code.putByte(opcode); - // update currentBlock - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, 0, null, null); - } else { - // updates current and max stack sizes - int size = stackSize + Frame.SIZE[opcode]; - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - // if opcode == ATHROW or xRETURN, ends current block (no successor) - if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) - || opcode == Opcodes.ATHROW) { - noSuccessor(); - } - } - } - - @Override - public void visitIntInsn(final int opcode, final int operand) { - lastCodeOffset = code.length; - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, operand, null, null); - } else if (opcode != Opcodes.NEWARRAY) { - // updates current and max stack sizes only for NEWARRAY - // (stack size variation = 0 for BIPUSH or SIPUSH) - int size = stackSize + 1; - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - if (opcode == Opcodes.SIPUSH) { - code.put12(opcode, operand); - } else { // BIPUSH or NEWARRAY - code.put11(opcode, operand); - } - } - - @Override - public void visitVarInsn(final int opcode, final int var) { - lastCodeOffset = code.length; - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, var, null, null); - } else { - // updates current and max stack sizes - if (opcode == Opcodes.RET) { - // no stack change, but end of current block (no successor) - currentBlock.status |= Label.RET; - // save 'stackSize' here for future use - // (see {@link #findSubroutineSuccessors}) - currentBlock.inputStackTop = stackSize; - noSuccessor(); - } else { // xLOAD or xSTORE - int size = stackSize + Frame.SIZE[opcode]; - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - } - if (compute != NOTHING) { - // updates max locals - int n; - if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD - || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) { - n = var + 2; - } else { - n = var + 1; - } - if (n > maxLocals) { - maxLocals = n; - } - } - // adds the instruction to the bytecode of the method - if (var < 4 && opcode != Opcodes.RET) { - int opt; - if (opcode < Opcodes.ISTORE) { - /* ILOAD_0 */ - opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var; - } else { - /* ISTORE_0 */ - opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var; - } - code.putByte(opt); - } else if (var >= 256) { - code.putByte(196 /* WIDE */).put12(opcode, var); - } else { - code.put11(opcode, var); - } - if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) { - visitLabel(new Label()); - } - } - - @Override - public void visitTypeInsn(final int opcode, final String type) { - lastCodeOffset = code.length; - Item i = cw.newClassItem(type); - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, code.length, cw, i); - } else if (opcode == Opcodes.NEW) { - // updates current and max stack sizes only if opcode == NEW - // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF) - int size = stackSize + 1; - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - code.put12(opcode, i.index); - } - - @Override - public void visitFieldInsn(final int opcode, final String owner, - final String name, final String desc) { - lastCodeOffset = code.length; - Item i = cw.newFieldItem(owner, name, desc); - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, 0, cw, i); - } else { - int size; - // computes the stack size variation - char c = desc.charAt(0); - switch (opcode) { - case Opcodes.GETSTATIC: - size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); - break; - case Opcodes.PUTSTATIC: - size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); - break; - case Opcodes.GETFIELD: - size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); - break; - // case Constants.PUTFIELD: - default: - size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); - break; - } - // updates current and max stack sizes - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - code.put12(opcode, i.index); - } - - @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc, final boolean itf) { - lastCodeOffset = code.length; - Item i = cw.newMethodItem(owner, name, desc, itf); - int argSize = i.intVal; - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, 0, cw, i); - } else { - /* - * computes the stack size variation. In order not to recompute - * several times this variation for the same Item, we use the - * intVal field of this item to store this variation, once it - * has been computed. More precisely this intVal field stores - * the sizes of the arguments and of the return value - * corresponding to desc. - */ - if (argSize == 0) { - // the above sizes have not been computed yet, - // so we compute them... - argSize = Type.getArgumentsAndReturnSizes(desc); - // ... and we save them in order - // not to recompute them in the future - i.intVal = argSize; - } - int size; - if (opcode == Opcodes.INVOKESTATIC) { - size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; - } else { - size = stackSize - (argSize >> 2) + (argSize & 0x03); - } - // updates current and max stack sizes - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - if (opcode == Opcodes.INVOKEINTERFACE) { - if (argSize == 0) { - argSize = Type.getArgumentsAndReturnSizes(desc); - i.intVal = argSize; - } - code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); - } else { - code.put12(opcode, i.index); - } - } - - @Override - public void visitInvokeDynamicInsn(final String name, final String desc, - final Handle bsm, final Object... bsmArgs) { - lastCodeOffset = code.length; - Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs); - int argSize = i.intVal; - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i); - } else { - /* - * computes the stack size variation. In order not to recompute - * several times this variation for the same Item, we use the - * intVal field of this item to store this variation, once it - * has been computed. More precisely this intVal field stores - * the sizes of the arguments and of the return value - * corresponding to desc. - */ - if (argSize == 0) { - // the above sizes have not been computed yet, - // so we compute them... - argSize = Type.getArgumentsAndReturnSizes(desc); - // ... and we save them in order - // not to recompute them in the future - i.intVal = argSize; - } - int size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; - - // updates current and max stack sizes - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - code.put12(Opcodes.INVOKEDYNAMIC, i.index); - code.putShort(0); - } - - @Override - public void visitJumpInsn(final int opcode, final Label label) { - lastCodeOffset = code.length; - Label nextInsn = null; - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(opcode, 0, null, null); - // 'label' is the target of a jump instruction - label.getFirst().status |= Label.TARGET; - // adds 'label' as a successor of this basic block - addSuccessor(Edge.NORMAL, label); - if (opcode != Opcodes.GOTO) { - // creates a Label for the next basic block - nextInsn = new Label(); - } - } else { - if (opcode == Opcodes.JSR) { - if ((label.status & Label.SUBROUTINE) == 0) { - label.status |= Label.SUBROUTINE; - ++subroutines; - } - currentBlock.status |= Label.JSR; - addSuccessor(stackSize + 1, label); - // creates a Label for the next basic block - nextInsn = new Label(); - /* - * note that, by construction in this method, a JSR block - * has at least two successors in the control flow graph: - * the first one leads the next instruction after the JSR, - * while the second one leads to the JSR target. - */ - } else { - // updates current stack size (max stack size unchanged - // because stack size variation always negative in this - // case) - stackSize += Frame.SIZE[opcode]; - addSuccessor(stackSize, label); - } - } - } - // adds the instruction to the bytecode of the method - if ((label.status & Label.RESOLVED) != 0 - && label.position - code.length < Short.MIN_VALUE) { - /* - * case of a backward jump with an offset < -32768. In this case we - * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx - * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the - * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'> - * designates the instruction just after the GOTO_W. - */ - if (opcode == Opcodes.GOTO) { - code.putByte(200); // GOTO_W - } else if (opcode == Opcodes.JSR) { - code.putByte(201); // JSR_W - } else { - // if the IF instruction is transformed into IFNOT GOTO_W the - // next instruction becomes the target of the IFNOT instruction - if (nextInsn != null) { - nextInsn.status |= Label.TARGET; - } - code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 - : opcode ^ 1); - code.putShort(8); // jump offset - code.putByte(200); // GOTO_W - } - label.put(this, code, code.length - 1, true); - } else { - /* - * case of a backward jump with an offset >= -32768, or of a forward - * jump with, of course, an unknown offset. In these cases we store - * the offset in 2 bytes (which will be increased in - * resizeInstructions, if needed). - */ - code.putByte(opcode); - label.put(this, code, code.length - 1, false); - } - if (currentBlock != null) { - if (nextInsn != null) { - // if the jump instruction is not a GOTO, the next instruction - // is also a successor of this instruction. Calling visitLabel - // adds the label of this next instruction as a successor of the - // current block, and starts a new basic block - visitLabel(nextInsn); - } - if (opcode == Opcodes.GOTO) { - noSuccessor(); - } - } - } - - @Override - public void visitLabel(final Label label) { - // resolves previous forward references to label, if any - resize |= label.resolve(this, code.length, code.data); - // updates currentBlock - if ((label.status & Label.DEBUG) != 0) { - return; - } - if (compute == FRAMES) { - if (currentBlock != null) { - if (label.position == currentBlock.position) { - // successive labels, do not start a new basic block - currentBlock.status |= (label.status & Label.TARGET); - label.frame = currentBlock.frame; - return; - } - // ends current block (with one new successor) - addSuccessor(Edge.NORMAL, label); - } - // begins a new current block - currentBlock = label; - if (label.frame == null) { - label.frame = new Frame(); - label.frame.owner = label; - } - // updates the basic block list - if (previousBlock != null) { - if (label.position == previousBlock.position) { - previousBlock.status |= (label.status & Label.TARGET); - label.frame = previousBlock.frame; - currentBlock = previousBlock; - return; - } - previousBlock.successor = label; - } - previousBlock = label; - } else if (compute == MAXS) { - if (currentBlock != null) { - // ends current block (with one new successor) - currentBlock.outputStackMax = maxStackSize; - addSuccessor(stackSize, label); - } - // begins a new current block - currentBlock = label; - // resets the relative current and max stack sizes - stackSize = 0; - maxStackSize = 0; - // updates the basic block list - if (previousBlock != null) { - previousBlock.successor = label; - } - previousBlock = label; - } - } - - @Override - public void visitLdcInsn(final Object cst) { - lastCodeOffset = code.length; - Item i = cw.newConstItem(cst); - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(Opcodes.LDC, 0, cw, i); - } else { - int size; - // computes the stack size variation - if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { - size = stackSize + 2; - } else { - size = stackSize + 1; - } - // updates current and max stack sizes - if (size > maxStackSize) { - maxStackSize = size; - } - stackSize = size; - } - } - // adds the instruction to the bytecode of the method - int index = i.index; - if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { - code.put12(20 /* LDC2_W */, index); - } else if (index >= 256) { - code.put12(19 /* LDC_W */, index); - } else { - code.put11(Opcodes.LDC, index); - } - } - - @Override - public void visitIincInsn(final int var, final int increment) { - lastCodeOffset = code.length; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(Opcodes.IINC, var, null, null); - } - } - if (compute != NOTHING) { - // updates max locals - int n = var + 1; - if (n > maxLocals) { - maxLocals = n; - } - } - // adds the instruction to the bytecode of the method - if ((var > 255) || (increment > 127) || (increment < -128)) { - code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var) - .putShort(increment); - } else { - code.putByte(Opcodes.IINC).put11(var, increment); - } - } - - @Override - public void visitTableSwitchInsn(final int min, final int max, - final Label dflt, final Label... labels) { - lastCodeOffset = code.length; - // adds the instruction to the bytecode of the method - int source = code.length; - code.putByte(Opcodes.TABLESWITCH); - code.putByteArray(null, 0, (4 - code.length % 4) % 4); - dflt.put(this, code, source, true); - code.putInt(min).putInt(max); - for (int i = 0; i < labels.length; ++i) { - labels[i].put(this, code, source, true); - } - // updates currentBlock - visitSwitchInsn(dflt, labels); - } - - @Override - public void visitLookupSwitchInsn(final Label dflt, final int[] keys, - final Label[] labels) { - lastCodeOffset = code.length; - // adds the instruction to the bytecode of the method - int source = code.length; - code.putByte(Opcodes.LOOKUPSWITCH); - code.putByteArray(null, 0, (4 - code.length % 4) % 4); - dflt.put(this, code, source, true); - code.putInt(labels.length); - for (int i = 0; i < labels.length; ++i) { - code.putInt(keys[i]); - labels[i].put(this, code, source, true); - } - // updates currentBlock - visitSwitchInsn(dflt, labels); - } - - private void visitSwitchInsn(final Label dflt, final Label[] labels) { - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null); - // adds current block successors - addSuccessor(Edge.NORMAL, dflt); - dflt.getFirst().status |= Label.TARGET; - for (int i = 0; i < labels.length; ++i) { - addSuccessor(Edge.NORMAL, labels[i]); - labels[i].getFirst().status |= Label.TARGET; - } - } else { - // updates current stack size (max stack size unchanged) - --stackSize; - // adds current block successors - addSuccessor(stackSize, dflt); - for (int i = 0; i < labels.length; ++i) { - addSuccessor(stackSize, labels[i]); - } - } - // ends current block - noSuccessor(); - } - } - - @Override - public void visitMultiANewArrayInsn(final String desc, final int dims) { - lastCodeOffset = code.length; - Item i = cw.newClassItem(desc); - // Label currentBlock = this.currentBlock; - if (currentBlock != null) { - if (compute == FRAMES) { - currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i); - } else { - // updates current stack size (max stack size unchanged because - // stack size variation always negative or null) - stackSize += 1 - dims; - } - } - // adds the instruction to the bytecode of the method - code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims); - } - - @Override - public AnnotationVisitor visitInsnAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8); - AnnotationWriter.putTarget(typeRef, typePath, bv); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = ctanns; - ctanns = aw; - } else { - aw.next = ictanns; - ictanns = aw; - } - return aw; - } - - @Override - public void visitTryCatchBlock(final Label start, final Label end, - final Label handler, final String type) { - ++handlerCount; - Handler h = new Handler(); - h.start = start; - h.end = end; - h.handler = handler; - h.desc = type; - h.type = type != null ? cw.newClass(type) : 0; - if (lastHandler == null) { - firstHandler = h; - } else { - lastHandler.next = h; - } - lastHandler = h; - } - - @Override - public AnnotationVisitor visitTryCatchAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - AnnotationWriter.putTarget(typeRef, typePath, bv); - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = ctanns; - ctanns = aw; - } else { - aw.next = ictanns; - ictanns = aw; - } - return aw; - } - - @Override - public void visitLocalVariable(final String name, final String desc, - final String signature, final Label start, final Label end, - final int index) { - if (signature != null) { - if (localVarType == null) { - localVarType = new ByteVector(); - } - ++localVarTypeCount; - localVarType.putShort(start.position) - .putShort(end.position - start.position) - .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature)) - .putShort(index); - } - if (localVar == null) { - localVar = new ByteVector(); - } - ++localVarCount; - localVar.putShort(start.position) - .putShort(end.position - start.position) - .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc)) - .putShort(index); - if (compute != NOTHING) { - // updates max locals - char c = desc.charAt(0); - int n = index + (c == 'J' || c == 'D' ? 2 : 1); - if (n > maxLocals) { - maxLocals = n; - } - } - } - - @Override - public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, - TypePath typePath, Label[] start, Label[] end, int[] index, - String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } - ByteVector bv = new ByteVector(); - // write target_type and target_info - bv.putByte(typeRef >>> 24).putShort(start.length); - for (int i = 0; i < start.length; ++i) { - bv.putShort(start[i].position) - .putShort(end[i].position - start[i].position) - .putShort(index[i]); - } - if (typePath == null) { - bv.putByte(0); - } else { - int length = typePath.b[typePath.offset] * 2 + 1; - bv.putByteArray(typePath.b, typePath.offset, length); - } - // write type, and reserve space for values count - bv.putShort(cw.newUTF8(desc)).putShort(0); - AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, - bv.length - 2); - if (visible) { - aw.next = ctanns; - ctanns = aw; - } else { - aw.next = ictanns; - ictanns = aw; - } - return aw; - } - - @Override - public void visitLineNumber(final int line, final Label start) { - if (lineNumber == null) { - lineNumber = new ByteVector(); - } - ++lineNumberCount; - lineNumber.putShort(start.position); - lineNumber.putShort(line); - } - - @Override - public void visitMaxs(final int maxStack, final int maxLocals) { - if (resize) { - // replaces the temporary jump opcodes introduced by Label.resolve. - if (ClassReader.RESIZE) { - resizeInstructions(); - } else { - throw new RuntimeException("Method code too large!"); - } - } - if (ClassReader.FRAMES && compute == FRAMES) { - // completes the control flow graph with exception handler blocks - Handler handler = firstHandler; - while (handler != null) { - Label l = handler.start.getFirst(); - Label h = handler.handler.getFirst(); - Label e = handler.end.getFirst(); - // computes the kind of the edges to 'h' - String t = handler.desc == null ? "java/lang/Throwable" - : handler.desc; - int kind = Frame.OBJECT | cw.addType(t); - // h is an exception handler - h.status |= Label.TARGET; - // adds 'h' as a successor of labels between 'start' and 'end' - while (l != e) { - // creates an edge to 'h' - Edge b = new Edge(); - b.info = kind; - b.successor = h; - // adds it to the successors of 'l' - b.next = l.successors; - l.successors = b; - // goes to the next label - l = l.successor; - } - handler = handler.next; - } - - // creates and visits the first (implicit) frame - Frame f = labels.frame; - Type[] args = Type.getArgumentTypes(descriptor); - f.initInputFrame(cw, access, args, this.maxLocals); - visitFrame(f); - - /* - * fix point algorithm: mark the first basic block as 'changed' - * (i.e. put it in the 'changed' list) and, while there are changed - * basic blocks, choose one, mark it as unchanged, and update its - * successors (which can be changed in the process). - */ - int max = 0; - Label changed = labels; - while (changed != null) { - // removes a basic block from the list of changed basic blocks - Label l = changed; - changed = changed.next; - l.next = null; - f = l.frame; - // a reachable jump target must be stored in the stack map - if ((l.status & Label.TARGET) != 0) { - l.status |= Label.STORE; - } - // all visited labels are reachable, by definition - l.status |= Label.REACHABLE; - // updates the (absolute) maximum stack size - int blockMax = f.inputStack.length + l.outputStackMax; - if (blockMax > max) { - max = blockMax; - } - // updates the successors of the current basic block - Edge e = l.successors; - while (e != null) { - Label n = e.successor.getFirst(); - boolean change = f.merge(cw, n.frame, e.info); - if (change && n.next == null) { - // if n has changed and is not already in the 'changed' - // list, adds it to this list - n.next = changed; - changed = n; - } - e = e.next; - } - } - - // visits all the frames that must be stored in the stack map - Label l = labels; - while (l != null) { - f = l.frame; - if ((l.status & Label.STORE) != 0) { - visitFrame(f); - } - if ((l.status & Label.REACHABLE) == 0) { - // finds start and end of dead basic block - Label k = l.successor; - int start = l.position; - int end = (k == null ? code.length : k.position) - 1; - // if non empty basic block - if (end >= start) { - max = Math.max(max, 1); - // replaces instructions with NOP ... NOP ATHROW - for (int i = start; i < end; ++i) { - code.data[i] = Opcodes.NOP; - } - code.data[end] = (byte) Opcodes.ATHROW; - // emits a frame for this unreachable block - int frameIndex = startFrame(start, 0, 1); - frame[frameIndex] = Frame.OBJECT - | cw.addType("java/lang/Throwable"); - endFrame(); - // removes the start-end range from the exception - // handlers - firstHandler = Handler.remove(firstHandler, l, k); - } - } - l = l.successor; - } - - handler = firstHandler; - handlerCount = 0; - while (handler != null) { - handlerCount += 1; - handler = handler.next; - } - - this.maxStack = max; - } else if (compute == MAXS) { - // completes the control flow graph with exception handler blocks - Handler handler = firstHandler; - while (handler != null) { - Label l = handler.start; - Label h = handler.handler; - Label e = handler.end; - // adds 'h' as a successor of labels between 'start' and 'end' - while (l != e) { - // creates an edge to 'h' - Edge b = new Edge(); - b.info = Edge.EXCEPTION; - b.successor = h; - // adds it to the successors of 'l' - if ((l.status & Label.JSR) == 0) { - b.next = l.successors; - l.successors = b; - } else { - // if l is a JSR block, adds b after the first two edges - // to preserve the hypothesis about JSR block successors - // order (see {@link #visitJumpInsn}) - b.next = l.successors.next.next; - l.successors.next.next = b; - } - // goes to the next label - l = l.successor; - } - handler = handler.next; - } - - if (subroutines > 0) { - // completes the control flow graph with the RET successors - /* - * first step: finds the subroutines. This step determines, for - * each basic block, to which subroutine(s) it belongs. - */ - // finds the basic blocks that belong to the "main" subroutine - int id = 0; - labels.visitSubroutine(null, 1, subroutines); - // finds the basic blocks that belong to the real subroutines - Label l = labels; - while (l != null) { - if ((l.status & Label.JSR) != 0) { - // the subroutine is defined by l's TARGET, not by l - Label subroutine = l.successors.next.successor; - // if this subroutine has not been visited yet... - if ((subroutine.status & Label.VISITED) == 0) { - // ...assigns it a new id and finds its basic blocks - id += 1; - subroutine.visitSubroutine(null, (id / 32L) << 32 - | (1L << (id % 32)), subroutines); - } - } - l = l.successor; - } - // second step: finds the successors of RET blocks - l = labels; - while (l != null) { - if ((l.status & Label.JSR) != 0) { - Label L = labels; - while (L != null) { - L.status &= ~Label.VISITED2; - L = L.successor; - } - // the subroutine is defined by l's TARGET, not by l - Label subroutine = l.successors.next.successor; - subroutine.visitSubroutine(l, 0, subroutines); - } - l = l.successor; - } - } - - /* - * control flow analysis algorithm: while the block stack is not - * empty, pop a block from this stack, update the max stack size, - * compute the true (non relative) begin stack size of the - * successors of this block, and push these successors onto the - * stack (unless they have already been pushed onto the stack). - * Note: by hypothesis, the {@link Label#inputStackTop} of the - * blocks in the block stack are the true (non relative) beginning - * stack sizes of these blocks. - */ - int max = 0; - Label stack = labels; - while (stack != null) { - // pops a block from the stack - Label l = stack; - stack = stack.next; - // computes the true (non relative) max stack size of this block - int start = l.inputStackTop; - int blockMax = start + l.outputStackMax; - // updates the global max stack size - if (blockMax > max) { - max = blockMax; - } - // analyzes the successors of the block - Edge b = l.successors; - if ((l.status & Label.JSR) != 0) { - // ignores the first edge of JSR blocks (virtual successor) - b = b.next; - } - while (b != null) { - l = b.successor; - // if this successor has not already been pushed... - if ((l.status & Label.PUSHED) == 0) { - // computes its true beginning stack size... - l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start - + b.info; - // ...and pushes it onto the stack - l.status |= Label.PUSHED; - l.next = stack; - stack = l; - } - b = b.next; - } - } - this.maxStack = Math.max(maxStack, max); - } else { - this.maxStack = maxStack; - this.maxLocals = maxLocals; - } - } - - @Override - public void visitEnd() { - } - - // ------------------------------------------------------------------------ - // Utility methods: control flow analysis algorithm - // ------------------------------------------------------------------------ - - /** - * Adds a successor to the {@link #currentBlock currentBlock} block. - * - * @param info - * information about the control flow edge to be added. - * @param successor - * the successor block to be added to the current block. - */ - private void addSuccessor(final int info, final Label successor) { - // creates and initializes an Edge object... - Edge b = new Edge(); - b.info = info; - b.successor = successor; - // ...and adds it to the successor list of the currentBlock block - b.next = currentBlock.successors; - currentBlock.successors = b; - } - - /** - * Ends the current basic block. This method must be used in the case where - * the current basic block does not have any successor. - */ - private void noSuccessor() { - if (compute == FRAMES) { - Label l = new Label(); - l.frame = new Frame(); - l.frame.owner = l; - l.resolve(this, code.length, code.data); - previousBlock.successor = l; - previousBlock = l; - } else { - currentBlock.outputStackMax = maxStackSize; - } - currentBlock = null; - } - - // ------------------------------------------------------------------------ - // Utility methods: stack map frames - // ------------------------------------------------------------------------ - - /** - * Visits a frame that has been computed from scratch. - * - * @param f - * the frame that must be visited. - */ - private void visitFrame(final Frame f) { - int i, t; - int nTop = 0; - int nLocal = 0; - int nStack = 0; - int[] locals = f.inputLocals; - int[] stacks = f.inputStack; - // computes the number of locals (ignores TOP types that are just after - // a LONG or a DOUBLE, and all trailing TOP types) - for (i = 0; i < locals.length; ++i) { - t = locals[i]; - if (t == Frame.TOP) { - ++nTop; - } else { - nLocal += nTop + 1; - nTop = 0; - } - if (t == Frame.LONG || t == Frame.DOUBLE) { - ++i; - } - } - // computes the stack size (ignores TOP types that are just after - // a LONG or a DOUBLE) - for (i = 0; i < stacks.length; ++i) { - t = stacks[i]; - ++nStack; - if (t == Frame.LONG || t == Frame.DOUBLE) { - ++i; - } - } - // visits the frame and its content - int frameIndex = startFrame(f.owner.position, nLocal, nStack); - for (i = 0; nLocal > 0; ++i, --nLocal) { - t = locals[i]; - frame[frameIndex++] = t; - if (t == Frame.LONG || t == Frame.DOUBLE) { - ++i; - } - } - for (i = 0; i < stacks.length; ++i) { - t = stacks[i]; - frame[frameIndex++] = t; - if (t == Frame.LONG || t == Frame.DOUBLE) { - ++i; - } - } - endFrame(); - } - - /** - * Visit the implicit first frame of this method. - */ - private void visitImplicitFirstFrame() { - // There can be at most descriptor.length() + 1 locals - int frameIndex = startFrame(0, descriptor.length() + 1, 0); - if ((access & Opcodes.ACC_STATIC) == 0) { - if ((access & ACC_CONSTRUCTOR) == 0) { - frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName); - } else { - frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS; - } - } - int i = 1; - loop: while (true) { - int j = i; - switch (descriptor.charAt(i++)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - frame[frameIndex++] = 1; // Opcodes.INTEGER; - break; - case 'F': - frame[frameIndex++] = 2; // Opcodes.FLOAT; - break; - case 'J': - frame[frameIndex++] = 4; // Opcodes.LONG; - break; - case 'D': - frame[frameIndex++] = 3; // Opcodes.DOUBLE; - break; - case '[': - while (descriptor.charAt(i) == '[') { - ++i; - } - if (descriptor.charAt(i) == 'L') { - ++i; - while (descriptor.charAt(i) != ';') { - ++i; - } - } - frame[frameIndex++] = Frame.OBJECT - | cw.addType(descriptor.substring(j, ++i)); - break; - case 'L': - while (descriptor.charAt(i) != ';') { - ++i; - } - frame[frameIndex++] = Frame.OBJECT - | cw.addType(descriptor.substring(j + 1, i++)); - break; - default: - break loop; - } - } - frame[1] = frameIndex - 3; - endFrame(); - } - - /** - * Starts the visit of a stack map frame. - * - * @param offset - * the offset of the instruction to which the frame corresponds. - * @param nLocal - * the number of local variables in the frame. - * @param nStack - * the number of stack elements in the frame. - * @return the index of the next element to be written in this frame. - */ - private int startFrame(final int offset, final int nLocal, final int nStack) { - int n = 3 + nLocal + nStack; - if (frame == null || frame.length < n) { - frame = new int[n]; - } - frame[0] = offset; - frame[1] = nLocal; - frame[2] = nStack; - return 3; - } - - /** - * Checks if the visit of the current frame {@link #frame} is finished, and - * if yes, write it in the StackMapTable attribute. - */ - private void endFrame() { - if (previousFrame != null) { // do not write the first frame - if (stackMap == null) { - stackMap = new ByteVector(); - } - writeFrame(); - ++frameCount; - } - previousFrame = frame; - frame = null; - } - - /** - * Compress and writes the current frame {@link #frame} in the StackMapTable - * attribute. - */ - private void writeFrame() { - int clocalsSize = frame[1]; - int cstackSize = frame[2]; - if ((cw.version & 0xFFFF) < Opcodes.V1_6) { - stackMap.putShort(frame[0]).putShort(clocalsSize); - writeFrameTypes(3, 3 + clocalsSize); - stackMap.putShort(cstackSize); - writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); - return; - } - int localsSize = previousFrame[1]; - int type = FULL_FRAME; - int k = 0; - int delta; - if (frameCount == 0) { - delta = frame[0]; - } else { - delta = frame[0] - previousFrame[0] - 1; - } - if (cstackSize == 0) { - k = clocalsSize - localsSize; - switch (k) { - case -3: - case -2: - case -1: - type = CHOP_FRAME; - localsSize = clocalsSize; - break; - case 0: - type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED; - break; - case 1: - case 2: - case 3: - type = APPEND_FRAME; - break; - } - } else if (clocalsSize == localsSize && cstackSize == 1) { - type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME - : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED; - } - if (type != FULL_FRAME) { - // verify if locals are the same - int l = 3; - for (int j = 0; j < localsSize; j++) { - if (frame[l] != previousFrame[l]) { - type = FULL_FRAME; - break; - } - l++; - } - } - switch (type) { - case SAME_FRAME: - stackMap.putByte(delta); - break; - case SAME_LOCALS_1_STACK_ITEM_FRAME: - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); - writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); - break; - case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: - stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort( - delta); - writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); - break; - case SAME_FRAME_EXTENDED: - stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); - break; - case CHOP_FRAME: - stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); - break; - case APPEND_FRAME: - stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); - writeFrameTypes(3 + localsSize, 3 + clocalsSize); - break; - // case FULL_FRAME: - default: - stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize); - writeFrameTypes(3, 3 + clocalsSize); - stackMap.putShort(cstackSize); - writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); - } - } - - /** - * Writes some types of the current frame {@link #frame} into the - * StackMapTableAttribute. This method converts types from the format used - * in {@link Label} to the format used in StackMapTable attributes. In - * particular, it converts type table indexes to constant pool indexes. - * - * @param start - * index of the first type in {@link #frame} to write. - * @param end - * index of last type in {@link #frame} to write (exclusive). - */ - private void writeFrameTypes(final int start, final int end) { - for (int i = start; i < end; ++i) { - int t = frame[i]; - int d = t & Frame.DIM; - if (d == 0) { - int v = t & Frame.BASE_VALUE; - switch (t & Frame.BASE_KIND) { - case Frame.OBJECT: - stackMap.putByte(7).putShort( - cw.newClass(cw.typeTable[v].strVal1)); - break; - case Frame.UNINITIALIZED: - stackMap.putByte(8).putShort(cw.typeTable[v].intVal); - break; - default: - stackMap.putByte(v); - } - } else { - StringBuilder sb = new StringBuilder(); - d >>= 28; - while (d-- > 0) { - sb.append('['); - } - if ((t & Frame.BASE_KIND) == Frame.OBJECT) { - sb.append('L'); - sb.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1); - sb.append(';'); - } else { - switch (t & 0xF) { - case 1: - sb.append('I'); - break; - case 2: - sb.append('F'); - break; - case 3: - sb.append('D'); - break; - case 9: - sb.append('Z'); - break; - case 10: - sb.append('B'); - break; - case 11: - sb.append('C'); - break; - case 12: - sb.append('S'); - break; - default: - sb.append('J'); - } - } - stackMap.putByte(7).putShort(cw.newClass(sb.toString())); - } - } - } - - private void writeFrameType(final Object type) { - if (type instanceof String) { - stackMap.putByte(7).putShort(cw.newClass((String) type)); - } else if (type instanceof Integer) { - stackMap.putByte(((Integer) type).intValue()); - } else { - stackMap.putByte(8).putShort(((Label) type).position); - } - } - - // ------------------------------------------------------------------------ - // Utility methods: dump bytecode array - // ------------------------------------------------------------------------ - - /** - * Returns the size of the bytecode of this method. - * - * @return the size of the bytecode of this method. - */ - final int getSize() { - if (classReaderOffset != 0) { - return 6 + classReaderLength; - } - int size = 8; - if (code.length > 0) { - if (code.length > 65536) { - String nameString = ""; - Item nameItem = cw.findItemByIndex(name); - if (nameItem != null) nameString = nameItem.strVal1 +"'s "; - throw new RuntimeException("Method "+ nameString +"code too large!"); - } - cw.newUTF8("Code"); - size += 18 + code.length + 8 * handlerCount; - if (localVar != null) { - cw.newUTF8("LocalVariableTable"); - size += 8 + localVar.length; - } - if (localVarType != null) { - cw.newUTF8("LocalVariableTypeTable"); - size += 8 + localVarType.length; - } - if (lineNumber != null) { - cw.newUTF8("LineNumberTable"); - size += 8 + lineNumber.length; - } - if (stackMap != null) { - boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; - cw.newUTF8(zip ? "StackMapTable" : "StackMap"); - size += 8 + stackMap.length; - } - if (ClassReader.ANNOTATIONS && ctanns != null) { - cw.newUTF8("RuntimeVisibleTypeAnnotations"); - size += 8 + ctanns.getSize(); - } - if (ClassReader.ANNOTATIONS && ictanns != null) { - cw.newUTF8("RuntimeInvisibleTypeAnnotations"); - size += 8 + ictanns.getSize(); - } - if (cattrs != null) { - size += cattrs.getSize(cw, code.data, code.length, maxStack, - maxLocals); - } - } - if (exceptionCount > 0) { - cw.newUTF8("Exceptions"); - size += 8 + 2 * exceptionCount; - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - cw.newUTF8("Synthetic"); - size += 6; - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - cw.newUTF8("Deprecated"); - size += 6; - } - if (ClassReader.SIGNATURES && signature != null) { - cw.newUTF8("Signature"); - cw.newUTF8(signature); - size += 8; - } - if (methodParameters != null) { - cw.newUTF8("MethodParameters"); - size += 7 + methodParameters.length; - } - if (ClassReader.ANNOTATIONS && annd != null) { - cw.newUTF8("AnnotationDefault"); - size += 6 + annd.length; - } - if (ClassReader.ANNOTATIONS && anns != null) { - cw.newUTF8("RuntimeVisibleAnnotations"); - size += 8 + anns.getSize(); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - cw.newUTF8("RuntimeInvisibleAnnotations"); - size += 8 + ianns.getSize(); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - cw.newUTF8("RuntimeVisibleTypeAnnotations"); - size += 8 + tanns.getSize(); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - cw.newUTF8("RuntimeInvisibleTypeAnnotations"); - size += 8 + itanns.getSize(); - } - if (ClassReader.ANNOTATIONS && panns != null) { - cw.newUTF8("RuntimeVisibleParameterAnnotations"); - size += 7 + 2 * (panns.length - synthetics); - for (int i = panns.length - 1; i >= synthetics; --i) { - size += panns[i] == null ? 0 : panns[i].getSize(); - } - } - if (ClassReader.ANNOTATIONS && ipanns != null) { - cw.newUTF8("RuntimeInvisibleParameterAnnotations"); - size += 7 + 2 * (ipanns.length - synthetics); - for (int i = ipanns.length - 1; i >= synthetics; --i) { - size += ipanns[i] == null ? 0 : ipanns[i].getSize(); - } - } - if (attrs != null) { - size += attrs.getSize(cw, null, 0, -1, -1); - } - return size; - } - - /** - * Puts the bytecode of this method in the given byte vector. - * - * @param out - * the byte vector into which the bytecode of this method must be - * copied. - */ - final void put(final ByteVector out) { - final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; - int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED - | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); - out.putShort(access & ~mask).putShort(name).putShort(desc); - if (classReaderOffset != 0) { - out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength); - return; - } - int attributeCount = 0; - if (code.length > 0) { - ++attributeCount; - } - if (exceptionCount > 0) { - ++attributeCount; - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - ++attributeCount; - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - ++attributeCount; - } - if (ClassReader.SIGNATURES && signature != null) { - ++attributeCount; - } - if (methodParameters != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && annd != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && anns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && ianns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && tanns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && itanns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && panns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && ipanns != null) { - ++attributeCount; - } - if (attrs != null) { - attributeCount += attrs.getCount(); - } - out.putShort(attributeCount); - if (code.length > 0) { - int size = 12 + code.length + 8 * handlerCount; - if (localVar != null) { - size += 8 + localVar.length; - } - if (localVarType != null) { - size += 8 + localVarType.length; - } - if (lineNumber != null) { - size += 8 + lineNumber.length; - } - if (stackMap != null) { - size += 8 + stackMap.length; - } - if (ClassReader.ANNOTATIONS && ctanns != null) { - size += 8 + ctanns.getSize(); - } - if (ClassReader.ANNOTATIONS && ictanns != null) { - size += 8 + ictanns.getSize(); - } - if (cattrs != null) { - size += cattrs.getSize(cw, code.data, code.length, maxStack, - maxLocals); - } - out.putShort(cw.newUTF8("Code")).putInt(size); - out.putShort(maxStack).putShort(maxLocals); - out.putInt(code.length).putByteArray(code.data, 0, code.length); - out.putShort(handlerCount); - if (handlerCount > 0) { - Handler h = firstHandler; - while (h != null) { - out.putShort(h.start.position).putShort(h.end.position) - .putShort(h.handler.position).putShort(h.type); - h = h.next; - } - } - attributeCount = 0; - if (localVar != null) { - ++attributeCount; - } - if (localVarType != null) { - ++attributeCount; - } - if (lineNumber != null) { - ++attributeCount; - } - if (stackMap != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && ctanns != null) { - ++attributeCount; - } - if (ClassReader.ANNOTATIONS && ictanns != null) { - ++attributeCount; - } - if (cattrs != null) { - attributeCount += cattrs.getCount(); - } - out.putShort(attributeCount); - if (localVar != null) { - out.putShort(cw.newUTF8("LocalVariableTable")); - out.putInt(localVar.length + 2).putShort(localVarCount); - out.putByteArray(localVar.data, 0, localVar.length); - } - if (localVarType != null) { - out.putShort(cw.newUTF8("LocalVariableTypeTable")); - out.putInt(localVarType.length + 2).putShort(localVarTypeCount); - out.putByteArray(localVarType.data, 0, localVarType.length); - } - if (lineNumber != null) { - out.putShort(cw.newUTF8("LineNumberTable")); - out.putInt(lineNumber.length + 2).putShort(lineNumberCount); - out.putByteArray(lineNumber.data, 0, lineNumber.length); - } - if (stackMap != null) { - boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; - out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap")); - out.putInt(stackMap.length + 2).putShort(frameCount); - out.putByteArray(stackMap.data, 0, stackMap.length); - } - if (ClassReader.ANNOTATIONS && ctanns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); - ctanns.put(out); - } - if (ClassReader.ANNOTATIONS && ictanns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); - ictanns.put(out); - } - if (cattrs != null) { - cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); - } - } - if (exceptionCount > 0) { - out.putShort(cw.newUTF8("Exceptions")).putInt( - 2 * exceptionCount + 2); - out.putShort(exceptionCount); - for (int i = 0; i < exceptionCount; ++i) { - out.putShort(exceptions[i]); - } - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if ((cw.version & 0xFFFF) < Opcodes.V1_5 - || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { - out.putShort(cw.newUTF8("Synthetic")).putInt(0); - } - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - out.putShort(cw.newUTF8("Deprecated")).putInt(0); - } - if (ClassReader.SIGNATURES && signature != null) { - out.putShort(cw.newUTF8("Signature")).putInt(2) - .putShort(cw.newUTF8(signature)); - } - if (methodParameters != null) { - out.putShort(cw.newUTF8("MethodParameters")); - out.putInt(methodParameters.length + 1).putByte( - methodParametersCount); - out.putByteArray(methodParameters.data, 0, methodParameters.length); - } - if (ClassReader.ANNOTATIONS && annd != null) { - out.putShort(cw.newUTF8("AnnotationDefault")); - out.putInt(annd.length); - out.putByteArray(annd.data, 0, annd.length); - } - if (ClassReader.ANNOTATIONS && anns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); - anns.put(out); - } - if (ClassReader.ANNOTATIONS && ianns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); - ianns.put(out); - } - if (ClassReader.ANNOTATIONS && tanns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); - tanns.put(out); - } - if (ClassReader.ANNOTATIONS && itanns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); - itanns.put(out); - } - if (ClassReader.ANNOTATIONS && panns != null) { - out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); - AnnotationWriter.put(panns, synthetics, out); - } - if (ClassReader.ANNOTATIONS && ipanns != null) { - out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); - AnnotationWriter.put(ipanns, synthetics, out); - } - if (attrs != null) { - attrs.put(cw, null, 0, -1, -1, out); - } - } - - // ------------------------------------------------------------------------ - // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W) - // ------------------------------------------------------------------------ - - /** - * Resizes and replaces the temporary instructions inserted by - * {@link Label#resolve} for wide forward jumps, while keeping jump offsets - * and instruction addresses consistent. This may require to resize other - * existing instructions, or even to introduce new instructions: for - * example, increasing the size of an instruction by 2 at the middle of a - * method can increases the offset of an IFEQ instruction from 32766 to - * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W - * 32765. This, in turn, may require to increase the size of another jump - * instruction, and so on... All these operations are handled automatically - * by this method. - * <p> - * <i>This method must be called after all the method that is being built - * has been visited</i>. In particular, the {@link Label Label} objects used - * to construct the method are no longer valid after this method has been - * called. - */ - private void resizeInstructions() { - byte[] b = code.data; // bytecode of the method - int u, v, label; // indexes in b - int i, j; // loop indexes - /* - * 1st step: As explained above, resizing an instruction may require to - * resize another one, which may require to resize yet another one, and - * so on. The first step of the algorithm consists in finding all the - * instructions that need to be resized, without modifying the code. - * This is done by the following "fix point" algorithm: - * - * Parse the code to find the jump instructions whose offset will need - * more than 2 bytes to be stored (the future offset is computed from - * the current offset and from the number of bytes that will be inserted - * or removed between the source and target instructions). For each such - * instruction, adds an entry in (a copy of) the indexes and sizes - * arrays (if this has not already been done in a previous iteration!). - * - * If at least one entry has been added during the previous step, go - * back to the beginning, otherwise stop. - * - * In fact the real algorithm is complicated by the fact that the size - * of TABLESWITCH and LOOKUPSWITCH instructions depends on their - * position in the bytecode (because of padding). In order to ensure the - * convergence of the algorithm, the number of bytes to be added or - * removed from these instructions is over estimated during the previous - * loop, and computed exactly only after the loop is finished (this - * requires another pass to parse the bytecode of the method). - */ - int[] allIndexes = new int[0]; // copy of indexes - int[] allSizes = new int[0]; // copy of sizes - boolean[] resize; // instructions to be resized - int newOffset; // future offset of a jump instruction - - resize = new boolean[code.length]; - - // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done - int state = 3; - do { - if (state == 3) { - state = 2; - } - u = 0; - while (u < b.length) { - int opcode = b[u] & 0xFF; // opcode of current instruction - int insert = 0; // bytes to be added after this instruction - - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - u += 1; - break; - case ClassWriter.LABEL_INSN: - if (opcode > 201) { - // converts temporary opcodes 202 to 217, 218 and - // 219 to IFEQ ... JSR (inclusive), IFNULL and - // IFNONNULL - opcode = opcode < 218 ? opcode - 49 : opcode - 20; - label = u + readUnsignedShort(b, u + 1); - } else { - label = u + readShort(b, u + 1); - } - newOffset = getNewOffset(allIndexes, allSizes, u, label); - if (newOffset < Short.MIN_VALUE - || newOffset > Short.MAX_VALUE) { - if (!resize[u]) { - if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { - // two additional bytes will be required to - // replace this GOTO or JSR instruction with - // a GOTO_W or a JSR_W - insert = 2; - } else { - // five additional bytes will be required to - // replace this IFxxx <l> instruction with - // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx - // is the "opposite" opcode of IFxxx (i.e., - // IFNE for IFEQ) and where <l'> designates - // the instruction just after the GOTO_W. - insert = 5; - } - resize[u] = true; - } - } - u += 3; - break; - case ClassWriter.LABELW_INSN: - u += 5; - break; - case ClassWriter.TABL_INSN: - if (state == 1) { - // true number of bytes to be added (or removed) - // from this instruction = (future number of padding - // bytes - current number of padding byte) - - // previously over estimated variation = - // = ((3 - newOffset%4) - (3 - u%4)) - u%4 - // = (-newOffset%4 + u%4) - u%4 - // = -(newOffset & 3) - newOffset = getNewOffset(allIndexes, allSizes, 0, u); - insert = -(newOffset & 3); - } else if (!resize[u]) { - // over estimation of the number of bytes to be - // added to this instruction = 3 - current number - // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3 - insert = u & 3; - resize[u] = true; - } - // skips instruction - u = u + 4 - (u & 3); - u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; - break; - case ClassWriter.LOOK_INSN: - if (state == 1) { - // like TABL_INSN - newOffset = getNewOffset(allIndexes, allSizes, 0, u); - insert = -(newOffset & 3); - } else if (!resize[u]) { - // like TABL_INSN - insert = u & 3; - resize[u] = true; - } - // skips instruction - u = u + 4 - (u & 3); - u += 8 * readInt(b, u + 4) + 8; - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - u += 6; - } else { - u += 4; - } - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - u += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - u += 3; - break; - case ClassWriter.ITFMETH_INSN: - case ClassWriter.INDYMETH_INSN: - u += 5; - break; - // case ClassWriter.MANA_INSN: - default: - u += 4; - break; - } - if (insert != 0) { - // adds a new (u, insert) entry in the allIndexes and - // allSizes arrays - int[] newIndexes = new int[allIndexes.length + 1]; - int[] newSizes = new int[allSizes.length + 1]; - System.arraycopy(allIndexes, 0, newIndexes, 0, - allIndexes.length); - System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); - newIndexes[allIndexes.length] = u; - newSizes[allSizes.length] = insert; - allIndexes = newIndexes; - allSizes = newSizes; - if (insert > 0) { - state = 3; - } - } - } - if (state < 3) { - --state; - } - } while (state != 0); - - // 2nd step: - // copies the bytecode of the method into a new bytevector, updates the - // offsets, and inserts (or removes) bytes as requested. - - ByteVector newCode = new ByteVector(code.length); - - u = 0; - while (u < code.length) { - int opcode = b[u] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - newCode.putByte(opcode); - u += 1; - break; - case ClassWriter.LABEL_INSN: - if (opcode > 201) { - // changes temporary opcodes 202 to 217 (inclusive), 218 - // and 219 to IFEQ ... JSR (inclusive), IFNULL and - // IFNONNULL - opcode = opcode < 218 ? opcode - 49 : opcode - 20; - label = u + readUnsignedShort(b, u + 1); - } else { - label = u + readShort(b, u + 1); - } - newOffset = getNewOffset(allIndexes, allSizes, u, label); - if (resize[u]) { - // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx - // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is - // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) - // and where <l'> designates the instruction just after - // the GOTO_W. - if (opcode == Opcodes.GOTO) { - newCode.putByte(200); // GOTO_W - } else if (opcode == Opcodes.JSR) { - newCode.putByte(201); // JSR_W - } else { - newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 - : opcode ^ 1); - newCode.putShort(8); // jump offset - newCode.putByte(200); // GOTO_W - // newOffset now computed from start of GOTO_W - newOffset -= 3; - } - newCode.putInt(newOffset); - } else { - newCode.putByte(opcode); - newCode.putShort(newOffset); - } - u += 3; - break; - case ClassWriter.LABELW_INSN: - label = u + readInt(b, u + 1); - newOffset = getNewOffset(allIndexes, allSizes, u, label); - newCode.putByte(opcode); - newCode.putInt(newOffset); - u += 5; - break; - case ClassWriter.TABL_INSN: - // skips 0 to 3 padding bytes - v = u; - u = u + 4 - (v & 3); - // reads and copies instruction - newCode.putByte(Opcodes.TABLESWITCH); - newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - j = readInt(b, u); - u += 4; - newCode.putInt(j); - j = readInt(b, u) - j + 1; - u += 4; - newCode.putInt(readInt(b, u - 4)); - for (; j > 0; --j) { - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - } - break; - case ClassWriter.LOOK_INSN: - // skips 0 to 3 padding bytes - v = u; - u = u + 4 - (v & 3); - // reads and copies instruction - newCode.putByte(Opcodes.LOOKUPSWITCH); - newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - j = readInt(b, u); - u += 4; - newCode.putInt(j); - for (; j > 0; --j) { - newCode.putInt(readInt(b, u)); - u += 4; - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - } - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - newCode.putByteArray(b, u, 6); - u += 6; - } else { - newCode.putByteArray(b, u, 4); - u += 4; - } - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - newCode.putByteArray(b, u, 2); - u += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - newCode.putByteArray(b, u, 3); - u += 3; - break; - case ClassWriter.ITFMETH_INSN: - case ClassWriter.INDYMETH_INSN: - newCode.putByteArray(b, u, 5); - u += 5; - break; - // case MANA_INSN: - default: - newCode.putByteArray(b, u, 4); - u += 4; - break; - } - } - - // updates the stack map frame labels - if (compute == FRAMES) { - Label l = labels; - while (l != null) { - /* - * Detects the labels that are just after an IF instruction that - * has been resized with the IFNOT GOTO_W pattern. These labels - * are now the target of a jump instruction (the IFNOT - * instruction). Note that we need the original label position - * here. getNewOffset must therefore never have been called for - * this label. - */ - u = l.position - 3; - if (u >= 0 && resize[u]) { - l.status |= Label.TARGET; - } - getNewOffset(allIndexes, allSizes, l); - l = l.successor; - } - // Update the offsets in the uninitialized types - for (i = 0; i < cw.typeTable.length; ++i) { - Item item = cw.typeTable[i]; - if (item != null && item.type == ClassWriter.TYPE_UNINIT) { - item.intVal = getNewOffset(allIndexes, allSizes, 0, - item.intVal); - } - } - // The stack map frames are not serialized yet, so we don't need - // to update them. They will be serialized in visitMaxs. - } else if (frameCount > 0) { - /* - * Resizing an existing stack map frame table is really hard. Not - * only the table must be parsed to update the offets, but new - * frames may be needed for jump instructions that were inserted by - * this method. And updating the offsets or inserting frames can - * change the format of the following frames, in case of packed - * frames. In practice the whole table must be recomputed. For this - * the frames are marked as potentially invalid. This will cause the - * whole class to be reread and rewritten with the COMPUTE_FRAMES - * option (see the ClassWriter.toByteArray method). This is not very - * efficient but is much easier and requires much less code than any - * other method I can think of. - */ - cw.invalidFrames = true; - } - // updates the exception handler block labels - Handler h = firstHandler; - while (h != null) { - getNewOffset(allIndexes, allSizes, h.start); - getNewOffset(allIndexes, allSizes, h.end); - getNewOffset(allIndexes, allSizes, h.handler); - h = h.next; - } - // updates the instructions addresses in the - // local var and line number tables - for (i = 0; i < 2; ++i) { - ByteVector bv = i == 0 ? localVar : localVarType; - if (bv != null) { - b = bv.data; - u = 0; - while (u < bv.length) { - label = readUnsignedShort(b, u); - newOffset = getNewOffset(allIndexes, allSizes, 0, label); - writeShort(b, u, newOffset); - label += readUnsignedShort(b, u + 2); - newOffset = getNewOffset(allIndexes, allSizes, 0, label) - - newOffset; - writeShort(b, u + 2, newOffset); - u += 10; - } - } - } - if (lineNumber != null) { - b = lineNumber.data; - u = 0; - while (u < lineNumber.length) { - writeShort( - b, - u, - getNewOffset(allIndexes, allSizes, 0, - readUnsignedShort(b, u))); - u += 4; - } - } - // updates the labels of the other attributes - Attribute attr = cattrs; - while (attr != null) { - Label[] labels = attr.getLabels(); - if (labels != null) { - for (i = labels.length - 1; i >= 0; --i) { - getNewOffset(allIndexes, allSizes, labels[i]); - } - } - attr = attr.next; - } - - // replaces old bytecodes with new ones - code = newCode; - } - - /** - * Reads an unsigned short value in the given byte array. - * - * @param b - * a byte array. - * @param index - * the start index of the value to be read. - * @return the read value. - */ - static int readUnsignedShort(final byte[] b, final int index) { - return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); - } - - /** - * Reads a signed short value in the given byte array. - * - * @param b - * a byte array. - * @param index - * the start index of the value to be read. - * @return the read value. - */ - static short readShort(final byte[] b, final int index) { - return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); - } - - /** - * Reads a signed int value in the given byte array. - * - * @param b - * a byte array. - * @param index - * the start index of the value to be read. - * @return the read value. - */ - static int readInt(final byte[] b, final int index) { - return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) - | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); - } - - /** - * Writes a short value in the given byte array. - * - * @param b - * a byte array. - * @param index - * where the first byte of the short value must be written. - * @param s - * the value to be written in the given byte array. - */ - static void writeShort(final byte[] b, final int index, final int s) { - b[index] = (byte) (s >>> 8); - b[index + 1] = (byte) s; - } - - /** - * Computes the future value of a bytecode offset. - * <p> - * Note: it is possible to have several entries for the same instruction in - * the <tt>indexes</tt> and <tt>sizes</tt>: two entries (index=a,size=b) and - * (index=a,size=b') are equivalent to a single entry (index=a,size=b+b'). - * - * @param indexes - * current positions of the instructions to be resized. Each - * instruction must be designated by the index of its <i>last</i> - * byte, plus one (or, in other words, by the index of the - * <i>first</i> byte of the <i>next</i> instruction). - * @param sizes - * the number of bytes to be <i>added</i> to the above - * instructions. More precisely, for each i < <tt>len</tt>, - * <tt>sizes</tt>[i] bytes will be added at the end of the - * instruction designated by <tt>indexes</tt>[i] or, if - * <tt>sizes</tt>[i] is negative, the <i>last</i> | - * <tt>sizes[i]</tt>| bytes of the instruction will be removed - * (the instruction size <i>must not</i> become negative or - * null). - * @param begin - * index of the first byte of the source instruction. - * @param end - * index of the first byte of the target instruction. - * @return the future value of the given bytecode offset. - */ - static int getNewOffset(final int[] indexes, final int[] sizes, - final int begin, final int end) { - int offset = end - begin; - for (int i = 0; i < indexes.length; ++i) { - if (begin < indexes[i] && indexes[i] <= end) { - // forward jump - offset += sizes[i]; - } else if (end < indexes[i] && indexes[i] <= begin) { - // backward jump - offset -= sizes[i]; - } - } - return offset; - } - - /** - * Updates the offset of the given label. - * - * @param indexes - * current positions of the instructions to be resized. Each - * instruction must be designated by the index of its <i>last</i> - * byte, plus one (or, in other words, by the index of the - * <i>first</i> byte of the <i>next</i> instruction). - * @param sizes - * the number of bytes to be <i>added</i> to the above - * instructions. More precisely, for each i < <tt>len</tt>, - * <tt>sizes</tt>[i] bytes will be added at the end of the - * instruction designated by <tt>indexes</tt>[i] or, if - * <tt>sizes</tt>[i] is negative, the <i>last</i> | - * <tt>sizes[i]</tt>| bytes of the instruction will be removed - * (the instruction size <i>must not</i> become negative or - * null). - * @param label - * the label whose offset must be updated. - */ - static void getNewOffset(final int[] indexes, final int[] sizes, - final Label label) { - if ((label.status & Label.RESIZED) == 0) { - label.position = getNewOffset(indexes, sizes, 0, label.position); - label.status |= Label.RESIZED; - } - } -} diff --git a/src/asm/scala/tools/asm/Opcodes.java b/src/asm/scala/tools/asm/Opcodes.java deleted file mode 100644 index 24eaffa717..0000000000 --- a/src/asm/scala/tools/asm/Opcodes.java +++ /dev/null @@ -1,361 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -/** - * Defines the JVM opcodes, access flags and array type codes. This interface - * does not define all the JVM opcodes because some opcodes are automatically - * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced - * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n - * opcodes are therefore not defined in this interface. Likewise for LDC, - * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and - * JSR_W. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public interface Opcodes { - - // ASM API versions - - int ASM4 = 4 << 16 | 0 << 8 | 0; - int ASM5 = 5 << 16 | 0 << 8 | 0; - - // versions - - int V1_1 = 3 << 16 | 45; - int V1_2 = 0 << 16 | 46; - int V1_3 = 0 << 16 | 47; - int V1_4 = 0 << 16 | 48; - int V1_5 = 0 << 16 | 49; - int V1_6 = 0 << 16 | 50; - int V1_7 = 0 << 16 | 51; - int V1_8 = 0 << 16 | 52; - - // access flags - - int ACC_PUBLIC = 0x0001; // class, field, method - int ACC_PRIVATE = 0x0002; // class, field, method - int ACC_PROTECTED = 0x0004; // class, field, method - int ACC_STATIC = 0x0008; // field, method - int ACC_FINAL = 0x0010; // class, field, method, parameter - int ACC_SUPER = 0x0020; // class - int ACC_SYNCHRONIZED = 0x0020; // method - int ACC_VOLATILE = 0x0040; // field - int ACC_BRIDGE = 0x0040; // method - int ACC_VARARGS = 0x0080; // method - int ACC_TRANSIENT = 0x0080; // field - int ACC_NATIVE = 0x0100; // method - int ACC_INTERFACE = 0x0200; // class - int ACC_ABSTRACT = 0x0400; // class, method - int ACC_STRICT = 0x0800; // method - int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter - int ACC_ANNOTATION = 0x2000; // class - int ACC_ENUM = 0x4000; // class(?) field inner - int ACC_MANDATED = 0x8000; // parameter - - // ASM specific pseudo access flags - - int ACC_DEPRECATED = 0x20000; // class, field, method - - // types for NEWARRAY - - int T_BOOLEAN = 4; - int T_CHAR = 5; - int T_FLOAT = 6; - int T_DOUBLE = 7; - int T_BYTE = 8; - int T_SHORT = 9; - int T_INT = 10; - int T_LONG = 11; - - // tags for Handle - - int H_GETFIELD = 1; - int H_GETSTATIC = 2; - int H_PUTFIELD = 3; - int H_PUTSTATIC = 4; - int H_INVOKEVIRTUAL = 5; - int H_INVOKESTATIC = 6; - int H_INVOKESPECIAL = 7; - int H_NEWINVOKESPECIAL = 8; - int H_INVOKEINTERFACE = 9; - - // stack map frame types - - /** - * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}. - */ - int F_NEW = -1; - - /** - * Represents a compressed frame with complete frame data. - */ - int F_FULL = 0; - - /** - * Represents a compressed frame where locals are the same as the locals in - * the previous frame, except that additional 1-3 locals are defined, and - * with an empty stack. - */ - int F_APPEND = 1; - - /** - * Represents a compressed frame where locals are the same as the locals in - * the previous frame, except that the last 1-3 locals are absent and with - * an empty stack. - */ - int F_CHOP = 2; - - /** - * Represents a compressed frame with exactly the same locals as the - * previous frame and with an empty stack. - */ - int F_SAME = 3; - - /** - * Represents a compressed frame with exactly the same locals as the - * previous frame and with a single value on the stack. - */ - int F_SAME1 = 4; - - Integer TOP = new Integer(0); - Integer INTEGER = new Integer(1); - Integer FLOAT = new Integer(2); - Integer DOUBLE = new Integer(3); - Integer LONG = new Integer(4); - Integer NULL = new Integer(5); - Integer UNINITIALIZED_THIS = new Integer(6); - - // opcodes // visit method (- = idem) - - int NOP = 0; // visitInsn - int ACONST_NULL = 1; // - - int ICONST_M1 = 2; // - - int ICONST_0 = 3; // - - int ICONST_1 = 4; // - - int ICONST_2 = 5; // - - int ICONST_3 = 6; // - - int ICONST_4 = 7; // - - int ICONST_5 = 8; // - - int LCONST_0 = 9; // - - int LCONST_1 = 10; // - - int FCONST_0 = 11; // - - int FCONST_1 = 12; // - - int FCONST_2 = 13; // - - int DCONST_0 = 14; // - - int DCONST_1 = 15; // - - int BIPUSH = 16; // visitIntInsn - int SIPUSH = 17; // - - int LDC = 18; // visitLdcInsn - // int LDC_W = 19; // - - // int LDC2_W = 20; // - - int ILOAD = 21; // visitVarInsn - int LLOAD = 22; // - - int FLOAD = 23; // - - int DLOAD = 24; // - - int ALOAD = 25; // - - // int ILOAD_0 = 26; // - - // int ILOAD_1 = 27; // - - // int ILOAD_2 = 28; // - - // int ILOAD_3 = 29; // - - // int LLOAD_0 = 30; // - - // int LLOAD_1 = 31; // - - // int LLOAD_2 = 32; // - - // int LLOAD_3 = 33; // - - // int FLOAD_0 = 34; // - - // int FLOAD_1 = 35; // - - // int FLOAD_2 = 36; // - - // int FLOAD_3 = 37; // - - // int DLOAD_0 = 38; // - - // int DLOAD_1 = 39; // - - // int DLOAD_2 = 40; // - - // int DLOAD_3 = 41; // - - // int ALOAD_0 = 42; // - - // int ALOAD_1 = 43; // - - // int ALOAD_2 = 44; // - - // int ALOAD_3 = 45; // - - int IALOAD = 46; // visitInsn - int LALOAD = 47; // - - int FALOAD = 48; // - - int DALOAD = 49; // - - int AALOAD = 50; // - - int BALOAD = 51; // - - int CALOAD = 52; // - - int SALOAD = 53; // - - int ISTORE = 54; // visitVarInsn - int LSTORE = 55; // - - int FSTORE = 56; // - - int DSTORE = 57; // - - int ASTORE = 58; // - - // int ISTORE_0 = 59; // - - // int ISTORE_1 = 60; // - - // int ISTORE_2 = 61; // - - // int ISTORE_3 = 62; // - - // int LSTORE_0 = 63; // - - // int LSTORE_1 = 64; // - - // int LSTORE_2 = 65; // - - // int LSTORE_3 = 66; // - - // int FSTORE_0 = 67; // - - // int FSTORE_1 = 68; // - - // int FSTORE_2 = 69; // - - // int FSTORE_3 = 70; // - - // int DSTORE_0 = 71; // - - // int DSTORE_1 = 72; // - - // int DSTORE_2 = 73; // - - // int DSTORE_3 = 74; // - - // int ASTORE_0 = 75; // - - // int ASTORE_1 = 76; // - - // int ASTORE_2 = 77; // - - // int ASTORE_3 = 78; // - - int IASTORE = 79; // visitInsn - int LASTORE = 80; // - - int FASTORE = 81; // - - int DASTORE = 82; // - - int AASTORE = 83; // - - int BASTORE = 84; // - - int CASTORE = 85; // - - int SASTORE = 86; // - - int POP = 87; // - - int POP2 = 88; // - - int DUP = 89; // - - int DUP_X1 = 90; // - - int DUP_X2 = 91; // - - int DUP2 = 92; // - - int DUP2_X1 = 93; // - - int DUP2_X2 = 94; // - - int SWAP = 95; // - - int IADD = 96; // - - int LADD = 97; // - - int FADD = 98; // - - int DADD = 99; // - - int ISUB = 100; // - - int LSUB = 101; // - - int FSUB = 102; // - - int DSUB = 103; // - - int IMUL = 104; // - - int LMUL = 105; // - - int FMUL = 106; // - - int DMUL = 107; // - - int IDIV = 108; // - - int LDIV = 109; // - - int FDIV = 110; // - - int DDIV = 111; // - - int IREM = 112; // - - int LREM = 113; // - - int FREM = 114; // - - int DREM = 115; // - - int INEG = 116; // - - int LNEG = 117; // - - int FNEG = 118; // - - int DNEG = 119; // - - int ISHL = 120; // - - int LSHL = 121; // - - int ISHR = 122; // - - int LSHR = 123; // - - int IUSHR = 124; // - - int LUSHR = 125; // - - int IAND = 126; // - - int LAND = 127; // - - int IOR = 128; // - - int LOR = 129; // - - int IXOR = 130; // - - int LXOR = 131; // - - int IINC = 132; // visitIincInsn - int I2L = 133; // visitInsn - int I2F = 134; // - - int I2D = 135; // - - int L2I = 136; // - - int L2F = 137; // - - int L2D = 138; // - - int F2I = 139; // - - int F2L = 140; // - - int F2D = 141; // - - int D2I = 142; // - - int D2L = 143; // - - int D2F = 144; // - - int I2B = 145; // - - int I2C = 146; // - - int I2S = 147; // - - int LCMP = 148; // - - int FCMPL = 149; // - - int FCMPG = 150; // - - int DCMPL = 151; // - - int DCMPG = 152; // - - int IFEQ = 153; // visitJumpInsn - int IFNE = 154; // - - int IFLT = 155; // - - int IFGE = 156; // - - int IFGT = 157; // - - int IFLE = 158; // - - int IF_ICMPEQ = 159; // - - int IF_ICMPNE = 160; // - - int IF_ICMPLT = 161; // - - int IF_ICMPGE = 162; // - - int IF_ICMPGT = 163; // - - int IF_ICMPLE = 164; // - - int IF_ACMPEQ = 165; // - - int IF_ACMPNE = 166; // - - int GOTO = 167; // - - int JSR = 168; // - - int RET = 169; // visitVarInsn - int TABLESWITCH = 170; // visiTableSwitchInsn - int LOOKUPSWITCH = 171; // visitLookupSwitch - int IRETURN = 172; // visitInsn - int LRETURN = 173; // - - int FRETURN = 174; // - - int DRETURN = 175; // - - int ARETURN = 176; // - - int RETURN = 177; // - - int GETSTATIC = 178; // visitFieldInsn - int PUTSTATIC = 179; // - - int GETFIELD = 180; // - - int PUTFIELD = 181; // - - int INVOKEVIRTUAL = 182; // visitMethodInsn - int INVOKESPECIAL = 183; // - - int INVOKESTATIC = 184; // - - int INVOKEINTERFACE = 185; // - - int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn - int NEW = 187; // visitTypeInsn - int NEWARRAY = 188; // visitIntInsn - int ANEWARRAY = 189; // visitTypeInsn - int ARRAYLENGTH = 190; // visitInsn - int ATHROW = 191; // - - int CHECKCAST = 192; // visitTypeInsn - int INSTANCEOF = 193; // - - int MONITORENTER = 194; // visitInsn - int MONITOREXIT = 195; // - - // int WIDE = 196; // NOT VISITED - int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn - int IFNULL = 198; // visitJumpInsn - int IFNONNULL = 199; // - - // int GOTO_W = 200; // - - // int JSR_W = 201; // - -} diff --git a/src/asm/scala/tools/asm/Type.java b/src/asm/scala/tools/asm/Type.java deleted file mode 100644 index c8f0048588..0000000000 --- a/src/asm/scala/tools/asm/Type.java +++ /dev/null @@ -1,896 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - -/** - * A Java field or method type. This class can be used to make it easier to - * manipulate type and method descriptors. - * - * @author Eric Bruneton - * @author Chris Nokleberg - */ -public class Type { - - /** - * The sort of the <tt>void</tt> type. See {@link #getSort getSort}. - */ - public static final int VOID = 0; - - /** - * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}. - */ - public static final int BOOLEAN = 1; - - /** - * The sort of the <tt>char</tt> type. See {@link #getSort getSort}. - */ - public static final int CHAR = 2; - - /** - * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}. - */ - public static final int BYTE = 3; - - /** - * The sort of the <tt>short</tt> type. See {@link #getSort getSort}. - */ - public static final int SHORT = 4; - - /** - * The sort of the <tt>int</tt> type. See {@link #getSort getSort}. - */ - public static final int INT = 5; - - /** - * The sort of the <tt>float</tt> type. See {@link #getSort getSort}. - */ - public static final int FLOAT = 6; - - /** - * The sort of the <tt>long</tt> type. See {@link #getSort getSort}. - */ - public static final int LONG = 7; - - /** - * The sort of the <tt>double</tt> type. See {@link #getSort getSort}. - */ - public static final int DOUBLE = 8; - - /** - * The sort of array reference types. See {@link #getSort getSort}. - */ - public static final int ARRAY = 9; - - /** - * The sort of object reference types. See {@link #getSort getSort}. - */ - public static final int OBJECT = 10; - - /** - * The sort of method types. See {@link #getSort getSort}. - */ - public static final int METHOD = 11; - - /** - * The <tt>void</tt> type. - */ - public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24) - | (5 << 16) | (0 << 8) | 0, 1); - - /** - * The <tt>boolean</tt> type. - */ - public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24) - | (0 << 16) | (5 << 8) | 1, 1); - - /** - * The <tt>char</tt> type. - */ - public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24) - | (0 << 16) | (6 << 8) | 1, 1); - - /** - * The <tt>byte</tt> type. - */ - public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24) - | (0 << 16) | (5 << 8) | 1, 1); - - /** - * The <tt>short</tt> type. - */ - public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24) - | (0 << 16) | (7 << 8) | 1, 1); - - /** - * The <tt>int</tt> type. - */ - public static final Type INT_TYPE = new Type(INT, null, ('I' << 24) - | (0 << 16) | (0 << 8) | 1, 1); - - /** - * The <tt>float</tt> type. - */ - public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24) - | (2 << 16) | (2 << 8) | 1, 1); - - /** - * The <tt>long</tt> type. - */ - public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24) - | (1 << 16) | (1 << 8) | 2, 1); - - /** - * The <tt>double</tt> type. - */ - public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24) - | (3 << 16) | (3 << 8) | 2, 1); - - // ------------------------------------------------------------------------ - // Fields - // ------------------------------------------------------------------------ - - /** - * The sort of this Java type. - */ - private final int sort; - - /** - * A buffer containing the internal name of this Java type. This field is - * only used for reference types. - */ - private final char[] buf; - - /** - * The offset of the internal name of this Java type in {@link #buf buf} or, - * for primitive types, the size, descriptor and getOpcode offsets for this - * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset - * for IALOAD or IASTORE, byte 3 the offset for all other instructions). - */ - private final int off; - - /** - * The length of the internal name of this Java type. - */ - private final int len; - - // ------------------------------------------------------------------------ - // Constructors - // ------------------------------------------------------------------------ - - /** - * Constructs a reference type. - * - * @param sort - * the sort of the reference type to be constructed. - * @param buf - * a buffer containing the descriptor of the previous type. - * @param off - * the offset of this descriptor in the previous buffer. - * @param len - * the length of this descriptor. - */ - private Type(final int sort, final char[] buf, final int off, final int len) { - this.sort = sort; - this.buf = buf; - this.off = off; - this.len = len; - } - - /** - * Returns the Java type corresponding to the given type descriptor. - * - * @param typeDescriptor - * a field or method type descriptor. - * @return the Java type corresponding to the given type descriptor. - */ - public static Type getType(final String typeDescriptor) { - return getType(typeDescriptor.toCharArray(), 0); - } - - /** - * Returns the Java type corresponding to the given internal name. - * - * @param internalName - * an internal name. - * @return the Java type corresponding to the given internal name. - */ - public static Type getObjectType(final String internalName) { - char[] buf = internalName.toCharArray(); - return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length); - } - - /** - * Returns the Java type corresponding to the given method descriptor. - * Equivalent to <code>Type.getType(methodDescriptor)</code>. - * - * @param methodDescriptor - * a method descriptor. - * @return the Java type corresponding to the given method descriptor. - */ - public static Type getMethodType(final String methodDescriptor) { - return getType(methodDescriptor.toCharArray(), 0); - } - - /** - * Returns the Java method type corresponding to the given argument and - * return types. - * - * @param returnType - * the return type of the method. - * @param argumentTypes - * the argument types of the method. - * @return the Java type corresponding to the given argument and return - * types. - */ - public static Type getMethodType(final Type returnType, - final Type... argumentTypes) { - return getType(getMethodDescriptor(returnType, argumentTypes)); - } - - /** - * Returns the Java type corresponding to the given class. - * - * @param c - * a class. - * @return the Java type corresponding to the given class. - */ - public static Type getType(final Class<?> c) { - if (c.isPrimitive()) { - if (c == Integer.TYPE) { - return INT_TYPE; - } else if (c == Void.TYPE) { - return VOID_TYPE; - } else if (c == Boolean.TYPE) { - return BOOLEAN_TYPE; - } else if (c == Byte.TYPE) { - return BYTE_TYPE; - } else if (c == Character.TYPE) { - return CHAR_TYPE; - } else if (c == Short.TYPE) { - return SHORT_TYPE; - } else if (c == Double.TYPE) { - return DOUBLE_TYPE; - } else if (c == Float.TYPE) { - return FLOAT_TYPE; - } else /* if (c == Long.TYPE) */{ - return LONG_TYPE; - } - } else { - return getType(getDescriptor(c)); - } - } - - /** - * Returns the Java method type corresponding to the given constructor. - * - * @param c - * a {@link Constructor Constructor} object. - * @return the Java method type corresponding to the given constructor. - */ - public static Type getType(final Constructor<?> c) { - return getType(getConstructorDescriptor(c)); - } - - /** - * Returns the Java method type corresponding to the given method. - * - * @param m - * a {@link Method Method} object. - * @return the Java method type corresponding to the given method. - */ - public static Type getType(final Method m) { - return getType(getMethodDescriptor(m)); - } - - /** - * Returns the Java types corresponding to the argument types of the given - * method descriptor. - * - * @param methodDescriptor - * a method descriptor. - * @return the Java types corresponding to the argument types of the given - * method descriptor. - */ - public static Type[] getArgumentTypes(final String methodDescriptor) { - char[] buf = methodDescriptor.toCharArray(); - int off = 1; - int size = 0; - while (true) { - char car = buf[off++]; - if (car == ')') { - break; - } else if (car == 'L') { - while (buf[off++] != ';') { - } - ++size; - } else if (car != '[') { - ++size; - } - } - Type[] args = new Type[size]; - off = 1; - size = 0; - while (buf[off] != ')') { - args[size] = getType(buf, off); - off += args[size].len + (args[size].sort == OBJECT ? 2 : 0); - size += 1; - } - return args; - } - - /** - * Returns the Java types corresponding to the argument types of the given - * method. - * - * @param method - * a method. - * @return the Java types corresponding to the argument types of the given - * method. - */ - public static Type[] getArgumentTypes(final Method method) { - Class<?>[] classes = method.getParameterTypes(); - Type[] types = new Type[classes.length]; - for (int i = classes.length - 1; i >= 0; --i) { - types[i] = getType(classes[i]); - } - return types; - } - - /** - * Returns the Java type corresponding to the return type of the given - * method descriptor. - * - * @param methodDescriptor - * a method descriptor. - * @return the Java type corresponding to the return type of the given - * method descriptor. - */ - public static Type getReturnType(final String methodDescriptor) { - char[] buf = methodDescriptor.toCharArray(); - return getType(buf, methodDescriptor.indexOf(')') + 1); - } - - /** - * Returns the Java type corresponding to the return type of the given - * method. - * - * @param method - * a method. - * @return the Java type corresponding to the return type of the given - * method. - */ - public static Type getReturnType(final Method method) { - return getType(method.getReturnType()); - } - - /** - * Computes the size of the arguments and of the return value of a method. - * - * @param desc - * the descriptor of a method. - * @return the size of the arguments of the method (plus one for the - * implicit this argument), argSize, and the size of its return - * value, retSize, packed into a single int i = - * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to - * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). - */ - public static int getArgumentsAndReturnSizes(final String desc) { - int n = 1; - int c = 1; - while (true) { - char car = desc.charAt(c++); - if (car == ')') { - car = desc.charAt(c); - return n << 2 - | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); - } else if (car == 'L') { - while (desc.charAt(c++) != ';') { - } - n += 1; - } else if (car == '[') { - while ((car = desc.charAt(c)) == '[') { - ++c; - } - if (car == 'D' || car == 'J') { - n -= 1; - } - } else if (car == 'D' || car == 'J') { - n += 2; - } else { - n += 1; - } - } - } - - /** - * Returns the Java type corresponding to the given type descriptor. For - * method descriptors, buf is supposed to contain nothing more than the - * descriptor itself. - * - * @param buf - * a buffer containing a type descriptor. - * @param off - * the offset of this descriptor in the previous buffer. - * @return the Java type corresponding to the given type descriptor. - */ - private static Type getType(final char[] buf, final int off) { - int len; - switch (buf[off]) { - case 'V': - return VOID_TYPE; - case 'Z': - return BOOLEAN_TYPE; - case 'C': - return CHAR_TYPE; - case 'B': - return BYTE_TYPE; - case 'S': - return SHORT_TYPE; - case 'I': - return INT_TYPE; - case 'F': - return FLOAT_TYPE; - case 'J': - return LONG_TYPE; - case 'D': - return DOUBLE_TYPE; - case '[': - len = 1; - while (buf[off + len] == '[') { - ++len; - } - if (buf[off + len] == 'L') { - ++len; - while (buf[off + len] != ';') { - ++len; - } - } - return new Type(ARRAY, buf, off, len + 1); - case 'L': - len = 1; - while (buf[off + len] != ';') { - ++len; - } - return new Type(OBJECT, buf, off + 1, len - 1); - // case '(': - default: - return new Type(METHOD, buf, off, buf.length - off); - } - } - - // ------------------------------------------------------------------------ - // Accessors - // ------------------------------------------------------------------------ - - /** - * Returns the sort of this Java type. - * - * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, - * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, - * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, - * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD - * METHOD}. - */ - public int getSort() { - return sort; - } - - /** - * Returns the number of dimensions of this array type. This method should - * only be used for an array type. - * - * @return the number of dimensions of this array type. - */ - public int getDimensions() { - int i = 1; - while (buf[off + i] == '[') { - ++i; - } - return i; - } - - /** - * Returns the type of the elements of this array type. This method should - * only be used for an array type. - * - * @return Returns the type of the elements of this array type. - */ - public Type getElementType() { - return getType(buf, off + getDimensions()); - } - - /** - * Returns the binary name of the class corresponding to this type. This - * method must not be used on method types. - * - * @return the binary name of the class corresponding to this type. - */ - public String getClassName() { - switch (sort) { - case VOID: - return "void"; - case BOOLEAN: - return "boolean"; - case CHAR: - return "char"; - case BYTE: - return "byte"; - case SHORT: - return "short"; - case INT: - return "int"; - case FLOAT: - return "float"; - case LONG: - return "long"; - case DOUBLE: - return "double"; - case ARRAY: - StringBuilder sb = new StringBuilder(getElementType().getClassName()); - for (int i = getDimensions(); i > 0; --i) { - sb.append("[]"); - } - return sb.toString(); - case OBJECT: - return new String(buf, off, len).replace('/', '.'); - default: - return null; - } - } - - /** - * Returns the internal name of the class corresponding to this object or - * array type. The internal name of a class is its fully qualified name (as - * returned by Class.getName(), where '.' are replaced by '/'. This method - * should only be used for an object or array type. - * - * @return the internal name of the class corresponding to this object type. - */ - public String getInternalName() { - return new String(buf, off, len); - } - - /** - * Returns the argument types of methods of this type. This method should - * only be used for method types. - * - * @return the argument types of methods of this type. - */ - public Type[] getArgumentTypes() { - return getArgumentTypes(getDescriptor()); - } - - /** - * Returns the return type of methods of this type. This method should only - * be used for method types. - * - * @return the return type of methods of this type. - */ - public Type getReturnType() { - return getReturnType(getDescriptor()); - } - - /** - * Returns the size of the arguments and of the return value of methods of - * this type. This method should only be used for method types. - * - * @return the size of the arguments (plus one for the implicit this - * argument), argSize, and the size of the return value, retSize, - * packed into a single - * int i = <tt>(argSize << 2) | retSize</tt> - * (argSize is therefore equal to <tt>i >> 2</tt>, - * and retSize to <tt>i & 0x03</tt>). - */ - public int getArgumentsAndReturnSizes() { - return getArgumentsAndReturnSizes(getDescriptor()); - } - - // ------------------------------------------------------------------------ - // Conversion to type descriptors - // ------------------------------------------------------------------------ - - /** - * Returns the descriptor corresponding to this Java type. - * - * @return the descriptor corresponding to this Java type. - */ - public String getDescriptor() { - StringBuffer buf = new StringBuffer(); - getDescriptor(buf); - return buf.toString(); - } - - /** - * Returns the descriptor corresponding to the given argument and return - * types. - * - * @param returnType - * the return type of the method. - * @param argumentTypes - * the argument types of the method. - * @return the descriptor corresponding to the given argument and return - * types. - */ - public static String getMethodDescriptor(final Type returnType, - final Type... argumentTypes) { - StringBuffer buf = new StringBuffer(); - buf.append('('); - for (int i = 0; i < argumentTypes.length; ++i) { - argumentTypes[i].getDescriptor(buf); - } - buf.append(')'); - returnType.getDescriptor(buf); - return buf.toString(); - } - - /** - * Appends the descriptor corresponding to this Java type to the given - * string buffer. - * - * @param buf - * the string buffer to which the descriptor must be appended. - */ - private void getDescriptor(final StringBuffer buf) { - if (this.buf == null) { - // descriptor is in byte 3 of 'off' for primitive types (buf == - // null) - buf.append((char) ((off & 0xFF000000) >>> 24)); - } else if (sort == OBJECT) { - buf.append('L'); - buf.append(this.buf, off, len); - buf.append(';'); - } else { // sort == ARRAY || sort == METHOD - buf.append(this.buf, off, len); - } - } - - // ------------------------------------------------------------------------ - // Direct conversion from classes to type descriptors, - // without intermediate Type objects - // ------------------------------------------------------------------------ - - /** - * Returns the internal name of the given class. The internal name of a - * class is its fully qualified name, as returned by Class.getName(), where - * '.' are replaced by '/'. - * - * @param c - * an object or array class. - * @return the internal name of the given class. - */ - public static String getInternalName(final Class<?> c) { - return c.getName().replace('.', '/'); - } - - /** - * Returns the descriptor corresponding to the given Java type. - * - * @param c - * an object class, a primitive class or an array class. - * @return the descriptor corresponding to the given class. - */ - public static String getDescriptor(final Class<?> c) { - StringBuffer buf = new StringBuffer(); - getDescriptor(buf, c); - return buf.toString(); - } - - /** - * Returns the descriptor corresponding to the given constructor. - * - * @param c - * a {@link Constructor Constructor} object. - * @return the descriptor of the given constructor. - */ - public static String getConstructorDescriptor(final Constructor<?> c) { - Class<?>[] parameters = c.getParameterTypes(); - StringBuffer buf = new StringBuffer(); - buf.append('('); - for (int i = 0; i < parameters.length; ++i) { - getDescriptor(buf, parameters[i]); - } - return buf.append(")V").toString(); - } - - /** - * Returns the descriptor corresponding to the given method. - * - * @param m - * a {@link Method Method} object. - * @return the descriptor of the given method. - */ - public static String getMethodDescriptor(final Method m) { - Class<?>[] parameters = m.getParameterTypes(); - StringBuffer buf = new StringBuffer(); - buf.append('('); - for (int i = 0; i < parameters.length; ++i) { - getDescriptor(buf, parameters[i]); - } - buf.append(')'); - getDescriptor(buf, m.getReturnType()); - return buf.toString(); - } - - /** - * Appends the descriptor of the given class to the given string buffer. - * - * @param buf - * the string buffer to which the descriptor must be appended. - * @param c - * the class whose descriptor must be computed. - */ - private static void getDescriptor(final StringBuffer buf, final Class<?> c) { - Class<?> d = c; - while (true) { - if (d.isPrimitive()) { - char car; - if (d == Integer.TYPE) { - car = 'I'; - } else if (d == Void.TYPE) { - car = 'V'; - } else if (d == Boolean.TYPE) { - car = 'Z'; - } else if (d == Byte.TYPE) { - car = 'B'; - } else if (d == Character.TYPE) { - car = 'C'; - } else if (d == Short.TYPE) { - car = 'S'; - } else if (d == Double.TYPE) { - car = 'D'; - } else if (d == Float.TYPE) { - car = 'F'; - } else /* if (d == Long.TYPE) */{ - car = 'J'; - } - buf.append(car); - return; - } else if (d.isArray()) { - buf.append('['); - d = d.getComponentType(); - } else { - buf.append('L'); - String name = d.getName(); - int len = name.length(); - for (int i = 0; i < len; ++i) { - char car = name.charAt(i); - buf.append(car == '.' ? '/' : car); - } - buf.append(';'); - return; - } - } - } - - // ------------------------------------------------------------------------ - // Corresponding size and opcodes - // ------------------------------------------------------------------------ - - /** - * Returns the size of values of this type. This method must not be used for - * method types. - * - * @return the size of values of this type, i.e., 2 for <tt>long</tt> and - * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise. - */ - public int getSize() { - // the size is in byte 0 of 'off' for primitive types (buf == null) - return buf == null ? (off & 0xFF) : 1; - } - - /** - * Returns a JVM instruction opcode adapted to this Java type. This method - * must not be used for method types. - * - * @param opcode - * a JVM instruction opcode. This opcode must be one of ILOAD, - * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, - * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. - * @return an opcode that is similar to the given opcode, but adapted to - * this Java type. For example, if this type is <tt>float</tt> and - * <tt>opcode</tt> is IRETURN, this method returns FRETURN. - */ - public int getOpcode(final int opcode) { - if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { - // the offset for IALOAD or IASTORE is in byte 1 of 'off' for - // primitive types (buf == null) - return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4); - } else { - // the offset for other instructions is in byte 2 of 'off' for - // primitive types (buf == null) - return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4); - } - } - - // ------------------------------------------------------------------------ - // Equals, hashCode and toString - // ------------------------------------------------------------------------ - - /** - * Tests if the given object is equal to this type. - * - * @param o - * the object to be compared to this type. - * @return <tt>true</tt> if the given object is equal to this type. - */ - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Type)) { - return false; - } - Type t = (Type) o; - if (sort != t.sort) { - return false; - } - if (sort >= ARRAY) { - if (len != t.len) { - return false; - } - for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { - if (buf[i] != t.buf[j]) { - return false; - } - } - } - return true; - } - - /** - * Returns a hash code value for this type. - * - * @return a hash code value for this type. - */ - @Override - public int hashCode() { - int hc = 13 * sort; - if (sort >= ARRAY) { - for (int i = off, end = i + len; i < end; i++) { - hc = 17 * (hc + buf[i]); - } - } - return hc; - } - - /** - * Returns a string representation of this type. - * - * @return the descriptor of this type. - */ - @Override - public String toString() { - return getDescriptor(); - } -} diff --git a/src/asm/scala/tools/asm/TypePath.java b/src/asm/scala/tools/asm/TypePath.java deleted file mode 100644 index d4c6f0d857..0000000000 --- a/src/asm/scala/tools/asm/TypePath.java +++ /dev/null @@ -1,193 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2013 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package scala.tools.asm; - -/** - * The path to a type argument, wildcard bound, array element type, or static - * inner type within an enclosing type. - * - * @author Eric Bruneton - */ -public class TypePath { - - /** - * A type path step that steps into the element type of an array type. See - * {@link #getStep getStep}. - */ - public final static int ARRAY_ELEMENT = 0; - - /** - * A type path step that steps into the nested type of a class type. See - * {@link #getStep getStep}. - */ - public final static int INNER_TYPE = 1; - - /** - * A type path step that steps into the bound of a wildcard type. See - * {@link #getStep getStep}. - */ - public final static int WILDCARD_BOUND = 2; - - /** - * A type path step that steps into a type argument of a generic type. See - * {@link #getStep getStep}. - */ - public final static int TYPE_ARGUMENT = 3; - - /** - * The byte array where the path is stored, in Java class file format. - */ - byte[] b; - - /** - * The offset of the first byte of the type path in 'b'. - */ - int offset; - - /** - * Creates a new type path. - * - * @param b - * the byte array containing the type path in Java class file - * format. - * @param offset - * the offset of the first byte of the type path in 'b'. - */ - TypePath(byte[] b, int offset) { - this.b = b; - this.offset = offset; - } - - /** - * Returns the length of this path. - * - * @return the length of this path. - */ - public int getLength() { - return b[offset]; - } - - /** - * Returns the value of the given step of this path. - * - * @param index - * an index between 0 and {@link #getLength()}, exclusive. - * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE - * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or - * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. - */ - public int getStep(int index) { - return b[offset + 2 * index + 1]; - } - - /** - * Returns the index of the type argument that the given step is stepping - * into. This method should only be used for steps whose value is - * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. - * - * @param index - * an index between 0 and {@link #getLength()}, exclusive. - * @return the index of the type argument that the given step is stepping - * into. - */ - public int getStepArgument(int index) { - return b[offset + 2 * index + 2]; - } - - /** - * Converts a type path in string form, in the format used by - * {@link #toString()}, into a TypePath object. - * - * @param typePath - * a type path in string form, in the format used by - * {@link #toString()}. May be null or empty. - * @return the corresponding TypePath object, or null if the path is empty. - */ - public static TypePath fromString(final String typePath) { - if (typePath == null || typePath.length() == 0) { - return null; - } - int n = typePath.length(); - ByteVector out = new ByteVector(n); - out.putByte(0); - for (int i = 0; i < n;) { - char c = typePath.charAt(i++); - if (c == '[') { - out.put11(ARRAY_ELEMENT, 0); - } else if (c == '.') { - out.put11(INNER_TYPE, 0); - } else if (c == '*') { - out.put11(WILDCARD_BOUND, 0); - } else if (c >= '0' && c <= '9') { - int typeArg = c - '0'; - while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') { - typeArg = typeArg * 10 + c - '0'; - i += 1; - } - out.put11(TYPE_ARGUMENT, typeArg); - } - } - out.data[0] = (byte) (out.length / 2); - return new TypePath(out.data, 0); - } - - /** - * Returns a string representation of this type path. {@link #ARRAY_ELEMENT - * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE - * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps - * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type - * argument index in decimal form. - */ - @Override - public String toString() { - int length = getLength(); - StringBuilder result = new StringBuilder(length * 2); - for (int i = 0; i < length; ++i) { - switch (getStep(i)) { - case ARRAY_ELEMENT: - result.append('['); - break; - case INNER_TYPE: - result.append('.'); - break; - case WILDCARD_BOUND: - result.append('*'); - break; - case TYPE_ARGUMENT: - result.append(getStepArgument(i)); - break; - default: - result.append('_'); - } - } - return result.toString(); - } -} diff --git a/src/asm/scala/tools/asm/TypeReference.java b/src/asm/scala/tools/asm/TypeReference.java deleted file mode 100644 index 118b0f6529..0000000000 --- a/src/asm/scala/tools/asm/TypeReference.java +++ /dev/null @@ -1,452 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2013 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package scala.tools.asm; - -/** - * A reference to a type appearing in a class, field or method declaration, or - * on an instruction. Such a reference designates the part of the class where - * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws' - * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable - * declaration, etc). - * - * @author Eric Bruneton - */ -public class TypeReference { - - /** - * The sort of type references that target a type parameter of a generic - * class. See {@link #getSort getSort}. - */ - public final static int CLASS_TYPE_PARAMETER = 0x00; - - /** - * The sort of type references that target a type parameter of a generic - * method. See {@link #getSort getSort}. - */ - public final static int METHOD_TYPE_PARAMETER = 0x01; - - /** - * The sort of type references that target the super class of a class or one - * of the interfaces it implements. See {@link #getSort getSort}. - */ - public final static int CLASS_EXTENDS = 0x10; - - /** - * The sort of type references that target a bound of a type parameter of a - * generic class. See {@link #getSort getSort}. - */ - public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11; - - /** - * The sort of type references that target a bound of a type parameter of a - * generic method. See {@link #getSort getSort}. - */ - public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12; - - /** - * The sort of type references that target the type of a field. See - * {@link #getSort getSort}. - */ - public final static int FIELD = 0x13; - - /** - * The sort of type references that target the return type of a method. See - * {@link #getSort getSort}. - */ - public final static int METHOD_RETURN = 0x14; - - /** - * The sort of type references that target the receiver type of a method. - * See {@link #getSort getSort}. - */ - public final static int METHOD_RECEIVER = 0x15; - - /** - * The sort of type references that target the type of a formal parameter of - * a method. See {@link #getSort getSort}. - */ - public final static int METHOD_FORMAL_PARAMETER = 0x16; - - /** - * The sort of type references that target the type of an exception declared - * in the throws clause of a method. See {@link #getSort getSort}. - */ - public final static int THROWS = 0x17; - - /** - * The sort of type references that target the type of a local variable in a - * method. See {@link #getSort getSort}. - */ - public final static int LOCAL_VARIABLE = 0x40; - - /** - * The sort of type references that target the type of a resource variable - * in a method. See {@link #getSort getSort}. - */ - public final static int RESOURCE_VARIABLE = 0x41; - - /** - * The sort of type references that target the type of the exception of a - * 'catch' clause in a method. See {@link #getSort getSort}. - */ - public final static int EXCEPTION_PARAMETER = 0x42; - - /** - * The sort of type references that target the type declared in an - * 'instanceof' instruction. See {@link #getSort getSort}. - */ - public final static int INSTANCEOF = 0x43; - - /** - * The sort of type references that target the type of the object created by - * a 'new' instruction. See {@link #getSort getSort}. - */ - public final static int NEW = 0x44; - - /** - * The sort of type references that target the receiver type of a - * constructor reference. See {@link #getSort getSort}. - */ - public final static int CONSTRUCTOR_REFERENCE = 0x45; - - /** - * The sort of type references that target the receiver type of a method - * reference. See {@link #getSort getSort}. - */ - public final static int METHOD_REFERENCE = 0x46; - - /** - * The sort of type references that target the type declared in an explicit - * or implicit cast instruction. See {@link #getSort getSort}. - */ - public final static int CAST = 0x47; - - /** - * The sort of type references that target a type parameter of a generic - * constructor in a constructor call. See {@link #getSort getSort}. - */ - public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; - - /** - * The sort of type references that target a type parameter of a generic - * method in a method call. See {@link #getSort getSort}. - */ - public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; - - /** - * The sort of type references that target a type parameter of a generic - * constructor in a constructor reference. See {@link #getSort getSort}. - */ - public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; - - /** - * The sort of type references that target a type parameter of a generic - * method in a method reference. See {@link #getSort getSort}. - */ - public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; - - /** - * The type reference value in Java class file format. - */ - private int value; - - /** - * Creates a new TypeReference. - * - * @param typeRef - * the int encoded value of the type reference, as received in a - * visit method related to type annotations, like - * visitTypeAnnotation. - */ - public TypeReference(int typeRef) { - this.value = typeRef; - } - - /** - * Returns a type reference of the given sort. - * - * @param sort - * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, - * {@link #METHOD_RECEIVER METHOD_RECEIVER}, - * {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, - * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, - * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, - * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or - * {@link #METHOD_REFERENCE METHOD_REFERENCE}. - * @return a type reference of the given sort. - */ - public static TypeReference newTypeReference(int sort) { - return new TypeReference(sort << 24); - } - - /** - * Returns a reference to a type parameter of a generic class or method. - * - * @param sort - * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. - * @param paramIndex - * the type parameter index. - * @return a reference to the given generic class or method type parameter. - */ - public static TypeReference newTypeParameterReference(int sort, - int paramIndex) { - return new TypeReference((sort << 24) | (paramIndex << 16)); - } - - /** - * Returns a reference to a type parameter bound of a generic class or - * method. - * - * @param sort - * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. - * @param paramIndex - * the type parameter index. - * @param boundIndex - * the type bound index within the above type parameters. - * @return a reference to the given generic class or method type parameter - * bound. - */ - public static TypeReference newTypeParameterBoundReference(int sort, - int paramIndex, int boundIndex) { - return new TypeReference((sort << 24) | (paramIndex << 16) - | (boundIndex << 8)); - } - - /** - * Returns a reference to the super class or to an interface of the - * 'implements' clause of a class. - * - * @param itfIndex - * the index of an interface in the 'implements' clause of a - * class, or -1 to reference the super class of the class. - * @return a reference to the given super type of a class. - */ - public static TypeReference newSuperTypeReference(int itfIndex) { - itfIndex &= 0xFFFF; - return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8)); - } - - /** - * Returns a reference to the type of a formal parameter of a method. - * - * @param paramIndex - * the formal parameter index. - * - * @return a reference to the type of the given method formal parameter. - */ - public static TypeReference newFormalParameterReference(int paramIndex) { - return new TypeReference((METHOD_FORMAL_PARAMETER << 24) - | (paramIndex << 16)); - } - - /** - * Returns a reference to the type of an exception, in a 'throws' clause of - * a method. - * - * @param exceptionIndex - * the index of an exception in a 'throws' clause of a method. - * - * @return a reference to the type of the given exception. - */ - public static TypeReference newExceptionReference(int exceptionIndex) { - return new TypeReference((THROWS << 24) | (exceptionIndex << 8)); - } - - /** - * Returns a reference to the type of the exception declared in a 'catch' - * clause of a method. - * - * @param tryCatchBlockIndex - * the index of a try catch block (using the order in which they - * are visited with visitTryCatchBlock). - * - * @return a reference to the type of the given exception. - */ - public static TypeReference newTryCatchReference(int tryCatchBlockIndex) { - return new TypeReference((EXCEPTION_PARAMETER << 24) - | (tryCatchBlockIndex << 8)); - } - - /** - * Returns a reference to the type of a type argument in a constructor or - * method call or reference. - * - * @param sort - * {@link #CAST CAST}, - * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link #METHOD_INVOCATION_TYPE_ARGUMENT - * METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link #METHOD_REFERENCE_TYPE_ARGUMENT - * METHOD_REFERENCE_TYPE_ARGUMENT}. - * @param argIndex - * the type argument index. - * - * @return a reference to the type of the given type argument. - */ - public static TypeReference newTypeArgumentReference(int sort, int argIndex) { - return new TypeReference((sort << 24) | argIndex); - } - - /** - * Returns the sort of this type reference. - * - * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, - * {@link #CLASS_EXTENDS CLASS_EXTENDS}, - * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND}, - * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}, - * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, - * {@link #METHOD_RECEIVER METHOD_RECEIVER}, - * {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}, - * {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, - * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, - * {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER}, - * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, - * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, - * {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST}, - * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link #METHOD_INVOCATION_TYPE_ARGUMENT - * METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link #METHOD_REFERENCE_TYPE_ARGUMENT - * METHOD_REFERENCE_TYPE_ARGUMENT}. - */ - public int getSort() { - return value >>> 24; - } - - /** - * Returns the index of the type parameter referenced by this type - * reference. This method must only be used for type references whose sort - * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, - * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or - * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. - * - * @return a type parameter index. - */ - public int getTypeParameterIndex() { - return (value & 0x00FF0000) >> 16; - } - - /** - * Returns the index of the type parameter bound, within the type parameter - * {@link #getTypeParameterIndex}, referenced by this type reference. This - * method must only be used for type references whose sort is - * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or - * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. - * - * @return a type parameter bound index. - */ - public int getTypeParameterBoundIndex() { - return (value & 0x0000FF00) >> 8; - } - - /** - * Returns the index of the "super type" of a class that is referenced by - * this type reference. This method must only be used for type references - * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}. - * - * @return the index of an interface in the 'implements' clause of a class, - * or -1 if this type reference references the type of the super - * class. - */ - public int getSuperTypeIndex() { - return (short) ((value & 0x00FFFF00) >> 8); - } - - /** - * Returns the index of the formal parameter whose type is referenced by - * this type reference. This method must only be used for type references - * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}. - * - * @return a formal parameter index. - */ - public int getFormalParameterIndex() { - return (value & 0x00FF0000) >> 16; - } - - /** - * Returns the index of the exception, in a 'throws' clause of a method, - * whose type is referenced by this type reference. This method must only be - * used for type references whose sort is {@link #THROWS THROWS}. - * - * @return the index of an exception in the 'throws' clause of a method. - */ - public int getExceptionIndex() { - return (value & 0x00FFFF00) >> 8; - } - - /** - * Returns the index of the try catch block (using the order in which they - * are visited with visitTryCatchBlock), whose 'catch' type is referenced by - * this type reference. This method must only be used for type references - * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} . - * - * @return the index of an exception in the 'throws' clause of a method. - */ - public int getTryCatchBlockIndex() { - return (value & 0x00FFFF00) >> 8; - } - - /** - * Returns the index of the type argument referenced by this type reference. - * This method must only be used for type references whose sort is - * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}. - * - * @return a type parameter index. - */ - public int getTypeArgumentIndex() { - return value & 0xFF; - } - - /** - * Returns the int encoded value of this type reference, suitable for use in - * visit methods related to type annotations, like visitTypeAnnotation. - * - * @return the int encoded value of this type reference. - */ - public int getValue() { - return value; - } -} diff --git a/src/asm/scala/tools/asm/commons/CodeSizeEvaluator.java b/src/asm/scala/tools/asm/commons/CodeSizeEvaluator.java deleted file mode 100644 index 80c07bdae0..0000000000 --- a/src/asm/scala/tools/asm/commons/CodeSizeEvaluator.java +++ /dev/null @@ -1,238 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.commons; - -import scala.tools.asm.Handle; -import scala.tools.asm.Label; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; - -/** - * A {@link MethodVisitor} that can be used to approximate method size. - * - * @author Eugene Kuleshov - */ -public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { - - private int minSize; - - private int maxSize; - - public CodeSizeEvaluator(final MethodVisitor mv) { - this(Opcodes.ASM5, mv); - } - - protected CodeSizeEvaluator(final int api, final MethodVisitor mv) { - super(api, mv); - } - - public int getMinSize() { - return this.minSize; - } - - public int getMaxSize() { - return this.maxSize; - } - - @Override - public void visitInsn(final int opcode) { - minSize += 1; - maxSize += 1; - if (mv != null) { - mv.visitInsn(opcode); - } - } - - @Override - public void visitIntInsn(final int opcode, final int operand) { - if (opcode == SIPUSH) { - minSize += 3; - maxSize += 3; - } else { - minSize += 2; - maxSize += 2; - } - if (mv != null) { - mv.visitIntInsn(opcode, operand); - } - } - - @Override - public void visitVarInsn(final int opcode, final int var) { - if (var < 4 && opcode != RET) { - minSize += 1; - maxSize += 1; - } else if (var >= 256) { - minSize += 4; - maxSize += 4; - } else { - minSize += 2; - maxSize += 2; - } - if (mv != null) { - mv.visitVarInsn(opcode, var); - } - } - - @Override - public void visitTypeInsn(final int opcode, final String type) { - minSize += 3; - maxSize += 3; - if (mv != null) { - mv.visitTypeInsn(opcode, type); - } - } - - @Override - public void visitFieldInsn(final int opcode, final String owner, - final String name, final String desc) { - minSize += 3; - maxSize += 3; - if (mv != null) { - mv.visitFieldInsn(opcode, owner, name, desc); - } - } - - @Deprecated - @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc) { - if (api >= Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc); - return; - } - doVisitMethodInsn(opcode, owner, name, desc, - opcode == Opcodes.INVOKEINTERFACE); - } - - @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc, final boolean itf) { - if (api < Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - doVisitMethodInsn(opcode, owner, name, desc, itf); - } - - private void doVisitMethodInsn(int opcode, final String owner, - final String name, final String desc, final boolean itf) { - if (opcode == INVOKEINTERFACE) { - minSize += 5; - maxSize += 5; - } else { - minSize += 3; - maxSize += 3; - } - if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc, itf); - } - } - - @Override - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, - Object... bsmArgs) { - minSize += 5; - maxSize += 5; - if (mv != null) { - mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); - } - } - - @Override - public void visitJumpInsn(final int opcode, final Label label) { - minSize += 3; - if (opcode == GOTO || opcode == JSR) { - maxSize += 5; - } else { - maxSize += 8; - } - if (mv != null) { - mv.visitJumpInsn(opcode, label); - } - } - - @Override - public void visitLdcInsn(final Object cst) { - if (cst instanceof Long || cst instanceof Double) { - minSize += 3; - maxSize += 3; - } else { - minSize += 2; - maxSize += 3; - } - if (mv != null) { - mv.visitLdcInsn(cst); - } - } - - @Override - public void visitIincInsn(final int var, final int increment) { - if (var > 255 || increment > 127 || increment < -128) { - minSize += 6; - maxSize += 6; - } else { - minSize += 3; - maxSize += 3; - } - if (mv != null) { - mv.visitIincInsn(var, increment); - } - } - - @Override - public void visitTableSwitchInsn(final int min, final int max, - final Label dflt, final Label... labels) { - minSize += 13 + labels.length * 4; - maxSize += 16 + labels.length * 4; - if (mv != null) { - mv.visitTableSwitchInsn(min, max, dflt, labels); - } - } - - @Override - public void visitLookupSwitchInsn(final Label dflt, final int[] keys, - final Label[] labels) { - minSize += 9 + keys.length * 8; - maxSize += 12 + keys.length * 8; - if (mv != null) { - mv.visitLookupSwitchInsn(dflt, keys, labels); - } - } - - @Override - public void visitMultiANewArrayInsn(final String desc, final int dims) { - minSize += 4; - maxSize += 4; - if (mv != null) { - mv.visitMultiANewArrayInsn(desc, dims); - } - } -} diff --git a/src/asm/scala/tools/asm/signature/SignatureReader.java b/src/asm/scala/tools/asm/signature/SignatureReader.java deleted file mode 100644 index 9c7c3880d9..0000000000 --- a/src/asm/scala/tools/asm/signature/SignatureReader.java +++ /dev/null @@ -1,228 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.signature; - -/** - * A type signature parser to make a signature visitor visit an existing - * signature. - * - * @author Thomas Hallgren - * @author Eric Bruneton - */ -public class SignatureReader { - - /** - * The signature to be read. - */ - private final String signature; - - /** - * Constructs a {@link SignatureReader} for the given signature. - * - * @param signature - * A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or - * <i>FieldTypeSignature</i>. - */ - public SignatureReader(final String signature) { - this.signature = signature; - } - - /** - * Makes the given visitor visit the signature of this - * {@link SignatureReader}. This signature is the one specified in the - * constructor (see {@link #SignatureReader(String) SignatureReader}). This - * method is intended to be called on a {@link SignatureReader} that was - * created using a <i>ClassSignature</i> (such as the <code>signature</code> - * parameter of the {@link scala.tools.asm.ClassVisitor#visit - * ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the - * <code>signature</code> parameter of the - * {@link scala.tools.asm.ClassVisitor#visitMethod - * ClassVisitor.visitMethod} method). - * - * @param v - * the visitor that must visit this signature. - */ - public void accept(final SignatureVisitor v) { - String signature = this.signature; - int len = signature.length(); - int pos; - char c; - - if (signature.charAt(0) == '<') { - pos = 2; - do { - int end = signature.indexOf(':', pos); - v.visitFormalTypeParameter(signature.substring(pos - 1, end)); - pos = end + 1; - - c = signature.charAt(pos); - if (c == 'L' || c == '[' || c == 'T') { - pos = parseType(signature, pos, v.visitClassBound()); - } - - while ((c = signature.charAt(pos++)) == ':') { - pos = parseType(signature, pos, v.visitInterfaceBound()); - } - } while (c != '>'); - } else { - pos = 0; - } - - if (signature.charAt(pos) == '(') { - pos++; - while (signature.charAt(pos) != ')') { - pos = parseType(signature, pos, v.visitParameterType()); - } - pos = parseType(signature, pos + 1, v.visitReturnType()); - while (pos < len) { - pos = parseType(signature, pos + 1, v.visitExceptionType()); - } - } else { - pos = parseType(signature, pos, v.visitSuperclass()); - while (pos < len) { - pos = parseType(signature, pos, v.visitInterface()); - } - } - } - - /** - * Makes the given visitor visit the signature of this - * {@link SignatureReader}. This signature is the one specified in the - * constructor (see {@link #SignatureReader(String) SignatureReader}). This - * method is intended to be called on a {@link SignatureReader} that was - * created using a <i>FieldTypeSignature</i>, such as the - * <code>signature</code> parameter of the - * {@link scala.tools.asm.ClassVisitor#visitField ClassVisitor.visitField} - * or {@link scala.tools.asm.MethodVisitor#visitLocalVariable - * MethodVisitor.visitLocalVariable} methods. - * - * @param v - * the visitor that must visit this signature. - */ - public void acceptType(final SignatureVisitor v) { - parseType(this.signature, 0, v); - } - - /** - * Parses a field type signature and makes the given visitor visit it. - * - * @param signature - * a string containing the signature that must be parsed. - * @param pos - * index of the first character of the signature to parsed. - * @param v - * the visitor that must visit this signature. - * @return the index of the first character after the parsed signature. - */ - private static int parseType(final String signature, int pos, - final SignatureVisitor v) { - char c; - int start, end; - boolean visited, inner; - String name; - - switch (c = signature.charAt(pos++)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - case 'F': - case 'J': - case 'D': - case 'V': - v.visitBaseType(c); - return pos; - - case '[': - return parseType(signature, pos, v.visitArrayType()); - - case 'T': - end = signature.indexOf(';', pos); - v.visitTypeVariable(signature.substring(pos, end)); - return end + 1; - - default: // case 'L': - start = pos; - visited = false; - inner = false; - for (;;) { - switch (c = signature.charAt(pos++)) { - case '.': - case ';': - if (!visited) { - name = signature.substring(start, pos - 1); - if (inner) { - v.visitInnerClassType(name); - } else { - v.visitClassType(name); - } - } - if (c == ';') { - v.visitEnd(); - return pos; - } - start = pos; - visited = false; - inner = true; - break; - - case '<': - name = signature.substring(start, pos - 1); - if (inner) { - v.visitInnerClassType(name); - } else { - v.visitClassType(name); - } - visited = true; - top: for (;;) { - switch (c = signature.charAt(pos)) { - case '>': - break top; - case '*': - ++pos; - v.visitTypeArgument(); - break; - case '+': - case '-': - pos = parseType(signature, pos + 1, - v.visitTypeArgument(c)); - break; - default: - pos = parseType(signature, pos, - v.visitTypeArgument('=')); - break; - } - } - } - } - } - } -} diff --git a/src/asm/scala/tools/asm/signature/SignatureVisitor.java b/src/asm/scala/tools/asm/signature/SignatureVisitor.java deleted file mode 100644 index 1e16bd3f7c..0000000000 --- a/src/asm/scala/tools/asm/signature/SignatureVisitor.java +++ /dev/null @@ -1,238 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.signature; - -import scala.tools.asm.Opcodes; - -/** - * A visitor to visit a generic signature. The methods of this interface must be - * called in one of the three following orders (the last one is the only valid - * order for a {@link SignatureVisitor} that is returned by a method of this - * interface): - * <ul> - * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt> - * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* ( - * <tt>visitSuperClass</tt> <tt>visitInterface</tt>* )</li> - * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt> - * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* ( - * <tt>visitParameterType</tt>* <tt>visitReturnType</tt> - * <tt>visitExceptionType</tt>* )</li> - * <li><i>TypeSignature</i> = <tt>visitBaseType</tt> | - * <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | ( - * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* ( - * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt> - * ) )</li> - * </ul> - * - * @author Thomas Hallgren - * @author Eric Bruneton - */ -public abstract class SignatureVisitor { - - /** - * Wildcard for an "extends" type argument. - */ - public final static char EXTENDS = '+'; - - /** - * Wildcard for a "super" type argument. - */ - public final static char SUPER = '-'; - - /** - * Wildcard for a normal type argument. - */ - public final static char INSTANCEOF = '='; - - /** - * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected final int api; - - /** - * Constructs a new {@link SignatureVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public SignatureVisitor(final int api) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { - throw new IllegalArgumentException(); - } - this.api = api; - } - - /** - * Visits a formal type parameter. - * - * @param name - * the name of the formal parameter. - */ - public void visitFormalTypeParameter(String name) { - } - - /** - * Visits the class bound of the last visited formal type parameter. - * - * @return a non null visitor to visit the signature of the class bound. - */ - public SignatureVisitor visitClassBound() { - return this; - } - - /** - * Visits an interface bound of the last visited formal type parameter. - * - * @return a non null visitor to visit the signature of the interface bound. - */ - public SignatureVisitor visitInterfaceBound() { - return this; - } - - /** - * Visits the type of the super class. - * - * @return a non null visitor to visit the signature of the super class - * type. - */ - public SignatureVisitor visitSuperclass() { - return this; - } - - /** - * Visits the type of an interface implemented by the class. - * - * @return a non null visitor to visit the signature of the interface type. - */ - public SignatureVisitor visitInterface() { - return this; - } - - /** - * Visits the type of a method parameter. - * - * @return a non null visitor to visit the signature of the parameter type. - */ - public SignatureVisitor visitParameterType() { - return this; - } - - /** - * Visits the return type of the method. - * - * @return a non null visitor to visit the signature of the return type. - */ - public SignatureVisitor visitReturnType() { - return this; - } - - /** - * Visits the type of a method exception. - * - * @return a non null visitor to visit the signature of the exception type. - */ - public SignatureVisitor visitExceptionType() { - return this; - } - - /** - * Visits a signature corresponding to a primitive type. - * - * @param descriptor - * the descriptor of the primitive type, or 'V' for <tt>void</tt> - * . - */ - public void visitBaseType(char descriptor) { - } - - /** - * Visits a signature corresponding to a type variable. - * - * @param name - * the name of the type variable. - */ - public void visitTypeVariable(String name) { - } - - /** - * Visits a signature corresponding to an array type. - * - * @return a non null visitor to visit the signature of the array element - * type. - */ - public SignatureVisitor visitArrayType() { - return this; - } - - /** - * Starts the visit of a signature corresponding to a class or interface - * type. - * - * @param name - * the internal name of the class or interface. - */ - public void visitClassType(String name) { - } - - /** - * Visits an inner class. - * - * @param name - * the local name of the inner class in its enclosing class. - */ - public void visitInnerClassType(String name) { - } - - /** - * Visits an unbounded type argument of the last visited class or inner - * class type. - */ - public void visitTypeArgument() { - } - - /** - * Visits a type argument of the last visited class or inner class type. - * - * @param wildcard - * '+', '-' or '='. - * @return a non null visitor to visit the signature of the type argument. - */ - public SignatureVisitor visitTypeArgument(char wildcard) { - return this; - } - - /** - * Ends the visit of a signature corresponding to a class or interface type. - */ - public void visitEnd() { - } -} diff --git a/src/asm/scala/tools/asm/signature/SignatureWriter.java b/src/asm/scala/tools/asm/signature/SignatureWriter.java deleted file mode 100644 index 65756eee51..0000000000 --- a/src/asm/scala/tools/asm/signature/SignatureWriter.java +++ /dev/null @@ -1,227 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.signature; - -import scala.tools.asm.Opcodes; - -/** - * A signature visitor that generates signatures in string format. - * - * @author Thomas Hallgren - * @author Eric Bruneton - */ -public class SignatureWriter extends SignatureVisitor { - - /** - * Buffer used to construct the signature. - */ - private final StringBuffer buf = new StringBuffer(); - - /** - * Indicates if the signature contains formal type parameters. - */ - private boolean hasFormals; - - /** - * Indicates if the signature contains method parameter types. - */ - private boolean hasParameters; - - /** - * Stack used to keep track of class types that have arguments. Each element - * of this stack is a boolean encoded in one bit. The top of the stack is - * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping = - * /2. - */ - private int argumentStack; - - /** - * Constructs a new {@link SignatureWriter} object. - */ - public SignatureWriter() { - super(Opcodes.ASM5); - } - - // ------------------------------------------------------------------------ - // Implementation of the SignatureVisitor interface - // ------------------------------------------------------------------------ - - @Override - public void visitFormalTypeParameter(final String name) { - if (!hasFormals) { - hasFormals = true; - buf.append('<'); - } - buf.append(name); - buf.append(':'); - } - - @Override - public SignatureVisitor visitClassBound() { - return this; - } - - @Override - public SignatureVisitor visitInterfaceBound() { - buf.append(':'); - return this; - } - - @Override - public SignatureVisitor visitSuperclass() { - endFormals(); - return this; - } - - @Override - public SignatureVisitor visitInterface() { - return this; - } - - @Override - public SignatureVisitor visitParameterType() { - endFormals(); - if (!hasParameters) { - hasParameters = true; - buf.append('('); - } - return this; - } - - @Override - public SignatureVisitor visitReturnType() { - endFormals(); - if (!hasParameters) { - buf.append('('); - } - buf.append(')'); - return this; - } - - @Override - public SignatureVisitor visitExceptionType() { - buf.append('^'); - return this; - } - - @Override - public void visitBaseType(final char descriptor) { - buf.append(descriptor); - } - - @Override - public void visitTypeVariable(final String name) { - buf.append('T'); - buf.append(name); - buf.append(';'); - } - - @Override - public SignatureVisitor visitArrayType() { - buf.append('['); - return this; - } - - @Override - public void visitClassType(final String name) { - buf.append('L'); - buf.append(name); - argumentStack *= 2; - } - - @Override - public void visitInnerClassType(final String name) { - endArguments(); - buf.append('.'); - buf.append(name); - argumentStack *= 2; - } - - @Override - public void visitTypeArgument() { - if (argumentStack % 2 == 0) { - ++argumentStack; - buf.append('<'); - } - buf.append('*'); - } - - @Override - public SignatureVisitor visitTypeArgument(final char wildcard) { - if (argumentStack % 2 == 0) { - ++argumentStack; - buf.append('<'); - } - if (wildcard != '=') { - buf.append(wildcard); - } - return this; - } - - @Override - public void visitEnd() { - endArguments(); - buf.append(';'); - } - - /** - * Returns the signature that was built by this signature writer. - * - * @return the signature that was built by this signature writer. - */ - @Override - public String toString() { - return buf.toString(); - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - /** - * Ends the formal type parameters section of the signature. - */ - private void endFormals() { - if (hasFormals) { - hasFormals = false; - buf.append('>'); - } - } - - /** - * Ends the type arguments of a class or inner class type. - */ - private void endArguments() { - if (argumentStack % 2 != 0) { - buf.append('>'); - } - argumentStack /= 2; - } -} diff --git a/src/asm/scala/tools/asm/tree/AbstractInsnNode.java b/src/asm/scala/tools/asm/tree/AbstractInsnNode.java deleted file mode 100644 index 2ce0c8b6ee..0000000000 --- a/src/asm/scala/tools/asm/tree/AbstractInsnNode.java +++ /dev/null @@ -1,326 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents a bytecode instruction. <i>An instruction can appear - * at most once in at most one {@link InsnList} at a time</i>. - * - * @author Eric Bruneton - */ -public abstract class AbstractInsnNode { - - /** - * The type of {@link InsnNode} instructions. - */ - public static final int INSN = 0; - - /** - * The type of {@link IntInsnNode} instructions. - */ - public static final int INT_INSN = 1; - - /** - * The type of {@link VarInsnNode} instructions. - */ - public static final int VAR_INSN = 2; - - /** - * The type of {@link TypeInsnNode} instructions. - */ - public static final int TYPE_INSN = 3; - - /** - * The type of {@link FieldInsnNode} instructions. - */ - public static final int FIELD_INSN = 4; - - /** - * The type of {@link MethodInsnNode} instructions. - */ - public static final int METHOD_INSN = 5; - - /** - * The type of {@link InvokeDynamicInsnNode} instructions. - */ - public static final int INVOKE_DYNAMIC_INSN = 6; - - /** - * The type of {@link JumpInsnNode} instructions. - */ - public static final int JUMP_INSN = 7; - - /** - * The type of {@link LabelNode} "instructions". - */ - public static final int LABEL = 8; - - /** - * The type of {@link LdcInsnNode} instructions. - */ - public static final int LDC_INSN = 9; - - /** - * The type of {@link IincInsnNode} instructions. - */ - public static final int IINC_INSN = 10; - - /** - * The type of {@link TableSwitchInsnNode} instructions. - */ - public static final int TABLESWITCH_INSN = 11; - - /** - * The type of {@link LookupSwitchInsnNode} instructions. - */ - public static final int LOOKUPSWITCH_INSN = 12; - - /** - * The type of {@link MultiANewArrayInsnNode} instructions. - */ - public static final int MULTIANEWARRAY_INSN = 13; - - /** - * The type of {@link FrameNode} "instructions". - */ - public static final int FRAME = 14; - - /** - * The type of {@link LineNumberNode} "instructions". - */ - public static final int LINE = 15; - - /** - * The opcode of this instruction. - */ - protected int opcode; - - /** - * The runtime visible type annotations of this instruction. This field is - * only used for real instructions (i.e. not for labels, frames, or line - * number nodes). This list is a list of {@link TypeAnnotationNode} objects. - * May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.TypeAnnotationNode - * @label visible - */ - public List<TypeAnnotationNode> visibleTypeAnnotations; - - /** - * The runtime invisible type annotations of this instruction. This field is - * only used for real instructions (i.e. not for labels, frames, or line - * number nodes). This list is a list of {@link TypeAnnotationNode} objects. - * May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.TypeAnnotationNode - * @label invisible - */ - public List<TypeAnnotationNode> invisibleTypeAnnotations; - - /** - * Previous instruction in the list to which this instruction belongs. - */ - AbstractInsnNode prev; - - /** - * Next instruction in the list to which this instruction belongs. - */ - AbstractInsnNode next; - - /** - * Index of this instruction in the list to which it belongs. The value of - * this field is correct only when {@link InsnList#cache} is not null. A - * value of -1 indicates that this instruction does not belong to any - * {@link InsnList}. - */ - int index; - - /** - * Constructs a new {@link AbstractInsnNode}. - * - * @param opcode - * the opcode of the instruction to be constructed. - */ - protected AbstractInsnNode(final int opcode) { - this.opcode = opcode; - this.index = -1; - } - - /** - * Returns the opcode of this instruction. - * - * @return the opcode of this instruction. - */ - public int getOpcode() { - return opcode; - } - - /** - * Returns the type of this instruction. - * - * @return the type of this instruction, i.e. one the constants defined in - * this class. - */ - public abstract int getType(); - - /** - * Returns the previous instruction in the list to which this instruction - * belongs, if any. - * - * @return the previous instruction in the list to which this instruction - * belongs, if any. May be <tt>null</tt>. - */ - public AbstractInsnNode getPrevious() { - return prev; - } - - /** - * Returns the next instruction in the list to which this instruction - * belongs, if any. - * - * @return the next instruction in the list to which this instruction - * belongs, if any. May be <tt>null</tt>. - */ - public AbstractInsnNode getNext() { - return next; - } - - /** - * Makes the given code visitor visit this instruction. - * - * @param cv - * a code visitor. - */ - public abstract void accept(final MethodVisitor cv); - - /** - * Makes the given visitor visit the annotations of this instruction. - * - * @param mv - * a method visitor. - */ - protected final void acceptAnnotations(final MethodVisitor mv) { - int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations - .size(); - for (int i = 0; i < n; ++i) { - TypeAnnotationNode an = visibleTypeAnnotations.get(i); - an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc, - true)); - } - n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations - .size(); - for (int i = 0; i < n; ++i) { - TypeAnnotationNode an = invisibleTypeAnnotations.get(i); - an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc, - false)); - } - } - - /** - * Returns a copy of this instruction. - * - * @param labels - * a map from LabelNodes to cloned LabelNodes. - * @return a copy of this instruction. The returned instruction does not - * belong to any {@link InsnList}. - */ - public abstract AbstractInsnNode clone( - final Map<LabelNode, LabelNode> labels); - - /** - * Returns the clone of the given label. - * - * @param label - * a label. - * @param map - * a map from LabelNodes to cloned LabelNodes. - * @return the clone of the given label. - */ - static LabelNode clone(final LabelNode label, - final Map<LabelNode, LabelNode> map) { - return map.get(label); - } - - /** - * Returns the clones of the given labels. - * - * @param labels - * a list of labels. - * @param map - * a map from LabelNodes to cloned LabelNodes. - * @return the clones of the given labels. - */ - static LabelNode[] clone(final List<LabelNode> labels, - final Map<LabelNode, LabelNode> map) { - LabelNode[] clones = new LabelNode[labels.size()]; - for (int i = 0; i < clones.length; ++i) { - clones[i] = map.get(labels.get(i)); - } - return clones; - } - - /** - * Clones the annotations of the given instruction into this instruction. - * - * @param insn - * the source instruction. - * @return this instruction. - */ - protected final AbstractInsnNode cloneAnnotations( - final AbstractInsnNode insn) { - if (insn.visibleTypeAnnotations != null) { - this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(); - for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) { - TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i); - TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef, - src.typePath, src.desc); - src.accept(ann); - this.visibleTypeAnnotations.add(ann); - } - } - if (insn.invisibleTypeAnnotations != null) { - this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(); - for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) { - TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i); - TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef, - src.typePath, src.desc); - src.accept(ann); - this.invisibleTypeAnnotations.add(ann); - } - } - return this; - } -} diff --git a/src/asm/scala/tools/asm/tree/AnnotationNode.java b/src/asm/scala/tools/asm/tree/AnnotationNode.java deleted file mode 100644 index b8d5988066..0000000000 --- a/src/asm/scala/tools/asm/tree/AnnotationNode.java +++ /dev/null @@ -1,231 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.ArrayList; -import java.util.List; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Opcodes; - -/** - * A node that represents an annotationn. - * - * @author Eric Bruneton - */ -public class AnnotationNode extends AnnotationVisitor { - - /** - * The class descriptor of the annotation class. - */ - public String desc; - - /** - * The name value pairs of this annotation. Each name value pair is stored - * as two consecutive elements in the list. The name is a {@link String}, - * and the value may be a {@link Byte}, {@link Boolean}, {@link Character}, - * {@link Short}, {@link Integer}, {@link Long}, {@link Float}, - * {@link Double}, {@link String} or {@link scala.tools.asm.Type}, or an - * two elements String array (for enumeration values), a - * {@link AnnotationNode}, or a {@link List} of values of one of the - * preceding types. The list may be <tt>null</tt> if there is no name value - * pair. - */ - public List<Object> values; - - /** - * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this - * constructor</i>. Instead, they must use the - * {@link #AnnotationNode(int, String)} version. - * - * @param desc - * the class descriptor of the annotation class. - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public AnnotationNode(final String desc) { - this(Opcodes.ASM5, desc); - if (getClass() != AnnotationNode.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs a new {@link AnnotationNode}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param desc - * the class descriptor of the annotation class. - */ - public AnnotationNode(final int api, final String desc) { - super(api); - this.desc = desc; - } - - /** - * Constructs a new {@link AnnotationNode} to visit an array value. - * - * @param values - * where the visited values must be stored. - */ - AnnotationNode(final List<Object> values) { - super(Opcodes.ASM5); - this.values = values; - } - - // ------------------------------------------------------------------------ - // Implementation of the AnnotationVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public void visit(final String name, final Object value) { - if (values == null) { - values = new ArrayList<Object>(this.desc != null ? 2 : 1); - } - if (this.desc != null) { - values.add(name); - } - values.add(value); - } - - @Override - public void visitEnum(final String name, final String desc, - final String value) { - if (values == null) { - values = new ArrayList<Object>(this.desc != null ? 2 : 1); - } - if (this.desc != null) { - values.add(name); - } - values.add(new String[] { desc, value }); - } - - @Override - public AnnotationVisitor visitAnnotation(final String name, - final String desc) { - if (values == null) { - values = new ArrayList<Object>(this.desc != null ? 2 : 1); - } - if (this.desc != null) { - values.add(name); - } - AnnotationNode annotation = new AnnotationNode(desc); - values.add(annotation); - return annotation; - } - - @Override - public AnnotationVisitor visitArray(final String name) { - if (values == null) { - values = new ArrayList<Object>(this.desc != null ? 2 : 1); - } - if (this.desc != null) { - values.add(name); - } - List<Object> array = new ArrayList<Object>(); - values.add(array); - return new AnnotationNode(array); - } - - @Override - public void visitEnd() { - } - - // ------------------------------------------------------------------------ - // Accept methods - // ------------------------------------------------------------------------ - - /** - * Checks that this annotation node is compatible with the given ASM API - * version. This methods checks that this node, and all its nodes - * recursively, do not contain elements that were introduced in more recent - * versions of the ASM API than the given version. - * - * @param api - * an ASM API version. Must be one of {@link Opcodes#ASM4} or - * {@link Opcodes#ASM5}. - */ - public void check(final int api) { - // nothing to do - } - - /** - * Makes the given visitor visit this annotation. - * - * @param av - * an annotation visitor. Maybe <tt>null</tt>. - */ - public void accept(final AnnotationVisitor av) { - if (av != null) { - if (values != null) { - for (int i = 0; i < values.size(); i += 2) { - String name = (String) values.get(i); - Object value = values.get(i + 1); - accept(av, name, value); - } - } - av.visitEnd(); - } - } - - /** - * Makes the given visitor visit a given annotation value. - * - * @param av - * an annotation visitor. Maybe <tt>null</tt>. - * @param name - * the value name. - * @param value - * the actual value. - */ - static void accept(final AnnotationVisitor av, final String name, - final Object value) { - if (av != null) { - if (value instanceof String[]) { - String[] typeconst = (String[]) value; - av.visitEnum(name, typeconst[0], typeconst[1]); - } else if (value instanceof AnnotationNode) { - AnnotationNode an = (AnnotationNode) value; - an.accept(av.visitAnnotation(name, an.desc)); - } else if (value instanceof List) { - AnnotationVisitor v = av.visitArray(name); - List<?> array = (List<?>) value; - for (int j = 0; j < array.size(); ++j) { - accept(v, null, array.get(j)); - } - v.visitEnd(); - } else { - av.visit(name, value); - } - } - } -} diff --git a/src/asm/scala/tools/asm/tree/ClassNode.java b/src/asm/scala/tools/asm/tree/ClassNode.java deleted file mode 100644 index 304b4ec9f5..0000000000 --- a/src/asm/scala/tools/asm/tree/ClassNode.java +++ /dev/null @@ -1,417 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Attribute; -import scala.tools.asm.ClassVisitor; -import scala.tools.asm.FieldVisitor; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.TypePath; - -/** - * A node that represents a class. - * - * @author Eric Bruneton - */ -public class ClassNode extends ClassVisitor { - - /** - * The class version. - */ - public int version; - - /** - * The class's access flags (see {@link scala.tools.asm.Opcodes}). This - * field also indicates if the class is deprecated. - */ - public int access; - - /** - * The internal name of the class (see - * {@link scala.tools.asm.Type#getInternalName() getInternalName}). - */ - public String name; - - /** - * The signature of the class. May be <tt>null</tt>. - */ - public String signature; - - /** - * The internal of name of the super class (see - * {@link scala.tools.asm.Type#getInternalName() getInternalName}). For - * interfaces, the super class is {@link Object}. May be <tt>null</tt>, but - * only for the {@link Object} class. - */ - public String superName; - - /** - * The internal names of the class's interfaces (see - * {@link scala.tools.asm.Type#getInternalName() getInternalName}). This - * list is a list of {@link String} objects. - */ - public List<String> interfaces; - - /** - * The name of the source file from which this class was compiled. May be - * <tt>null</tt>. - */ - public String sourceFile; - - /** - * Debug information to compute the correspondence between source and - * compiled elements of the class. May be <tt>null</tt>. - */ - public String sourceDebug; - - /** - * The internal name of the enclosing class of the class. May be - * <tt>null</tt>. - */ - public String outerClass; - - /** - * The name of the method that contains the class, or <tt>null</tt> if the - * class is not enclosed in a method. - */ - public String outerMethod; - - /** - * The descriptor of the method that contains the class, or <tt>null</tt> if - * the class is not enclosed in a method. - */ - public String outerMethodDesc; - - /** - * The runtime visible annotations of this class. This list is a list of - * {@link AnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.AnnotationNode - * @label visible - */ - public List<AnnotationNode> visibleAnnotations; - - /** - * The runtime invisible annotations of this class. This list is a list of - * {@link AnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.AnnotationNode - * @label invisible - */ - public List<AnnotationNode> invisibleAnnotations; - - /** - * The runtime visible type annotations of this class. This list is a list - * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.TypeAnnotationNode - * @label visible - */ - public List<TypeAnnotationNode> visibleTypeAnnotations; - - /** - * The runtime invisible type annotations of this class. This list is a list - * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.TypeAnnotationNode - * @label invisible - */ - public List<TypeAnnotationNode> invisibleTypeAnnotations; - - /** - * The non standard attributes of this class. This list is a list of - * {@link Attribute} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.Attribute - */ - public List<Attribute> attrs; - - /** - * Informations about the inner classes of this class. This list is a list - * of {@link InnerClassNode} objects. - * - * @associates scala.tools.asm.tree.InnerClassNode - */ - public List<InnerClassNode> innerClasses; - - /** - * The fields of this class. This list is a list of {@link FieldNode} - * objects. - * - * @associates scala.tools.asm.tree.FieldNode - */ - public List<FieldNode> fields; - - /** - * The methods of this class. This list is a list of {@link MethodNode} - * objects. - * - * @associates scala.tools.asm.tree.MethodNode - */ - public List<MethodNode> methods; - - /** - * Constructs a new {@link ClassNode}. <i>Subclasses must not use this - * constructor</i>. Instead, they must use the {@link #ClassNode(int)} - * version. - * - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public ClassNode() { - this(Opcodes.ASM5); - if (getClass() != ClassNode.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs a new {@link ClassNode}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public ClassNode(final int api) { - super(api); - this.interfaces = new ArrayList<String>(); - this.innerClasses = new ArrayList<InnerClassNode>(); - this.fields = new ArrayList<FieldNode>(); - this.methods = new ArrayList<MethodNode>(); - } - - // ------------------------------------------------------------------------ - // Implementation of the ClassVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public void visit(final int version, final int access, final String name, - final String signature, final String superName, - final String[] interfaces) { - this.version = version; - this.access = access; - this.name = name; - this.signature = signature; - this.superName = superName; - if (interfaces != null) { - this.interfaces.addAll(Arrays.asList(interfaces)); - } - } - - @Override - public void visitSource(final String file, final String debug) { - sourceFile = file; - sourceDebug = debug; - } - - @Override - public void visitOuterClass(final String owner, final String name, - final String desc) { - outerClass = owner; - outerMethod = name; - outerMethodDesc = desc; - } - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - AnnotationNode an = new AnnotationNode(desc); - if (visible) { - if (visibleAnnotations == null) { - visibleAnnotations = new ArrayList<AnnotationNode>(1); - } - visibleAnnotations.add(an); - } else { - if (invisibleAnnotations == null) { - invisibleAnnotations = new ArrayList<AnnotationNode>(1); - } - invisibleAnnotations.add(an); - } - return an; - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); - if (visible) { - if (visibleTypeAnnotations == null) { - visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); - } - visibleTypeAnnotations.add(an); - } else { - if (invisibleTypeAnnotations == null) { - invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); - } - invisibleTypeAnnotations.add(an); - } - return an; - } - - @Override - public void visitAttribute(final Attribute attr) { - if (attrs == null) { - attrs = new ArrayList<Attribute>(1); - } - attrs.add(attr); - } - - @Override - public void visitInnerClass(final String name, final String outerName, - final String innerName, final int access) { - InnerClassNode icn = new InnerClassNode(name, outerName, innerName, - access); - innerClasses.add(icn); - } - - @Override - public FieldVisitor visitField(final int access, final String name, - final String desc, final String signature, final Object value) { - FieldNode fn = new FieldNode(access, name, desc, signature, value); - fields.add(fn); - return fn; - } - - @Override - public MethodVisitor visitMethod(final int access, final String name, - final String desc, final String signature, final String[] exceptions) { - MethodNode mn = new MethodNode(access, name, desc, signature, - exceptions); - methods.add(mn); - return mn; - } - - @Override - public void visitEnd() { - } - - // ------------------------------------------------------------------------ - // Accept method - // ------------------------------------------------------------------------ - - /** - * Checks that this class node is compatible with the given ASM API version. - * This methods checks that this node, and all its nodes recursively, do not - * contain elements that were introduced in more recent versions of the ASM - * API than the given version. - * - * @param api - * an ASM API version. Must be one of {@link Opcodes#ASM4} or - * {@link Opcodes#ASM5}. - */ - public void check(final int api) { - if (api == Opcodes.ASM4) { - if (visibleTypeAnnotations != null - && visibleTypeAnnotations.size() > 0) { - throw new RuntimeException(); - } - if (invisibleTypeAnnotations != null - && invisibleTypeAnnotations.size() > 0) { - throw new RuntimeException(); - } - for (FieldNode f : fields) { - f.check(api); - } - for (MethodNode m : methods) { - m.check(api); - } - } - } - - /** - * Makes the given class visitor visit this class. - * - * @param cv - * a class visitor. - */ - public void accept(final ClassVisitor cv) { - // visits header - String[] interfaces = new String[this.interfaces.size()]; - this.interfaces.toArray(interfaces); - cv.visit(version, access, name, signature, superName, interfaces); - // visits source - if (sourceFile != null || sourceDebug != null) { - cv.visitSource(sourceFile, sourceDebug); - } - // visits outer class - if (outerClass != null) { - cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc); - } - // visits attributes - int i, n; - n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); - for (i = 0; i < n; ++i) { - AnnotationNode an = visibleAnnotations.get(i); - an.accept(cv.visitAnnotation(an.desc, true)); - } - n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); - for (i = 0; i < n; ++i) { - AnnotationNode an = invisibleAnnotations.get(i); - an.accept(cv.visitAnnotation(an.desc, false)); - } - n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); - for (i = 0; i < n; ++i) { - TypeAnnotationNode an = visibleTypeAnnotations.get(i); - an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, - true)); - } - n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations - .size(); - for (i = 0; i < n; ++i) { - TypeAnnotationNode an = invisibleTypeAnnotations.get(i); - an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, - false)); - } - n = attrs == null ? 0 : attrs.size(); - for (i = 0; i < n; ++i) { - cv.visitAttribute(attrs.get(i)); - } - // visits inner classes - for (i = 0; i < innerClasses.size(); ++i) { - innerClasses.get(i).accept(cv); - } - // visits fields - for (i = 0; i < fields.size(); ++i) { - fields.get(i).accept(cv); - } - // visits methods - for (i = 0; i < methods.size(); ++i) { - methods.get(i).accept(cv); - } - // visits end - cv.visitEnd(); - } -} diff --git a/src/asm/scala/tools/asm/tree/FieldInsnNode.java b/src/asm/scala/tools/asm/tree/FieldInsnNode.java deleted file mode 100644 index c027de109b..0000000000 --- a/src/asm/scala/tools/asm/tree/FieldInsnNode.java +++ /dev/null @@ -1,110 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents a field instruction. A field instruction is an - * instruction that loads or stores the value of a field of an object. - * - * @author Eric Bruneton - */ -public class FieldInsnNode extends AbstractInsnNode { - - /** - * The internal name of the field's owner class (see - * {@link scala.tools.asm.Type#getInternalName() getInternalName}). - */ - public String owner; - - /** - * The field's name. - */ - public String name; - - /** - * The field's descriptor (see {@link scala.tools.asm.Type}). - */ - public String desc; - - /** - * Constructs a new {@link FieldInsnNode}. - * - * @param opcode - * the opcode of the type instruction to be constructed. This - * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. - * @param owner - * the internal name of the field's owner class (see - * {@link scala.tools.asm.Type#getInternalName() - * getInternalName}). - * @param name - * the field's name. - * @param desc - * the field's descriptor (see {@link scala.tools.asm.Type}). - */ - public FieldInsnNode(final int opcode, final String owner, - final String name, final String desc) { - super(opcode); - this.owner = owner; - this.name = name; - this.desc = desc; - } - - /** - * Sets the opcode of this instruction. - * - * @param opcode - * the new instruction opcode. This opcode must be GETSTATIC, - * PUTSTATIC, GETFIELD or PUTFIELD. - */ - public void setOpcode(final int opcode) { - this.opcode = opcode; - } - - @Override - public int getType() { - return FIELD_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitFieldInsn(opcode, owner, name, desc); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new FieldInsnNode(opcode, owner, name, desc) - .cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/FieldNode.java b/src/asm/scala/tools/asm/tree/FieldNode.java deleted file mode 100644 index 3fb14dac4f..0000000000 --- a/src/asm/scala/tools/asm/tree/FieldNode.java +++ /dev/null @@ -1,307 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.ArrayList; -import java.util.List; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Attribute; -import scala.tools.asm.ClassVisitor; -import scala.tools.asm.FieldVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.TypePath; - -/** - * A node that represents a field. - * - * @author Eric Bruneton - */ -public class FieldNode extends FieldVisitor { - - /** - * The field's access flags (see {@link scala.tools.asm.Opcodes}). This - * field also indicates if the field is synthetic and/or deprecated. - */ - public int access; - - /** - * The field's name. - */ - public String name; - - /** - * The field's descriptor (see {@link scala.tools.asm.Type}). - */ - public String desc; - - /** - * The field's signature. May be <tt>null</tt>. - */ - public String signature; - - /** - * The field's initial value. This field, which may be <tt>null</tt> if the - * field does not have an initial value, must be an {@link Integer}, a - * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}. - */ - public Object value; - - /** - * The runtime visible annotations of this field. This list is a list of - * {@link AnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.AnnotationNode - * @label visible - */ - public List<AnnotationNode> visibleAnnotations; - - /** - * The runtime invisible annotations of this field. This list is a list of - * {@link AnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.AnnotationNode - * @label invisible - */ - public List<AnnotationNode> invisibleAnnotations; - - /** - * The runtime visible type annotations of this field. This list is a list - * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.TypeAnnotationNode - * @label visible - */ - public List<TypeAnnotationNode> visibleTypeAnnotations; - - /** - * The runtime invisible type annotations of this field. This list is a list - * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.TypeAnnotationNode - * @label invisible - */ - public List<TypeAnnotationNode> invisibleTypeAnnotations; - - /** - * The non standard attributes of this field. This list is a list of - * {@link Attribute} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.Attribute - */ - public List<Attribute> attrs; - - /** - * Constructs a new {@link FieldNode}. <i>Subclasses must not use this - * constructor</i>. Instead, they must use the - * {@link #FieldNode(int, int, String, String, String, Object)} version. - * - * @param access - * the field's access flags (see - * {@link scala.tools.asm.Opcodes}). This parameter also - * indicates if the field is synthetic and/or deprecated. - * @param name - * the field's name. - * @param desc - * the field's descriptor (see {@link scala.tools.asm.Type - * Type}). - * @param signature - * the field's signature. - * @param value - * the field's initial value. This parameter, which may be - * <tt>null</tt> if the field does not have an initial value, - * must be an {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double} or a {@link String}. - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public FieldNode(final int access, final String name, final String desc, - final String signature, final Object value) { - this(Opcodes.ASM5, access, name, desc, signature, value); - if (getClass() != FieldNode.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs a new {@link FieldNode}. <i>Subclasses must not use this - * constructor</i>. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param access - * the field's access flags (see - * {@link scala.tools.asm.Opcodes}). This parameter also - * indicates if the field is synthetic and/or deprecated. - * @param name - * the field's name. - * @param desc - * the field's descriptor (see {@link scala.tools.asm.Type - * Type}). - * @param signature - * the field's signature. - * @param value - * the field's initial value. This parameter, which may be - * <tt>null</tt> if the field does not have an initial value, - * must be an {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double} or a {@link String}. - */ - public FieldNode(final int api, final int access, final String name, - final String desc, final String signature, final Object value) { - super(api); - this.access = access; - this.name = name; - this.desc = desc; - this.signature = signature; - this.value = value; - } - - // ------------------------------------------------------------------------ - // Implementation of the FieldVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - AnnotationNode an = new AnnotationNode(desc); - if (visible) { - if (visibleAnnotations == null) { - visibleAnnotations = new ArrayList<AnnotationNode>(1); - } - visibleAnnotations.add(an); - } else { - if (invisibleAnnotations == null) { - invisibleAnnotations = new ArrayList<AnnotationNode>(1); - } - invisibleAnnotations.add(an); - } - return an; - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); - if (visible) { - if (visibleTypeAnnotations == null) { - visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); - } - visibleTypeAnnotations.add(an); - } else { - if (invisibleTypeAnnotations == null) { - invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); - } - invisibleTypeAnnotations.add(an); - } - return an; - } - - @Override - public void visitAttribute(final Attribute attr) { - if (attrs == null) { - attrs = new ArrayList<Attribute>(1); - } - attrs.add(attr); - } - - @Override - public void visitEnd() { - } - - // ------------------------------------------------------------------------ - // Accept methods - // ------------------------------------------------------------------------ - - /** - * Checks that this field node is compatible with the given ASM API version. - * This methods checks that this node, and all its nodes recursively, do not - * contain elements that were introduced in more recent versions of the ASM - * API than the given version. - * - * @param api - * an ASM API version. Must be one of {@link Opcodes#ASM4} or - * {@link Opcodes#ASM5}. - */ - public void check(final int api) { - if (api == Opcodes.ASM4) { - if (visibleTypeAnnotations != null - && visibleTypeAnnotations.size() > 0) { - throw new RuntimeException(); - } - if (invisibleTypeAnnotations != null - && invisibleTypeAnnotations.size() > 0) { - throw new RuntimeException(); - } - } - } - - /** - * Makes the given class visitor visit this field. - * - * @param cv - * a class visitor. - */ - public void accept(final ClassVisitor cv) { - FieldVisitor fv = cv.visitField(access, name, desc, signature, value); - if (fv == null) { - return; - } - int i, n; - n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); - for (i = 0; i < n; ++i) { - AnnotationNode an = visibleAnnotations.get(i); - an.accept(fv.visitAnnotation(an.desc, true)); - } - n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); - for (i = 0; i < n; ++i) { - AnnotationNode an = invisibleAnnotations.get(i); - an.accept(fv.visitAnnotation(an.desc, false)); - } - n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); - for (i = 0; i < n; ++i) { - TypeAnnotationNode an = visibleTypeAnnotations.get(i); - an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, - true)); - } - n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations - .size(); - for (i = 0; i < n; ++i) { - TypeAnnotationNode an = invisibleTypeAnnotations.get(i); - an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, - false)); - } - n = attrs == null ? 0 : attrs.size(); - for (i = 0; i < n; ++i) { - fv.visitAttribute(attrs.get(i)); - } - fv.visitEnd(); - } -} diff --git a/src/asm/scala/tools/asm/tree/FrameNode.java b/src/asm/scala/tools/asm/tree/FrameNode.java deleted file mode 100644 index f13fc66749..0000000000 --- a/src/asm/scala/tools/asm/tree/FrameNode.java +++ /dev/null @@ -1,210 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; - -/** - * A node that represents a stack map frame. These nodes are pseudo instruction - * nodes in order to be inserted in an instruction list. In fact these nodes - * must(*) be inserted <i>just before</i> any instruction node <b>i</b> that - * follows an unconditionnal branch instruction such as GOTO or THROW, that is - * the target of a jump instruction, or that starts an exception handler block. - * The stack map frame types must describe the values of the local variables and - * of the operand stack elements <i>just before</i> <b>i</b> is executed. <br> - * <br> - * (*) this is mandatory only for classes whose version is greater than or equal - * to {@link Opcodes#V1_6 V1_6}. - * - * @author Eric Bruneton - */ -public class FrameNode extends AbstractInsnNode { - - /** - * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded - * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, - * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or - * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames. - */ - public int type; - - /** - * The types of the local variables of this stack map frame. Elements of - * this list can be Integer, String or LabelNode objects (for primitive, - * reference and uninitialized types respectively - see - * {@link MethodVisitor}). - */ - public List<Object> local; - - /** - * The types of the operand stack elements of this stack map frame. Elements - * of this list can be Integer, String or LabelNode objects (for primitive, - * reference and uninitialized types respectively - see - * {@link MethodVisitor}). - */ - public List<Object> stack; - - private FrameNode() { - super(-1); - } - - /** - * Constructs a new {@link FrameNode}. - * - * @param type - * the type of this frame. Must be {@link Opcodes#F_NEW} for - * expanded frames, or {@link Opcodes#F_FULL}, - * {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, - * {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, - * {@link Opcodes#F_SAME1} for compressed frames. - * @param nLocal - * number of local variables of this stack map frame. - * @param local - * the types of the local variables of this stack map frame. - * Elements of this list can be Integer, String or LabelNode - * objects (for primitive, reference and uninitialized types - * respectively - see {@link MethodVisitor}). - * @param nStack - * number of operand stack elements of this stack map frame. - * @param stack - * the types of the operand stack elements of this stack map - * frame. Elements of this list can be Integer, String or - * LabelNode objects (for primitive, reference and uninitialized - * types respectively - see {@link MethodVisitor}). - */ - public FrameNode(final int type, final int nLocal, final Object[] local, - final int nStack, final Object[] stack) { - super(-1); - this.type = type; - switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - this.local = asList(nLocal, local); - this.stack = asList(nStack, stack); - break; - case Opcodes.F_APPEND: - this.local = asList(nLocal, local); - break; - case Opcodes.F_CHOP: - this.local = Arrays.asList(new Object[nLocal]); - break; - case Opcodes.F_SAME: - break; - case Opcodes.F_SAME1: - this.stack = asList(1, stack); - break; - } - } - - @Override - public int getType() { - return FRAME; - } - - /** - * Makes the given visitor visit this stack map frame. - * - * @param mv - * a method visitor. - */ - @Override - public void accept(final MethodVisitor mv) { - switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - mv.visitFrame(type, local.size(), asArray(local), stack.size(), - asArray(stack)); - break; - case Opcodes.F_APPEND: - mv.visitFrame(type, local.size(), asArray(local), 0, null); - break; - case Opcodes.F_CHOP: - mv.visitFrame(type, local.size(), null, 0, null); - break; - case Opcodes.F_SAME: - mv.visitFrame(type, 0, null, 0, null); - break; - case Opcodes.F_SAME1: - mv.visitFrame(type, 0, null, 1, asArray(stack)); - break; - } - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - FrameNode clone = new FrameNode(); - clone.type = type; - if (local != null) { - clone.local = new ArrayList<Object>(); - for (int i = 0; i < local.size(); ++i) { - Object l = local.get(i); - if (l instanceof LabelNode) { - l = labels.get(l); - } - clone.local.add(l); - } - } - if (stack != null) { - clone.stack = new ArrayList<Object>(); - for (int i = 0; i < stack.size(); ++i) { - Object s = stack.get(i); - if (s instanceof LabelNode) { - s = labels.get(s); - } - clone.stack.add(s); - } - } - return clone; - } - - // ------------------------------------------------------------------------ - - private static List<Object> asList(final int n, final Object[] o) { - return Arrays.asList(o).subList(0, n); - } - - private static Object[] asArray(final List<Object> l) { - Object[] objs = new Object[l.size()]; - for (int i = 0; i < objs.length; ++i) { - Object o = l.get(i); - if (o instanceof LabelNode) { - o = ((LabelNode) o).getLabel(); - } - objs[i] = o; - } - return objs; - } -} diff --git a/src/asm/scala/tools/asm/tree/IincInsnNode.java b/src/asm/scala/tools/asm/tree/IincInsnNode.java deleted file mode 100644 index c37ac91c27..0000000000 --- a/src/asm/scala/tools/asm/tree/IincInsnNode.java +++ /dev/null @@ -1,83 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; - -/** - * A node that represents an IINC instruction. - * - * @author Eric Bruneton - */ -public class IincInsnNode extends AbstractInsnNode { - - /** - * Index of the local variable to be incremented. - */ - public int var; - - /** - * Amount to increment the local variable by. - */ - public int incr; - - /** - * Constructs a new {@link IincInsnNode}. - * - * @param var - * index of the local variable to be incremented. - * @param incr - * increment amount to increment the local variable by. - */ - public IincInsnNode(final int var, final int incr) { - super(Opcodes.IINC); - this.var = var; - this.incr = incr; - } - - @Override - public int getType() { - return IINC_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitIincInsn(var, incr); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new IincInsnNode(var, incr).cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/InnerClassNode.java b/src/asm/scala/tools/asm/tree/InnerClassNode.java deleted file mode 100644 index aa3810c759..0000000000 --- a/src/asm/scala/tools/asm/tree/InnerClassNode.java +++ /dev/null @@ -1,101 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import scala.tools.asm.ClassVisitor; - -/** - * A node that represents an inner class. - * - * @author Eric Bruneton - */ -public class InnerClassNode { - - /** - * The internal name of an inner class (see - * {@link scala.tools.asm.Type#getInternalName() getInternalName}). - */ - public String name; - - /** - * The internal name of the class to which the inner class belongs (see - * {@link scala.tools.asm.Type#getInternalName() getInternalName}). May be - * <tt>null</tt>. - */ - public String outerName; - - /** - * The (simple) name of the inner class inside its enclosing class. May be - * <tt>null</tt> for anonymous inner classes. - */ - public String innerName; - - /** - * The access flags of the inner class as originally declared in the - * enclosing class. - */ - public int access; - - /** - * Constructs a new {@link InnerClassNode}. - * - * @param name - * the internal name of an inner class (see - * {@link scala.tools.asm.Type#getInternalName() - * getInternalName}). - * @param outerName - * the internal name of the class to which the inner class - * belongs (see {@link scala.tools.asm.Type#getInternalName() - * getInternalName}). May be <tt>null</tt>. - * @param innerName - * the (simple) name of the inner class inside its enclosing - * class. May be <tt>null</tt> for anonymous inner classes. - * @param access - * the access flags of the inner class as originally declared in - * the enclosing class. - */ - public InnerClassNode(final String name, final String outerName, - final String innerName, final int access) { - this.name = name; - this.outerName = outerName; - this.innerName = innerName; - this.access = access; - } - - /** - * Makes the given class visitor visit this inner class. - * - * @param cv - * a class visitor. - */ - public void accept(final ClassVisitor cv) { - cv.visitInnerClass(name, outerName, innerName, access); - } -} diff --git a/src/asm/scala/tools/asm/tree/InsnList.java b/src/asm/scala/tools/asm/tree/InsnList.java deleted file mode 100644 index e808712e78..0000000000 --- a/src/asm/scala/tools/asm/tree/InsnList.java +++ /dev/null @@ -1,622 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.ListIterator; -import java.util.NoSuchElementException; - -import scala.tools.asm.MethodVisitor; - -/** - * A doubly linked list of {@link AbstractInsnNode} objects. <i>This - * implementation is not thread safe</i>. - */ -public class InsnList { - - /** - * The number of instructions in this list. - */ - private int size; - - /** - * The first instruction in this list. May be <tt>null</tt>. - */ - private AbstractInsnNode first; - - /** - * The last instruction in this list. May be <tt>null</tt>. - */ - private AbstractInsnNode last; - - /** - * A cache of the instructions of this list. This cache is used to improve - * the performance of the {@link #get} method. - */ - AbstractInsnNode[] cache; - - /** - * Returns the number of instructions in this list. - * - * @return the number of instructions in this list. - */ - public int size() { - return size; - } - - /** - * Returns the first instruction in this list. - * - * @return the first instruction in this list, or <tt>null</tt> if the list - * is empty. - */ - public AbstractInsnNode getFirst() { - return first; - } - - /** - * Returns the last instruction in this list. - * - * @return the last instruction in this list, or <tt>null</tt> if the list - * is empty. - */ - public AbstractInsnNode getLast() { - return last; - } - - /** - * Returns the instruction whose index is given. This method builds a cache - * of the instructions in this list to avoid scanning the whole list each - * time it is called. Once the cache is built, this method run in constant - * time. This cache is invalidated by all the methods that modify the list. - * - * @param index - * the index of the instruction that must be returned. - * @return the instruction whose index is given. - * @throws IndexOutOfBoundsException - * if (index < 0 || index >= size()). - */ - public AbstractInsnNode get(final int index) { - if (index < 0 || index >= size) { - throw new IndexOutOfBoundsException(); - } - if (cache == null) { - cache = toArray(); - } - return cache[index]; - } - - /** - * Returns <tt>true</tt> if the given instruction belongs to this list. This - * method always scans the instructions of this list until it finds the - * given instruction or reaches the end of the list. - * - * @param insn - * an instruction. - * @return <tt>true</tt> if the given instruction belongs to this list. - */ - public boolean contains(final AbstractInsnNode insn) { - AbstractInsnNode i = first; - while (i != null && i != insn) { - i = i.next; - } - return i != null; - } - - /** - * Returns the index of the given instruction in this list. This method - * builds a cache of the instruction indexes to avoid scanning the whole - * list each time it is called. Once the cache is built, this method run in - * constant time. The cache is invalidated by all the methods that modify - * the list. - * - * @param insn - * an instruction <i>of this list</i>. - * @return the index of the given instruction in this list. <i>The result of - * this method is undefined if the given instruction does not belong - * to this list</i>. Use {@link #contains contains} to test if an - * instruction belongs to an instruction list or not. - */ - public int indexOf(final AbstractInsnNode insn) { - if (cache == null) { - cache = toArray(); - } - return insn.index; - } - - /** - * Makes the given visitor visit all of the instructions in this list. - * - * @param mv - * the method visitor that must visit the instructions. - */ - public void accept(final MethodVisitor mv) { - AbstractInsnNode insn = first; - while (insn != null) { - insn.accept(mv); - insn = insn.next; - } - } - - /** - * Returns an iterator over the instructions in this list. - * - * @return an iterator over the instructions in this list. - */ - public ListIterator<AbstractInsnNode> iterator() { - return iterator(0); - } - - /** - * Returns an iterator over the instructions in this list. - * - * @return an iterator over the instructions in this list. - */ - @SuppressWarnings("unchecked") - public ListIterator<AbstractInsnNode> iterator(int index) { - return new InsnListIterator(index); - } - - /** - * Returns an array containing all of the instructions in this list. - * - * @return an array containing all of the instructions in this list. - */ - public AbstractInsnNode[] toArray() { - int i = 0; - AbstractInsnNode elem = first; - AbstractInsnNode[] insns = new AbstractInsnNode[size]; - while (elem != null) { - insns[i] = elem; - elem.index = i++; - elem = elem.next; - } - return insns; - } - - /** - * Replaces an instruction of this list with another instruction. - * - * @param location - * an instruction <i>of this list</i>. - * @param insn - * another instruction, <i>which must not belong to any - * {@link InsnList}</i>. - */ - public void set(final AbstractInsnNode location, final AbstractInsnNode insn) { - AbstractInsnNode next = location.next; - insn.next = next; - if (next != null) { - next.prev = insn; - } else { - last = insn; - } - AbstractInsnNode prev = location.prev; - insn.prev = prev; - if (prev != null) { - prev.next = insn; - } else { - first = insn; - } - if (cache != null) { - int index = location.index; - cache[index] = insn; - insn.index = index; - } else { - insn.index = 0; // insn now belongs to an InsnList - } - location.index = -1; // i no longer belongs to an InsnList - location.prev = null; - location.next = null; - } - - /** - * Adds the given instruction to the end of this list. - * - * @param insn - * an instruction, <i>which must not belong to any - * {@link InsnList}</i>. - */ - public void add(final AbstractInsnNode insn) { - if(insn.prev != null || insn.next != null) { - // Adding an instruction that still refers to others (in the same or another InsnList) leads to hard to debug bugs. - // Initially everything may look ok (e.g. iteration follows `next` thus a stale `prev` isn't noticed). - // However, a stale link brings the doubly-linked into disarray e.g. upon removing an element, - // which results in the `next` of a stale `prev` being updated, among other failure scenarios. - // Better fail early. - throw new RuntimeException("Instruction " + insn + " already belongs to some InsnList."); - } - ++size; - if (last == null) { - first = insn; - last = insn; - } else { - last.next = insn; - insn.prev = last; - } - last = insn; - cache = null; - insn.index = 0; // insn now belongs to an InsnList - } - - /** - * Adds the given instructions to the end of this list. - * - * @param insns - * an instruction list, which is cleared during the process. This - * list must be different from 'this'. - */ - public void add(final InsnList insns) { - if (insns.size == 0) { - return; - } - size += insns.size; - if (last == null) { - first = insns.first; - last = insns.last; - } else { - AbstractInsnNode elem = insns.first; - last.next = elem; - elem.prev = last; - last = insns.last; - } - cache = null; - insns.removeAll(false); - } - - /** - * Inserts the given instruction at the begining of this list. - * - * @param insn - * an instruction, <i>which must not belong to any - * {@link InsnList}</i>. - */ - public void insert(final AbstractInsnNode insn) { - ++size; - if (first == null) { - first = insn; - last = insn; - } else { - first.prev = insn; - insn.next = first; - } - first = insn; - cache = null; - insn.index = 0; // insn now belongs to an InsnList - } - - /** - * Inserts the given instructions at the begining of this list. - * - * @param insns - * an instruction list, which is cleared during the process. This - * list must be different from 'this'. - */ - public void insert(final InsnList insns) { - if (insns.size == 0) { - return; - } - size += insns.size; - if (first == null) { - first = insns.first; - last = insns.last; - } else { - AbstractInsnNode elem = insns.last; - first.prev = elem; - elem.next = first; - first = insns.first; - } - cache = null; - insns.removeAll(false); - } - - /** - * Inserts the given instruction after the specified instruction. - * - * @param location - * an instruction <i>of this list</i> after which insn must be - * inserted. - * @param insn - * the instruction to be inserted, <i>which must not belong to - * any {@link InsnList}</i>. - */ - public void insert(final AbstractInsnNode location, - final AbstractInsnNode insn) { - ++size; - AbstractInsnNode next = location.next; - if (next == null) { - last = insn; - } else { - next.prev = insn; - } - location.next = insn; - insn.next = next; - insn.prev = location; - cache = null; - insn.index = 0; // insn now belongs to an InsnList - } - - /** - * Inserts the given instructions after the specified instruction. - * - * @param location - * an instruction <i>of this list</i> after which the - * instructions must be inserted. - * @param insns - * the instruction list to be inserted, which is cleared during - * the process. This list must be different from 'this'. - */ - public void insert(final AbstractInsnNode location, final InsnList insns) { - if (insns.size == 0) { - return; - } - size += insns.size; - AbstractInsnNode ifirst = insns.first; - AbstractInsnNode ilast = insns.last; - AbstractInsnNode next = location.next; - if (next == null) { - last = ilast; - } else { - next.prev = ilast; - } - location.next = ifirst; - ilast.next = next; - ifirst.prev = location; - cache = null; - insns.removeAll(false); - } - - /** - * Inserts the given instruction before the specified instruction. - * - * @param location - * an instruction <i>of this list</i> before which insn must be - * inserted. - * @param insn - * the instruction to be inserted, <i>which must not belong to - * any {@link InsnList}</i>. - */ - public void insertBefore(final AbstractInsnNode location, - final AbstractInsnNode insn) { - ++size; - AbstractInsnNode prev = location.prev; - if (prev == null) { - first = insn; - } else { - prev.next = insn; - } - location.prev = insn; - insn.next = location; - insn.prev = prev; - cache = null; - insn.index = 0; // insn now belongs to an InsnList - } - - /** - * Inserts the given instructions before the specified instruction. - * - * @param location - * an instruction <i>of this list</i> before which the - * instructions must be inserted. - * @param insns - * the instruction list to be inserted, which is cleared during - * the process. This list must be different from 'this'. - */ - public void insertBefore(final AbstractInsnNode location, - final InsnList insns) { - if (insns.size == 0) { - return; - } - size += insns.size; - AbstractInsnNode ifirst = insns.first; - AbstractInsnNode ilast = insns.last; - AbstractInsnNode prev = location.prev; - if (prev == null) { - first = ifirst; - } else { - prev.next = ifirst; - } - location.prev = ilast; - ilast.next = location; - ifirst.prev = prev; - cache = null; - insns.removeAll(false); - } - - /** - * Removes the given instruction from this list. - * - * @param insn - * the instruction <i>of this list</i> that must be removed. - */ - public void remove(final AbstractInsnNode insn) { - --size; - AbstractInsnNode next = insn.next; - AbstractInsnNode prev = insn.prev; - if (next == null) { - if (prev == null) { - first = null; - last = null; - } else { - prev.next = null; - last = prev; - } - } else { - if (prev == null) { - first = next; - next.prev = null; - } else { - prev.next = next; - next.prev = prev; - } - } - cache = null; - insn.index = -1; // insn no longer belongs to an InsnList - insn.prev = null; - insn.next = null; - } - - /** - * Removes all of the instructions of this list. - * - * @param mark - * if the instructions must be marked as no longer belonging to - * any {@link InsnList}. - */ - void removeAll(final boolean mark) { - if (mark) { - AbstractInsnNode insn = first; - while (insn != null) { - AbstractInsnNode next = insn.next; - insn.index = -1; // insn no longer belongs to an InsnList - insn.prev = null; - insn.next = null; - insn = next; - } - } - size = 0; - first = null; - last = null; - cache = null; - } - - /** - * Removes all of the instructions of this list. - */ - public void clear() { - removeAll(false); - } - - /** - * Reset all labels in the instruction list. This method should be called - * before reusing same instructions list between several - * <code>ClassWriter</code>s. - */ - public void resetLabels() { - AbstractInsnNode insn = first; - while (insn != null) { - if (insn instanceof LabelNode) { - ((LabelNode) insn).resetLabel(); - } - insn = insn.next; - } - } - - // this class is not generified because it will create bridges - private final class InsnListIterator implements ListIterator { - - AbstractInsnNode next; - - AbstractInsnNode prev; - - AbstractInsnNode remove; - - InsnListIterator(int index) { - if (index == size()) { - next = null; - prev = getLast(); - } else { - next = get(index); - prev = next.prev; - } - } - - public boolean hasNext() { - return next != null; - } - - public Object next() { - if (next == null) { - throw new NoSuchElementException(); - } - AbstractInsnNode result = next; - prev = result; - next = result.next; - remove = result; - return result; - } - - public void remove() { - if (remove != null) { - if (remove == next) { - next = next.next; - } else { - prev = prev.prev; - } - InsnList.this.remove(remove); - remove = null; - } else { - throw new IllegalStateException(); - } - } - - public boolean hasPrevious() { - return prev != null; - } - - public Object previous() { - AbstractInsnNode result = prev; - next = result; - prev = result.prev; - remove = result; - return result; - } - - public int nextIndex() { - if (next == null) { - return size(); - } - if (cache == null) { - cache = toArray(); - } - return next.index; - } - - public int previousIndex() { - if (prev == null) { - return -1; - } - if (cache == null) { - cache = toArray(); - } - return prev.index; - } - - public void add(Object o) { - InsnList.this.insertBefore(next, (AbstractInsnNode) o); - prev = (AbstractInsnNode) o; - remove = null; - } - - public void set(Object o) { - InsnList.this.set(next.prev, (AbstractInsnNode) o); - prev = (AbstractInsnNode) o; - } - } -} diff --git a/src/asm/scala/tools/asm/tree/InsnNode.java b/src/asm/scala/tools/asm/tree/InsnNode.java deleted file mode 100644 index f5313929ee..0000000000 --- a/src/asm/scala/tools/asm/tree/InsnNode.java +++ /dev/null @@ -1,88 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents a zero operand instruction. - * - * @author Eric Bruneton - */ -public class InsnNode extends AbstractInsnNode { - - /** - * Constructs a new {@link InsnNode}. - * - * @param opcode - * the opcode of the instruction to be constructed. This opcode - * must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, - * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, - * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, - * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, - * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, - * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, - * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, - * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, - * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, - * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, - * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, - * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, - * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, - * or MONITOREXIT. - */ - public InsnNode(final int opcode) { - super(opcode); - } - - @Override - public int getType() { - return INSN; - } - - /** - * Makes the given visitor visit this instruction. - * - * @param mv - * a method visitor. - */ - @Override - public void accept(final MethodVisitor mv) { - mv.visitInsn(opcode); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new InsnNode(opcode).cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/IntInsnNode.java b/src/asm/scala/tools/asm/tree/IntInsnNode.java deleted file mode 100644 index 6bbe8d845c..0000000000 --- a/src/asm/scala/tools/asm/tree/IntInsnNode.java +++ /dev/null @@ -1,88 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents an instruction with a single int operand. - * - * @author Eric Bruneton - */ -public class IntInsnNode extends AbstractInsnNode { - - /** - * The operand of this instruction. - */ - public int operand; - - /** - * Constructs a new {@link IntInsnNode}. - * - * @param opcode - * the opcode of the instruction to be constructed. This opcode - * must be BIPUSH, SIPUSH or NEWARRAY. - * @param operand - * the operand of the instruction to be constructed. - */ - public IntInsnNode(final int opcode, final int operand) { - super(opcode); - this.operand = operand; - } - - /** - * Sets the opcode of this instruction. - * - * @param opcode - * the new instruction opcode. This opcode must be BIPUSH, SIPUSH - * or NEWARRAY. - */ - public void setOpcode(final int opcode) { - this.opcode = opcode; - } - - @Override - public int getType() { - return INT_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitIntInsn(opcode, operand); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new IntInsnNode(opcode, operand).cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/InvokeDynamicInsnNode.java b/src/asm/scala/tools/asm/tree/InvokeDynamicInsnNode.java deleted file mode 100644 index 0f85e60291..0000000000 --- a/src/asm/scala/tools/asm/tree/InvokeDynamicInsnNode.java +++ /dev/null @@ -1,102 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.Handle; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; - -/** - * A node that represents an invokedynamic instruction. - * - * @author Remi Forax - */ -public class InvokeDynamicInsnNode extends AbstractInsnNode { - - /** - * Invokedynamic name. - */ - public String name; - - /** - * Invokedynamic descriptor. - */ - public String desc; - - /** - * Bootstrap method - */ - public Handle bsm; - - /** - * Bootstrap constant arguments - */ - public Object[] bsmArgs; - - /** - * Constructs a new {@link InvokeDynamicInsnNode}. - * - * @param name - * invokedynamic name. - * @param desc - * invokedynamic descriptor (see {@link scala.tools.asm.Type}). - * @param bsm - * the bootstrap method. - * @param bsmArgs - * the boostrap constant arguments. - */ - public InvokeDynamicInsnNode(final String name, final String desc, - final Handle bsm, final Object... bsmArgs) { - super(Opcodes.INVOKEDYNAMIC); - this.name = name; - this.desc = desc; - this.bsm = bsm; - this.bsmArgs = bsmArgs; - } - - @Override - public int getType() { - return INVOKE_DYNAMIC_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs) - .cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/JumpInsnNode.java b/src/asm/scala/tools/asm/tree/JumpInsnNode.java deleted file mode 100644 index 8b8a769204..0000000000 --- a/src/asm/scala/tools/asm/tree/JumpInsnNode.java +++ /dev/null @@ -1,97 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents a jump instruction. A jump instruction is an - * instruction that may jump to another instruction. - * - * @author Eric Bruneton - */ -public class JumpInsnNode extends AbstractInsnNode { - - /** - * The operand of this instruction. This operand is a label that designates - * the instruction to which this instruction may jump. - */ - public LabelNode label; - - /** - * Constructs a new {@link JumpInsnNode}. - * - * @param opcode - * the opcode of the type instruction to be constructed. This - * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, - * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, - * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. - * @param label - * the operand of the instruction to be constructed. This operand - * is a label that designates the instruction to which the jump - * instruction may jump. - */ - public JumpInsnNode(final int opcode, final LabelNode label) { - super(opcode); - this.label = label; - } - - /** - * Sets the opcode of this instruction. - * - * @param opcode - * the new instruction opcode. This opcode must be IFEQ, IFNE, - * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, - * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, - * JSR, IFNULL or IFNONNULL. - */ - public void setOpcode(final int opcode) { - this.opcode = opcode; - } - - @Override - public int getType() { - return JUMP_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitJumpInsn(opcode, label.getLabel()); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new JumpInsnNode(opcode, clone(label, labels)) - .cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/LabelNode.java b/src/asm/scala/tools/asm/tree/LabelNode.java deleted file mode 100644 index 44c48c1160..0000000000 --- a/src/asm/scala/tools/asm/tree/LabelNode.java +++ /dev/null @@ -1,78 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.Label; -import scala.tools.asm.MethodVisitor; - -/** - * An {@link AbstractInsnNode} that encapsulates a {@link Label}. - */ -public class LabelNode extends AbstractInsnNode { - - private Label label; - - public LabelNode() { - super(-1); - } - - public LabelNode(final Label label) { - super(-1); - this.label = label; - } - - @Override - public int getType() { - return LABEL; - } - - public Label getLabel() { - if (label == null) { - label = new Label(); - } - return label; - } - - @Override - public void accept(final MethodVisitor cv) { - cv.visitLabel(getLabel()); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return labels.get(this); - } - - public void resetLabel() { - label = null; - } -} diff --git a/src/asm/scala/tools/asm/tree/LdcInsnNode.java b/src/asm/scala/tools/asm/tree/LdcInsnNode.java deleted file mode 100644 index 1cc850bb31..0000000000 --- a/src/asm/scala/tools/asm/tree/LdcInsnNode.java +++ /dev/null @@ -1,79 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; - -/** - * A node that represents an LDC instruction. - * - * @author Eric Bruneton - */ -public class LdcInsnNode extends AbstractInsnNode { - - /** - * The constant to be loaded on the stack. This parameter must be a non null - * {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a - * {@link String} or a {@link scala.tools.asm.Type}. - */ - public Object cst; - - /** - * Constructs a new {@link LdcInsnNode}. - * - * @param cst - * the constant to be loaded on the stack. This parameter must be - * a non null {@link Integer}, a {@link Float}, a {@link Long}, a - * {@link Double} or a {@link String}. - */ - public LdcInsnNode(final Object cst) { - super(Opcodes.LDC); - this.cst = cst; - } - - @Override - public int getType() { - return LDC_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitLdcInsn(cst); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new LdcInsnNode(cst).cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/LineNumberNode.java b/src/asm/scala/tools/asm/tree/LineNumberNode.java deleted file mode 100644 index 9947aa70a9..0000000000 --- a/src/asm/scala/tools/asm/tree/LineNumberNode.java +++ /dev/null @@ -1,84 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents a line number declaration. These nodes are pseudo - * instruction nodes in order to be inserted in an instruction list. - * - * @author Eric Bruneton - */ -public class LineNumberNode extends AbstractInsnNode { - - /** - * A line number. This number refers to the source file from which the class - * was compiled. - */ - public int line; - - /** - * The first instruction corresponding to this line number. - */ - public LabelNode start; - - /** - * Constructs a new {@link LineNumberNode}. - * - * @param line - * a line number. This number refers to the source file from - * which the class was compiled. - * @param start - * the first instruction corresponding to this line number. - */ - public LineNumberNode(final int line, final LabelNode start) { - super(-1); - this.line = line; - this.start = start; - } - - @Override - public int getType() { - return LINE; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitLineNumber(line, start.getLabel()); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new LineNumberNode(line, clone(start, labels)); - } -} diff --git a/src/asm/scala/tools/asm/tree/LocalVariableAnnotationNode.java b/src/asm/scala/tools/asm/tree/LocalVariableAnnotationNode.java deleted file mode 100644 index d05b808171..0000000000 --- a/src/asm/scala/tools/asm/tree/LocalVariableAnnotationNode.java +++ /dev/null @@ -1,157 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package scala.tools.asm.tree; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import scala.tools.asm.Label; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.TypePath; -import scala.tools.asm.TypeReference; - -/** - * A node that represents a type annotation on a local or resource variable. - * - * @author Eric Bruneton - */ -public class LocalVariableAnnotationNode extends TypeAnnotationNode { - - /** - * The fist instructions corresponding to the continuous ranges that make - * the scope of this local variable (inclusive). Must not be <tt>null</tt>. - */ - public List<LabelNode> start; - - /** - * The last instructions corresponding to the continuous ranges that make - * the scope of this local variable (exclusive). This list must have the - * same size as the 'start' list. Must not be <tt>null</tt>. - */ - public List<LabelNode> end; - - /** - * The local variable's index in each range. This list must have the same - * size as the 'start' list. Must not be <tt>null</tt>. - */ - public List<Integer> index; - - /** - * Constructs a new {@link LocalVariableAnnotationNode}. <i>Subclasses must - * not use this constructor</i>. Instead, they must use the - * {@link #LocalVariableAnnotationNode(int, TypePath, LabelNode[], LabelNode[], int[], String)} - * version. - * - * @param typeRef - * a reference to the annotated type. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param start - * the fist instructions corresponding to the continuous ranges - * that make the scope of this local variable (inclusive). - * @param end - * the last instructions corresponding to the continuous ranges - * that make the scope of this local variable (exclusive). This - * array must have the same size as the 'start' array. - * @param index - * the local variable's index in each range. This array must have - * the same size as the 'start' array. - * @param desc - * the class descriptor of the annotation class. - */ - public LocalVariableAnnotationNode(int typeRef, TypePath typePath, - LabelNode[] start, LabelNode[] end, int[] index, String desc) { - this(Opcodes.ASM5, typeRef, typePath, start, end, index, desc); - } - - /** - * Constructs a new {@link LocalVariableAnnotationNode}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param typeRef - * a reference to the annotated type. See {@link TypeReference}. - * @param start - * the fist instructions corresponding to the continuous ranges - * that make the scope of this local variable (inclusive). - * @param end - * the last instructions corresponding to the continuous ranges - * that make the scope of this local variable (exclusive). This - * array must have the same size as the 'start' array. - * @param index - * the local variable's index in each range. This array must have - * the same size as the 'start' array. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - */ - public LocalVariableAnnotationNode(int api, int typeRef, TypePath typePath, - LabelNode[] start, LabelNode[] end, int[] index, String desc) { - super(api, typeRef, typePath, desc); - this.start = new ArrayList<LabelNode>(start.length); - this.start.addAll(Arrays.asList(start)); - this.end = new ArrayList<LabelNode>(end.length); - this.end.addAll(Arrays.asList(end)); - this.index = new ArrayList<Integer>(index.length); - for (int i : index) { - this.index.add(i); - } - } - - /** - * Makes the given visitor visit this type annotation. - * - * @param mv - * the visitor that must visit this annotation. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - */ - public void accept(final MethodVisitor mv, boolean visible) { - Label[] start = new Label[this.start.size()]; - Label[] end = new Label[this.end.size()]; - int[] index = new int[this.index.size()]; - for (int i = 0; i < start.length; ++i) { - start[i] = this.start.get(i).getLabel(); - end[i] = this.end.get(i).getLabel(); - index[i] = this.index.get(i); - } - accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end, - index, desc, true)); - } -} diff --git a/src/asm/scala/tools/asm/tree/LocalVariableNode.java b/src/asm/scala/tools/asm/tree/LocalVariableNode.java deleted file mode 100644 index 0d8e27356f..0000000000 --- a/src/asm/scala/tools/asm/tree/LocalVariableNode.java +++ /dev/null @@ -1,112 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents a local variable declaration. - * - * @author Eric Bruneton - */ -public class LocalVariableNode { - - /** - * The name of a local variable. - */ - public String name; - - /** - * The type descriptor of this local variable. - */ - public String desc; - - /** - * The signature of this local variable. May be <tt>null</tt>. - */ - public String signature; - - /** - * The first instruction corresponding to the scope of this local variable - * (inclusive). - */ - public LabelNode start; - - /** - * The last instruction corresponding to the scope of this local variable - * (exclusive). - */ - public LabelNode end; - - /** - * The local variable's index. - */ - public int index; - - /** - * Constructs a new {@link LocalVariableNode}. - * - * @param name - * the name of a local variable. - * @param desc - * the type descriptor of this local variable. - * @param signature - * the signature of this local variable. May be <tt>null</tt>. - * @param start - * the first instruction corresponding to the scope of this local - * variable (inclusive). - * @param end - * the last instruction corresponding to the scope of this local - * variable (exclusive). - * @param index - * the local variable's index. - */ - public LocalVariableNode(final String name, final String desc, - final String signature, final LabelNode start, final LabelNode end, - final int index) { - this.name = name; - this.desc = desc; - this.signature = signature; - this.start = start; - this.end = end; - this.index = index; - } - - /** - * Makes the given visitor visit this local variable declaration. - * - * @param mv - * a method visitor. - */ - public void accept(final MethodVisitor mv) { - mv.visitLocalVariable(name, desc, signature, start.getLabel(), - end.getLabel(), index); - } -} diff --git a/src/asm/scala/tools/asm/tree/LookupSwitchInsnNode.java b/src/asm/scala/tools/asm/tree/LookupSwitchInsnNode.java deleted file mode 100644 index 7db2f53ff4..0000000000 --- a/src/asm/scala/tools/asm/tree/LookupSwitchInsnNode.java +++ /dev/null @@ -1,118 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import scala.tools.asm.Label; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; - -/** - * A node that represents a LOOKUPSWITCH instruction. - * - * @author Eric Bruneton - */ -public class LookupSwitchInsnNode extends AbstractInsnNode { - - /** - * Beginning of the default handler block. - */ - public LabelNode dflt; - - /** - * The values of the keys. This list is a list of {@link Integer} objects. - */ - public List<Integer> keys; - - /** - * Beginnings of the handler blocks. This list is a list of - * {@link LabelNode} objects. - */ - public List<LabelNode> labels; - - /** - * Constructs a new {@link LookupSwitchInsnNode}. - * - * @param dflt - * beginning of the default handler block. - * @param keys - * the values of the keys. - * @param labels - * beginnings of the handler blocks. <tt>labels[i]</tt> is the - * beginning of the handler block for the <tt>keys[i]</tt> key. - */ - public LookupSwitchInsnNode(final LabelNode dflt, final int[] keys, - final LabelNode[] labels) { - super(Opcodes.LOOKUPSWITCH); - this.dflt = dflt; - this.keys = new ArrayList<Integer>(keys == null ? 0 : keys.length); - this.labels = new ArrayList<LabelNode>(labels == null ? 0 - : labels.length); - if (keys != null) { - for (int i = 0; i < keys.length; ++i) { - this.keys.add(new Integer(keys[i])); - } - } - if (labels != null) { - this.labels.addAll(Arrays.asList(labels)); - } - } - - @Override - public int getType() { - return LOOKUPSWITCH_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - int[] keys = new int[this.keys.size()]; - for (int i = 0; i < keys.length; ++i) { - keys[i] = this.keys.get(i).intValue(); - } - Label[] labels = new Label[this.labels.size()]; - for (int i = 0; i < labels.length; ++i) { - labels[i] = this.labels.get(i).getLabel(); - } - mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt, - labels), null, clone(this.labels, labels)); - clone.keys.addAll(keys); - return clone.cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/MethodInsnNode.java b/src/asm/scala/tools/asm/tree/MethodInsnNode.java deleted file mode 100644 index 30c7854646..0000000000 --- a/src/asm/scala/tools/asm/tree/MethodInsnNode.java +++ /dev/null @@ -1,141 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; - -/** - * A node that represents a method instruction. A method instruction is an - * instruction that invokes a method. - * - * @author Eric Bruneton - */ -public class MethodInsnNode extends AbstractInsnNode { - - /** - * The internal name of the method's owner class (see - * {@link scala.tools.asm.Type#getInternalName() getInternalName}). - * For methods of arrays, e.g., clone(), the array type descriptor. - */ - public String owner; - - /** - * The method's name. - */ - public String name; - - /** - * The method's descriptor (see {@link scala.tools.asm.Type}). - */ - public String desc; - - /** - * If the method's owner class if an interface. - */ - public boolean itf; - - /** - * Constructs a new {@link MethodInsnNode}. - * - * @param opcode - * the opcode of the type instruction to be constructed. This - * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or - * INVOKEINTERFACE. - * @param owner - * the internal name of the method's owner class (see - * {@link scala.tools.asm.Type#getInternalName() - * getInternalName}). - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link scala.tools.asm.Type}). - */ - @Deprecated - public MethodInsnNode(final int opcode, final String owner, - final String name, final String desc) { - this(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE); - } - - /** - * Constructs a new {@link MethodInsnNode}. - * - * @param opcode - * the opcode of the type instruction to be constructed. This - * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or - * INVOKEINTERFACE. - * @param owner - * the internal name of the method's owner class (see - * {@link scala.tools.asm.Type#getInternalName() - * getInternalName}). - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link scala.tools.asm.Type}). - * @param itf - * if the method's owner class is an interface. - */ - public MethodInsnNode(final int opcode, final String owner, - final String name, final String desc, final boolean itf) { - super(opcode); - this.owner = owner; - this.name = name; - this.desc = desc; - this.itf = itf; - } - - /** - * Sets the opcode of this instruction. - * - * @param opcode - * the new instruction opcode. This opcode must be INVOKEVIRTUAL, - * INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE. - */ - public void setOpcode(final int opcode) { - this.opcode = opcode; - } - - @Override - public int getType() { - return METHOD_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitMethodInsn(opcode, owner, name, desc, itf); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new MethodInsnNode(opcode, owner, name, desc, itf); - } -} diff --git a/src/asm/scala/tools/asm/tree/MethodNode.java b/src/asm/scala/tools/asm/tree/MethodNode.java deleted file mode 100644 index 3dec50e02c..0000000000 --- a/src/asm/scala/tools/asm/tree/MethodNode.java +++ /dev/null @@ -1,839 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Attribute; -import scala.tools.asm.ClassVisitor; -import scala.tools.asm.Handle; -import scala.tools.asm.Label; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.Type; -import scala.tools.asm.TypePath; - -/** - * A node that represents a method. - * - * @author Eric Bruneton - */ -public class MethodNode extends MethodVisitor { - - /** - * The method's access flags (see {@link Opcodes}). This field also - * indicates if the method is synthetic and/or deprecated. - */ - public int access; - - /** - * The method's name. - */ - public String name; - - /** - * The method's descriptor (see {@link Type}). - */ - public String desc; - - /** - * The method's signature. May be <tt>null</tt>. - */ - public String signature; - - /** - * The internal names of the method's exception classes (see - * {@link Type#getInternalName() getInternalName}). This list is a list of - * {@link String} objects. - */ - public List<String> exceptions; - - /** - * The method parameter info (access flags and name) - */ - public List<ParameterNode> parameters; - - /** - * The runtime visible annotations of this method. This list is a list of - * {@link AnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.AnnotationNode - * @label visible - */ - public List<AnnotationNode> visibleAnnotations; - - /** - * The runtime invisible annotations of this method. This list is a list of - * {@link AnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.AnnotationNode - * @label invisible - */ - public List<AnnotationNode> invisibleAnnotations; - - /** - * The runtime visible type annotations of this method. This list is a list - * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.TypeAnnotationNode - * @label visible - */ - public List<TypeAnnotationNode> visibleTypeAnnotations; - - /** - * The runtime invisible type annotations of this method. This list is a - * list of {@link TypeAnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.TypeAnnotationNode - * @label invisible - */ - public List<TypeAnnotationNode> invisibleTypeAnnotations; - - /** - * The non standard attributes of this method. This list is a list of - * {@link Attribute} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.Attribute - */ - public List<Attribute> attrs; - - /** - * The default value of this annotation interface method. This field must be - * a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short}, - * {@link Integer}, {@link Long}, {@link Float}, {@link Double}, - * {@link String} or {@link Type}, or an two elements String array (for - * enumeration values), a {@link AnnotationNode}, or a {@link List} of - * values of one of the preceding types. May be <tt>null</tt>. - */ - public Object annotationDefault; - - /** - * The runtime visible parameter annotations of this method. These lists are - * lists of {@link AnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.AnnotationNode - * @label invisible parameters - */ - public List<AnnotationNode>[] visibleParameterAnnotations; - - /** - * The runtime invisible parameter annotations of this method. These lists - * are lists of {@link AnnotationNode} objects. May be <tt>null</tt>. - * - * @associates scala.tools.asm.tree.AnnotationNode - * @label visible parameters - */ - public List<AnnotationNode>[] invisibleParameterAnnotations; - - /** - * The instructions of this method. This list is a list of - * {@link AbstractInsnNode} objects. - * - * @associates scala.tools.asm.tree.AbstractInsnNode - * @label instructions - */ - public InsnList instructions; - - /** - * The try catch blocks of this method. This list is a list of - * {@link TryCatchBlockNode} objects. - * - * @associates scala.tools.asm.tree.TryCatchBlockNode - */ - public List<TryCatchBlockNode> tryCatchBlocks; - - /** - * The maximum stack size of this method. - */ - public int maxStack; - - /** - * The maximum number of local variables of this method. - */ - public int maxLocals; - - /** - * The local variables of this method. This list is a list of - * {@link LocalVariableNode} objects. May be <tt>null</tt> - * - * @associates scala.tools.asm.tree.LocalVariableNode - */ - public List<LocalVariableNode> localVariables; - - /** - * The visible local variable annotations of this method. This list is a - * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt> - * - * @associates scala.tools.asm.tree.LocalVariableAnnotationNode - */ - public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations; - - /** - * The invisible local variable annotations of this method. This list is a - * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt> - * - * @associates scala.tools.asm.tree.LocalVariableAnnotationNode - */ - public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations; - - /** - * If the accept method has been called on this object. - */ - private boolean visited; - - /** - * Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not - * use this constructor</i>. Instead, they must use the - * {@link #MethodNode(int)} version. - * - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public MethodNode() { - this(Opcodes.ASM5); - if (getClass() != MethodNode.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs an uninitialized {@link MethodNode}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - public MethodNode(final int api) { - super(api); - this.instructions = new InsnList(); - } - - /** - * Constructs a new {@link MethodNode}. <i>Subclasses must not use this - * constructor</i>. Instead, they must use the - * {@link #MethodNode(int, int, String, String, String, String[])} version. - * - * @param access - * the method's access flags (see {@link Opcodes}). This - * parameter also indicates if the method is synthetic and/or - * deprecated. - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type}). - * @param signature - * the method's signature. May be <tt>null</tt>. - * @param exceptions - * the internal names of the method's exception classes (see - * {@link Type#getInternalName() getInternalName}). May be - * <tt>null</tt>. - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public MethodNode(final int access, final String name, final String desc, - final String signature, final String[] exceptions) { - this(Opcodes.ASM5, access, name, desc, signature, exceptions); - if (getClass() != MethodNode.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs a new {@link MethodNode}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param access - * the method's access flags (see {@link Opcodes}). This - * parameter also indicates if the method is synthetic and/or - * deprecated. - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type}). - * @param signature - * the method's signature. May be <tt>null</tt>. - * @param exceptions - * the internal names of the method's exception classes (see - * {@link Type#getInternalName() getInternalName}). May be - * <tt>null</tt>. - */ - public MethodNode(final int api, final int access, final String name, - final String desc, final String signature, final String[] exceptions) { - super(api); - this.access = access; - this.name = name; - this.desc = desc; - this.signature = signature; - this.exceptions = new ArrayList<String>(exceptions == null ? 0 - : exceptions.length); - boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0; - if (!isAbstract) { - this.localVariables = new ArrayList<LocalVariableNode>(5); - } - this.tryCatchBlocks = new ArrayList<TryCatchBlockNode>(); - if (exceptions != null) { - this.exceptions.addAll(Arrays.asList(exceptions)); - } - this.instructions = new InsnList(); - } - - // ------------------------------------------------------------------------ - // Implementation of the MethodVisitor abstract class - // ------------------------------------------------------------------------ - - @Override - public void visitParameter(String name, int access) { - if (parameters == null) { - parameters = new ArrayList<ParameterNode>(5); - } - parameters.add(new ParameterNode(name, access)); - } - - @Override - @SuppressWarnings("serial") - public AnnotationVisitor visitAnnotationDefault() { - return new AnnotationNode(new ArrayList<Object>(0) { - @Override - public boolean add(final Object o) { - annotationDefault = o; - return super.add(o); - } - }); - } - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - AnnotationNode an = new AnnotationNode(desc); - if (visible) { - if (visibleAnnotations == null) { - visibleAnnotations = new ArrayList<AnnotationNode>(1); - } - visibleAnnotations.add(an); - } else { - if (invisibleAnnotations == null) { - invisibleAnnotations = new ArrayList<AnnotationNode>(1); - } - invisibleAnnotations.add(an); - } - return an; - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); - if (visible) { - if (visibleTypeAnnotations == null) { - visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); - } - visibleTypeAnnotations.add(an); - } else { - if (invisibleTypeAnnotations == null) { - invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); - } - invisibleTypeAnnotations.add(an); - } - return an; - } - - @Override - public AnnotationVisitor visitParameterAnnotation(final int parameter, - final String desc, final boolean visible) { - AnnotationNode an = new AnnotationNode(desc); - if (visible) { - if (visibleParameterAnnotations == null) { - int params = Type.getArgumentTypes(this.desc).length; - visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; - } - if (visibleParameterAnnotations[parameter] == null) { - visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>( - 1); - } - visibleParameterAnnotations[parameter].add(an); - } else { - if (invisibleParameterAnnotations == null) { - int params = Type.getArgumentTypes(this.desc).length; - invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; - } - if (invisibleParameterAnnotations[parameter] == null) { - invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>( - 1); - } - invisibleParameterAnnotations[parameter].add(an); - } - return an; - } - - @Override - public void visitAttribute(final Attribute attr) { - if (attrs == null) { - attrs = new ArrayList<Attribute>(1); - } - attrs.add(attr); - } - - @Override - public void visitCode() { - } - - @Override - public void visitFrame(final int type, final int nLocal, - final Object[] local, final int nStack, final Object[] stack) { - instructions.add(new FrameNode(type, nLocal, local == null ? null - : getLabelNodes(local), nStack, stack == null ? null - : getLabelNodes(stack))); - } - - @Override - public void visitInsn(final int opcode) { - instructions.add(new InsnNode(opcode)); - } - - @Override - public void visitIntInsn(final int opcode, final int operand) { - instructions.add(new IntInsnNode(opcode, operand)); - } - - @Override - public void visitVarInsn(final int opcode, final int var) { - instructions.add(new VarInsnNode(opcode, var)); - } - - @Override - public void visitTypeInsn(final int opcode, final String type) { - instructions.add(new TypeInsnNode(opcode, type)); - } - - @Override - public void visitFieldInsn(final int opcode, final String owner, - final String name, final String desc) { - instructions.add(new FieldInsnNode(opcode, owner, name, desc)); - } - - @Deprecated - @Override - public void visitMethodInsn(int opcode, String owner, String name, - String desc) { - if (api >= Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc); - return; - } - instructions.add(new MethodInsnNode(opcode, owner, name, desc)); - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, - String desc, boolean itf) { - if (api < Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf)); - } - - @Override - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, - Object... bsmArgs) { - instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)); - } - - @Override - public void visitJumpInsn(final int opcode, final Label label) { - instructions.add(new JumpInsnNode(opcode, getLabelNode(label))); - } - - @Override - public void visitLabel(final Label label) { - instructions.add(getLabelNode(label)); - } - - @Override - public void visitLdcInsn(final Object cst) { - instructions.add(new LdcInsnNode(cst)); - } - - @Override - public void visitIincInsn(final int var, final int increment) { - instructions.add(new IincInsnNode(var, increment)); - } - - @Override - public void visitTableSwitchInsn(final int min, final int max, - final Label dflt, final Label... labels) { - instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt), - getLabelNodes(labels))); - } - - @Override - public void visitLookupSwitchInsn(final Label dflt, final int[] keys, - final Label[] labels) { - instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys, - getLabelNodes(labels))); - } - - @Override - public void visitMultiANewArrayInsn(final String desc, final int dims) { - instructions.add(new MultiANewArrayInsnNode(desc, dims)); - } - - @Override - public AnnotationVisitor visitInsnAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - // Finds the last real instruction, i.e. the instruction targeted by - // this annotation. - AbstractInsnNode insn = instructions.getLast(); - while (insn.getOpcode() == -1) { - insn = insn.getPrevious(); - } - // Adds the annotation to this instruction. - TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); - if (visible) { - if (insn.visibleTypeAnnotations == null) { - insn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( - 1); - } - insn.visibleTypeAnnotations.add(an); - } else { - if (insn.invisibleTypeAnnotations == null) { - insn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( - 1); - } - insn.invisibleTypeAnnotations.add(an); - } - return an; - } - - @Override - public void visitTryCatchBlock(final Label start, final Label end, - final Label handler, final String type) { - tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start), - getLabelNode(end), getLabelNode(handler), type)); - } - - @Override - public AnnotationVisitor visitTryCatchAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8); - TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); - if (visible) { - if (tcb.visibleTypeAnnotations == null) { - tcb.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( - 1); - } - tcb.visibleTypeAnnotations.add(an); - } else { - if (tcb.invisibleTypeAnnotations == null) { - tcb.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( - 1); - } - tcb.invisibleTypeAnnotations.add(an); - } - return an; - } - - @Override - public void visitLocalVariable(final String name, final String desc, - final String signature, final Label start, final Label end, - final int index) { - localVariables.add(new LocalVariableNode(name, desc, signature, - getLabelNode(start), getLabelNode(end), index)); - } - - @Override - public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, - TypePath typePath, Label[] start, Label[] end, int[] index, - String desc, boolean visible) { - LocalVariableAnnotationNode an = new LocalVariableAnnotationNode( - typeRef, typePath, getLabelNodes(start), getLabelNodes(end), - index, desc); - if (visible) { - if (visibleLocalVariableAnnotations == null) { - visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>( - 1); - } - visibleLocalVariableAnnotations.add(an); - } else { - if (invisibleLocalVariableAnnotations == null) { - invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>( - 1); - } - invisibleLocalVariableAnnotations.add(an); - } - return an; - } - - @Override - public void visitLineNumber(final int line, final Label start) { - instructions.add(new LineNumberNode(line, getLabelNode(start))); - } - - @Override - public void visitMaxs(final int maxStack, final int maxLocals) { - this.maxStack = maxStack; - this.maxLocals = maxLocals; - } - - @Override - public void visitEnd() { - } - - /** - * Returns the LabelNode corresponding to the given Label. Creates a new - * LabelNode if necessary. The default implementation of this method uses - * the {@link Label#info} field to store associations between labels and - * label nodes. - * - * @param l - * a Label. - * @return the LabelNode corresponding to l. - */ - protected LabelNode getLabelNode(final Label l) { - if (!(l.info instanceof LabelNode)) { - l.info = new LabelNode(l); - } - return (LabelNode) l.info; - } - - private LabelNode[] getLabelNodes(final Label[] l) { - LabelNode[] nodes = new LabelNode[l.length]; - for (int i = 0; i < l.length; ++i) { - nodes[i] = getLabelNode(l[i]); - } - return nodes; - } - - private Object[] getLabelNodes(final Object[] objs) { - Object[] nodes = new Object[objs.length]; - for (int i = 0; i < objs.length; ++i) { - Object o = objs[i]; - if (o instanceof Label) { - o = getLabelNode((Label) o); - } - nodes[i] = o; - } - return nodes; - } - - // ------------------------------------------------------------------------ - // Accept method - // ------------------------------------------------------------------------ - - /** - * Checks that this method node is compatible with the given ASM API - * version. This methods checks that this node, and all its nodes - * recursively, do not contain elements that were introduced in more recent - * versions of the ASM API than the given version. - * - * @param api - * an ASM API version. Must be one of {@link Opcodes#ASM4} or - * {@link Opcodes#ASM5}. - */ - public void check(final int api) { - if (api == Opcodes.ASM4) { - if (visibleTypeAnnotations != null - && visibleTypeAnnotations.size() > 0) { - throw new RuntimeException(); - } - if (invisibleTypeAnnotations != null - && invisibleTypeAnnotations.size() > 0) { - throw new RuntimeException(); - } - int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size(); - for (int i = 0; i < n; ++i) { - TryCatchBlockNode tcb = tryCatchBlocks.get(i); - if (tcb.visibleTypeAnnotations != null - && tcb.visibleTypeAnnotations.size() > 0) { - throw new RuntimeException(); - } - if (tcb.invisibleTypeAnnotations != null - && tcb.invisibleTypeAnnotations.size() > 0) { - throw new RuntimeException(); - } - } - for (int i = 0; i < instructions.size(); ++i) { - AbstractInsnNode insn = instructions.get(i); - if (insn.visibleTypeAnnotations != null - && insn.visibleTypeAnnotations.size() > 0) { - throw new RuntimeException(); - } - if (insn.invisibleTypeAnnotations != null - && insn.invisibleTypeAnnotations.size() > 0) { - throw new RuntimeException(); - } - if (insn instanceof MethodInsnNode) { - boolean itf = ((MethodInsnNode) insn).itf; - if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) { - throw new RuntimeException(); - } - } - } - if (visibleLocalVariableAnnotations != null - && visibleLocalVariableAnnotations.size() > 0) { - throw new RuntimeException(); - } - if (invisibleLocalVariableAnnotations != null - && invisibleLocalVariableAnnotations.size() > 0) { - throw new RuntimeException(); - } - } - } - - /** - * Makes the given class visitor visit this method. - * - * @param cv - * a class visitor. - */ - public void accept(final ClassVisitor cv) { - String[] exceptions = new String[this.exceptions.size()]; - this.exceptions.toArray(exceptions); - MethodVisitor mv = cv.visitMethod(access, name, desc, signature, - exceptions); - if (mv != null) { - accept(mv); - } - } - - /** - * Makes the given method visitor visit this method. - * - * @param mv - * a method visitor. - */ - public void accept(final MethodVisitor mv) { - // visits the method parameters - int i, j, n; - n = parameters == null ? 0 : parameters.size(); - for (i = 0; i < n; i++) { - ParameterNode parameter = parameters.get(i); - mv.visitParameter(parameter.name, parameter.access); - } - // visits the method attributes - if (annotationDefault != null) { - AnnotationVisitor av = mv.visitAnnotationDefault(); - AnnotationNode.accept(av, null, annotationDefault); - if (av != null) { - av.visitEnd(); - } - } - n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); - for (i = 0; i < n; ++i) { - AnnotationNode an = visibleAnnotations.get(i); - an.accept(mv.visitAnnotation(an.desc, true)); - } - n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); - for (i = 0; i < n; ++i) { - AnnotationNode an = invisibleAnnotations.get(i); - an.accept(mv.visitAnnotation(an.desc, false)); - } - n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); - for (i = 0; i < n; ++i) { - TypeAnnotationNode an = visibleTypeAnnotations.get(i); - an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, - true)); - } - n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations - .size(); - for (i = 0; i < n; ++i) { - TypeAnnotationNode an = invisibleTypeAnnotations.get(i); - an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, - false)); - } - n = visibleParameterAnnotations == null ? 0 - : visibleParameterAnnotations.length; - for (i = 0; i < n; ++i) { - List<?> l = visibleParameterAnnotations[i]; - if (l == null) { - continue; - } - for (j = 0; j < l.size(); ++j) { - AnnotationNode an = (AnnotationNode) l.get(j); - an.accept(mv.visitParameterAnnotation(i, an.desc, true)); - } - } - n = invisibleParameterAnnotations == null ? 0 - : invisibleParameterAnnotations.length; - for (i = 0; i < n; ++i) { - List<?> l = invisibleParameterAnnotations[i]; - if (l == null) { - continue; - } - for (j = 0; j < l.size(); ++j) { - AnnotationNode an = (AnnotationNode) l.get(j); - an.accept(mv.visitParameterAnnotation(i, an.desc, false)); - } - } - if (visited) { - instructions.resetLabels(); - } - n = attrs == null ? 0 : attrs.size(); - for (i = 0; i < n; ++i) { - mv.visitAttribute(attrs.get(i)); - } - // visits the method's code - if (instructions.size() > 0) { - mv.visitCode(); - // visits try catch blocks - n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size(); - for (i = 0; i < n; ++i) { - tryCatchBlocks.get(i).updateIndex(i); - tryCatchBlocks.get(i).accept(mv); - } - // visits instructions - instructions.accept(mv); - // visits local variables - n = localVariables == null ? 0 : localVariables.size(); - for (i = 0; i < n; ++i) { - localVariables.get(i).accept(mv); - } - // visits local variable annotations - n = visibleLocalVariableAnnotations == null ? 0 - : visibleLocalVariableAnnotations.size(); - for (i = 0; i < n; ++i) { - visibleLocalVariableAnnotations.get(i).accept(mv, true); - } - n = invisibleLocalVariableAnnotations == null ? 0 - : invisibleLocalVariableAnnotations.size(); - for (i = 0; i < n; ++i) { - invisibleLocalVariableAnnotations.get(i).accept(mv, false); - } - // visits maxs - mv.visitMaxs(maxStack, maxLocals); - visited = true; - } - mv.visitEnd(); - } -} diff --git a/src/asm/scala/tools/asm/tree/MultiANewArrayInsnNode.java b/src/asm/scala/tools/asm/tree/MultiANewArrayInsnNode.java deleted file mode 100644 index a8339a20b5..0000000000 --- a/src/asm/scala/tools/asm/tree/MultiANewArrayInsnNode.java +++ /dev/null @@ -1,84 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; - -/** - * A node that represents a MULTIANEWARRAY instruction. - * - * @author Eric Bruneton - */ -public class MultiANewArrayInsnNode extends AbstractInsnNode { - - /** - * An array type descriptor (see {@link scala.tools.asm.Type}). - */ - public String desc; - - /** - * Number of dimensions of the array to allocate. - */ - public int dims; - - /** - * Constructs a new {@link MultiANewArrayInsnNode}. - * - * @param desc - * an array type descriptor (see {@link scala.tools.asm.Type}). - * @param dims - * number of dimensions of the array to allocate. - */ - public MultiANewArrayInsnNode(final String desc, final int dims) { - super(Opcodes.MULTIANEWARRAY); - this.desc = desc; - this.dims = dims; - } - - @Override - public int getType() { - return MULTIANEWARRAY_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitMultiANewArrayInsn(desc, dims); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this); - } - -} diff --git a/src/asm/scala/tools/asm/tree/ParameterNode.java b/src/asm/scala/tools/asm/tree/ParameterNode.java deleted file mode 100644 index a3e55d5629..0000000000 --- a/src/asm/scala/tools/asm/tree/ParameterNode.java +++ /dev/null @@ -1,76 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents a parameter access and name. - * - * @author Remi Forax - */ -public class ParameterNode { - /** - * The parameter's name. - */ - public String name; - - /** - * The parameter's access flags (see {@link scala.tools.asm.Opcodes}). - * Valid values are <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> and - * <tt>ACC_MANDATED</tt>. - */ - public int access; - - /** - * Constructs a new {@link ParameterNode}. - * - * @param access - * The parameter's access flags. Valid values are - * <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> or/and - * <tt>ACC_MANDATED</tt> (see {@link scala.tools.asm.Opcodes}). - * @param name - * the parameter's name. - */ - public ParameterNode(final String name, final int access) { - this.name = name; - this.access = access; - } - - /** - * Makes the given visitor visit this parameter declaration. - * - * @param mv - * a method visitor. - */ - public void accept(final MethodVisitor mv) { - mv.visitParameter(name, access); - } -} diff --git a/src/asm/scala/tools/asm/tree/TableSwitchInsnNode.java b/src/asm/scala/tools/asm/tree/TableSwitchInsnNode.java deleted file mode 100644 index fb17b9e2e9..0000000000 --- a/src/asm/scala/tools/asm/tree/TableSwitchInsnNode.java +++ /dev/null @@ -1,114 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import scala.tools.asm.Label; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; - -/** - * A node that represents a TABLESWITCH instruction. - * - * @author Eric Bruneton - */ -public class TableSwitchInsnNode extends AbstractInsnNode { - - /** - * The minimum key value. - */ - public int min; - - /** - * The maximum key value. - */ - public int max; - - /** - * Beginning of the default handler block. - */ - public LabelNode dflt; - - /** - * Beginnings of the handler blocks. This list is a list of - * {@link LabelNode} objects. - */ - public List<LabelNode> labels; - - /** - * Constructs a new {@link TableSwitchInsnNode}. - * - * @param min - * the minimum key value. - * @param max - * the maximum key value. - * @param dflt - * beginning of the default handler block. - * @param labels - * beginnings of the handler blocks. <tt>labels[i]</tt> is the - * beginning of the handler block for the <tt>min + i</tt> key. - */ - public TableSwitchInsnNode(final int min, final int max, - final LabelNode dflt, final LabelNode... labels) { - super(Opcodes.TABLESWITCH); - this.min = min; - this.max = max; - this.dflt = dflt; - this.labels = new ArrayList<LabelNode>(); - if (labels != null) { - this.labels.addAll(Arrays.asList(labels)); - } - } - - @Override - public int getType() { - return TABLESWITCH_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - Label[] labels = new Label[this.labels.size()]; - for (int i = 0; i < labels.length; ++i) { - labels[i] = this.labels.get(i).getLabel(); - } - mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone( - this.labels, labels)).cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/TryCatchBlockNode.java b/src/asm/scala/tools/asm/tree/TryCatchBlockNode.java deleted file mode 100644 index c639b9aa8b..0000000000 --- a/src/asm/scala/tools/asm/tree/TryCatchBlockNode.java +++ /dev/null @@ -1,153 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.List; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents a try catch block. - * - * @author Eric Bruneton - */ -public class TryCatchBlockNode { - - /** - * Beginning of the exception handler's scope (inclusive). - */ - public LabelNode start; - - /** - * End of the exception handler's scope (exclusive). - */ - public LabelNode end; - - /** - * Beginning of the exception handler's code. - */ - public LabelNode handler; - - /** - * Internal name of the type of exceptions handled by the handler. May be - * <tt>null</tt> to catch any exceptions (for "finally" blocks). - */ - public String type; - - /** - * The runtime visible type annotations on the exception handler type. This - * list is a list of {@link TypeAnnotationNode} objects. May be - * <tt>null</tt>. - * - * @associates scala.tools.asm.tree.TypeAnnotationNode - * @label visible - */ - public List<TypeAnnotationNode> visibleTypeAnnotations; - - /** - * The runtime invisible type annotations on the exception handler type. - * This list is a list of {@link TypeAnnotationNode} objects. May be - * <tt>null</tt>. - * - * @associates scala.tools.asm.tree.TypeAnnotationNode - * @label invisible - */ - public List<TypeAnnotationNode> invisibleTypeAnnotations; - - /** - * Constructs a new {@link TryCatchBlockNode}. - * - * @param start - * beginning of the exception handler's scope (inclusive). - * @param end - * end of the exception handler's scope (exclusive). - * @param handler - * beginning of the exception handler's code. - * @param type - * internal name of the type of exceptions handled by the - * handler, or <tt>null</tt> to catch any exceptions (for - * "finally" blocks). - */ - public TryCatchBlockNode(final LabelNode start, final LabelNode end, - final LabelNode handler, final String type) { - this.start = start; - this.end = end; - this.handler = handler; - this.type = type; - } - - /** - * Updates the index of this try catch block in the method's list of try - * catch block nodes. This index maybe stored in the 'target' field of the - * type annotations of this block. - * - * @param index - * the new index of this try catch block in the method's list of - * try catch block nodes. - */ - public void updateIndex(final int index) { - int newTypeRef = 0x42000000 | (index << 8); - if (visibleTypeAnnotations != null) { - for (TypeAnnotationNode tan : visibleTypeAnnotations) { - tan.typeRef = newTypeRef; - } - } - if (invisibleTypeAnnotations != null) { - for (TypeAnnotationNode tan : invisibleTypeAnnotations) { - tan.typeRef = newTypeRef; - } - } - } - - /** - * Makes the given visitor visit this try catch block. - * - * @param mv - * a method visitor. - */ - public void accept(final MethodVisitor mv) { - mv.visitTryCatchBlock(start.getLabel(), end.getLabel(), - handler == null ? null : handler.getLabel(), type); - int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations - .size(); - for (int i = 0; i < n; ++i) { - TypeAnnotationNode an = visibleTypeAnnotations.get(i); - an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath, - an.desc, true)); - } - n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations - .size(); - for (int i = 0; i < n; ++i) { - TypeAnnotationNode an = invisibleTypeAnnotations.get(i); - an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath, - an.desc, false)); - } - } -} diff --git a/src/asm/scala/tools/asm/tree/TypeAnnotationNode.java b/src/asm/scala/tools/asm/tree/TypeAnnotationNode.java deleted file mode 100644 index 73b29624f7..0000000000 --- a/src/asm/scala/tools/asm/tree/TypeAnnotationNode.java +++ /dev/null @@ -1,100 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import scala.tools.asm.Opcodes; -import scala.tools.asm.TypePath; -import scala.tools.asm.TypeReference; - -/** - * A node that represents a type annotationn. - * - * @author Eric Bruneton - */ -public class TypeAnnotationNode extends AnnotationNode { - - /** - * A reference to the annotated type. See {@link TypeReference}. - */ - public int typeRef; - - /** - * The path to the annotated type argument, wildcard bound, array element - * type, or static outer type within the referenced type. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - */ - public TypePath typePath; - - /** - * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this - * constructor</i>. Instead, they must use the - * {@link #TypeAnnotationNode(int, int, TypePath, String)} version. - * - * @param typeRef - * a reference to the annotated type. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public TypeAnnotationNode(final int typeRef, final TypePath typePath, - final String desc) { - this(Opcodes.ASM5, typeRef, typePath, desc); - if (getClass() != TypeAnnotationNode.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs a new {@link AnnotationNode}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param typeRef - * a reference to the annotated type. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - */ - public TypeAnnotationNode(final int api, final int typeRef, - final TypePath typePath, final String desc) { - super(api, desc); - this.typeRef = typeRef; - this.typePath = typePath; - } -} diff --git a/src/asm/scala/tools/asm/tree/TypeInsnNode.java b/src/asm/scala/tools/asm/tree/TypeInsnNode.java deleted file mode 100644 index 401400c3cb..0000000000 --- a/src/asm/scala/tools/asm/tree/TypeInsnNode.java +++ /dev/null @@ -1,91 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents a type instruction. A type instruction is an - * instruction that takes a type descriptor as parameter. - * - * @author Eric Bruneton - */ -public class TypeInsnNode extends AbstractInsnNode { - - /** - * The operand of this instruction. This operand is an internal name (see - * {@link scala.tools.asm.Type}). - */ - public String desc; - - /** - * Constructs a new {@link TypeInsnNode}. - * - * @param opcode - * the opcode of the type instruction to be constructed. This - * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. - * @param desc - * the operand of the instruction to be constructed. This operand - * is an internal name (see {@link scala.tools.asm.Type}). - */ - public TypeInsnNode(final int opcode, final String desc) { - super(opcode); - this.desc = desc; - } - - /** - * Sets the opcode of this instruction. - * - * @param opcode - * the new instruction opcode. This opcode must be NEW, - * ANEWARRAY, CHECKCAST or INSTANCEOF. - */ - public void setOpcode(final int opcode) { - this.opcode = opcode; - } - - @Override - public int getType() { - return TYPE_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitTypeInsn(opcode, desc); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new TypeInsnNode(opcode, desc).cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/VarInsnNode.java b/src/asm/scala/tools/asm/tree/VarInsnNode.java deleted file mode 100644 index 685e4fce2c..0000000000 --- a/src/asm/scala/tools/asm/tree/VarInsnNode.java +++ /dev/null @@ -1,94 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree; - -import java.util.Map; - -import scala.tools.asm.MethodVisitor; - -/** - * A node that represents a local variable instruction. A local variable - * instruction is an instruction that loads or stores the value of a local - * variable. - * - * @author Eric Bruneton - */ -public class VarInsnNode extends AbstractInsnNode { - - /** - * The operand of this instruction. This operand is the index of a local - * variable. - */ - public int var; - - /** - * Constructs a new {@link VarInsnNode}. - * - * @param opcode - * the opcode of the local variable instruction to be - * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD, - * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. - * @param var - * the operand of the instruction to be constructed. This operand - * is the index of a local variable. - */ - public VarInsnNode(final int opcode, final int var) { - super(opcode); - this.var = var; - } - - /** - * Sets the opcode of this instruction. - * - * @param opcode - * the new instruction opcode. This opcode must be ILOAD, LLOAD, - * FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or - * RET. - */ - public void setOpcode(final int opcode) { - this.opcode = opcode; - } - - @Override - public int getType() { - return VAR_INSN; - } - - @Override - public void accept(final MethodVisitor mv) { - mv.visitVarInsn(opcode, var); - acceptAnnotations(mv); - } - - @Override - public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { - return new VarInsnNode(opcode, var).cloneAnnotations(this); - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/Analyzer.java b/src/asm/scala/tools/asm/tree/analysis/Analyzer.java deleted file mode 100644 index ff840aabde..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/Analyzer.java +++ /dev/null @@ -1,549 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import scala.tools.asm.Opcodes; -import scala.tools.asm.Type; -import scala.tools.asm.tree.AbstractInsnNode; -import scala.tools.asm.tree.IincInsnNode; -import scala.tools.asm.tree.InsnList; -import scala.tools.asm.tree.JumpInsnNode; -import scala.tools.asm.tree.LabelNode; -import scala.tools.asm.tree.LookupSwitchInsnNode; -import scala.tools.asm.tree.MethodNode; -import scala.tools.asm.tree.TableSwitchInsnNode; -import scala.tools.asm.tree.TryCatchBlockNode; -import scala.tools.asm.tree.VarInsnNode; - -/** - * A semantic bytecode analyzer. <i>This class does not fully check that JSR and - * RET instructions are valid.</i> - * - * @param <V> - * type of the Value used for the analysis. - * - * @author Eric Bruneton - */ -public class Analyzer<V extends Value> implements Opcodes { - - private final Interpreter<V> interpreter; - - private int n; - - private InsnList insns; - - private List<TryCatchBlockNode>[] handlers; - - private Frame<V>[] frames; - - private Subroutine[] subroutines; - - private boolean[] queued; - - private int[] queue; - - private int top; - - /** - * Constructs a new {@link Analyzer}. - * - * @param interpreter - * the interpreter to be used to symbolically interpret the - * bytecode instructions. - */ - public Analyzer(final Interpreter<V> interpreter) { - this.interpreter = interpreter; - } - - /** - * Analyzes the given method. - * - * @param owner - * the internal name of the class to which the method belongs. - * @param m - * the method to be analyzed. - * @return the symbolic state of the execution stack frame at each bytecode - * instruction of the method. The size of the returned array is - * equal to the number of instructions (and labels) of the method. A - * given frame is <tt>null</tt> if and only if the corresponding - * instruction cannot be reached (dead code). - * @throws AnalyzerException - * if a problem occurs during the analysis. - */ - public Frame<V>[] analyze(final String owner, final MethodNode m) - throws AnalyzerException { - if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) { - frames = (Frame<V>[]) new Frame<?>[0]; - return frames; - } - n = m.instructions.size(); - insns = m.instructions; - handlers = (List<TryCatchBlockNode>[]) new List<?>[n]; - frames = (Frame<V>[]) new Frame<?>[n]; - subroutines = new Subroutine[n]; - queued = new boolean[n]; - queue = new int[n]; - top = 0; - - // computes exception handlers for each instruction - for (int i = 0; i < m.tryCatchBlocks.size(); ++i) { - TryCatchBlockNode tcb = m.tryCatchBlocks.get(i); - int begin = insns.indexOf(tcb.start); - int end = insns.indexOf(tcb.end); - for (int j = begin; j < end; ++j) { - List<TryCatchBlockNode> insnHandlers = handlers[j]; - if (insnHandlers == null) { - insnHandlers = new ArrayList<TryCatchBlockNode>(); - handlers[j] = insnHandlers; - } - insnHandlers.add(tcb); - } - } - - // computes the subroutine for each instruction: - Subroutine main = new Subroutine(null, m.maxLocals, null); - List<AbstractInsnNode> subroutineCalls = new ArrayList<AbstractInsnNode>(); - Map<LabelNode, Subroutine> subroutineHeads = new HashMap<LabelNode, Subroutine>(); - findSubroutine(0, main, subroutineCalls); - while (!subroutineCalls.isEmpty()) { - JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0); - Subroutine sub = subroutineHeads.get(jsr.label); - if (sub == null) { - sub = new Subroutine(jsr.label, m.maxLocals, jsr); - subroutineHeads.put(jsr.label, sub); - findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls); - } else { - sub.callers.add(jsr); - } - } - for (int i = 0; i < n; ++i) { - if (subroutines[i] != null && subroutines[i].start == null) { - subroutines[i] = null; - } - } - - // initializes the data structures for the control flow analysis - Frame<V> current = newFrame(m.maxLocals, m.maxStack); - Frame<V> handler = newFrame(m.maxLocals, m.maxStack); - current.setReturn(interpreter.newValue(Type.getReturnType(m.desc))); - Type[] args = Type.getArgumentTypes(m.desc); - int local = 0; - if ((m.access & ACC_STATIC) == 0) { - Type ctype = Type.getObjectType(owner); - current.setLocal(local++, interpreter.newValue(ctype)); - } - for (int i = 0; i < args.length; ++i) { - current.setLocal(local++, interpreter.newValue(args[i])); - if (args[i].getSize() == 2) { - current.setLocal(local++, interpreter.newValue(null)); - } - } - while (local < m.maxLocals) { - current.setLocal(local++, interpreter.newValue(null)); - } - merge(0, current, null); - - init(owner, m); - - // control flow analysis - while (top > 0) { - int insn = queue[--top]; - Frame<V> f = frames[insn]; - Subroutine subroutine = subroutines[insn]; - queued[insn] = false; - - AbstractInsnNode insnNode = null; - try { - insnNode = m.instructions.get(insn); - int insnOpcode = insnNode.getOpcode(); - int insnType = insnNode.getType(); - - if (insnType == AbstractInsnNode.LABEL - || insnType == AbstractInsnNode.LINE - || insnType == AbstractInsnNode.FRAME) { - merge(insn + 1, f, subroutine); - newControlFlowEdge(insn, insn + 1); - } else { - current.init(f).execute(insnNode, interpreter); - subroutine = subroutine == null ? null : subroutine.copy(); - - if (insnNode instanceof JumpInsnNode) { - JumpInsnNode j = (JumpInsnNode) insnNode; - if (insnOpcode != GOTO && insnOpcode != JSR) { - merge(insn + 1, current, subroutine); - newControlFlowEdge(insn, insn + 1); - } - int jump = insns.indexOf(j.label); - if (insnOpcode == JSR) { - merge(jump, current, new Subroutine(j.label, - m.maxLocals, j)); - } else { - merge(jump, current, subroutine); - } - newControlFlowEdge(insn, jump); - } else if (insnNode instanceof LookupSwitchInsnNode) { - LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode; - int jump = insns.indexOf(lsi.dflt); - merge(jump, current, subroutine); - newControlFlowEdge(insn, jump); - for (int j = 0; j < lsi.labels.size(); ++j) { - LabelNode label = lsi.labels.get(j); - jump = insns.indexOf(label); - merge(jump, current, subroutine); - newControlFlowEdge(insn, jump); - } - } else if (insnNode instanceof TableSwitchInsnNode) { - TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode; - int jump = insns.indexOf(tsi.dflt); - merge(jump, current, subroutine); - newControlFlowEdge(insn, jump); - for (int j = 0; j < tsi.labels.size(); ++j) { - LabelNode label = tsi.labels.get(j); - jump = insns.indexOf(label); - merge(jump, current, subroutine); - newControlFlowEdge(insn, jump); - } - } else if (insnOpcode == RET) { - if (subroutine == null) { - throw new AnalyzerException(insnNode, - "RET instruction outside of a sub routine"); - } - for (int i = 0; i < subroutine.callers.size(); ++i) { - JumpInsnNode caller = subroutine.callers.get(i); - int call = insns.indexOf(caller); - if (frames[call] != null) { - merge(call + 1, frames[call], current, - subroutines[call], subroutine.access); - newControlFlowEdge(insn, call + 1); - } - } - } else if (insnOpcode != ATHROW - && (insnOpcode < IRETURN || insnOpcode > RETURN)) { - if (subroutine != null) { - if (insnNode instanceof VarInsnNode) { - int var = ((VarInsnNode) insnNode).var; - subroutine.access[var] = true; - if (insnOpcode == LLOAD || insnOpcode == DLOAD - || insnOpcode == LSTORE - || insnOpcode == DSTORE) { - subroutine.access[var + 1] = true; - } - } else if (insnNode instanceof IincInsnNode) { - int var = ((IincInsnNode) insnNode).var; - subroutine.access[var] = true; - } - } - merge(insn + 1, current, subroutine); - newControlFlowEdge(insn, insn + 1); - } - } - - List<TryCatchBlockNode> insnHandlers = handlers[insn]; - if (insnHandlers != null) { - for (int i = 0; i < insnHandlers.size(); ++i) { - TryCatchBlockNode tcb = insnHandlers.get(i); - Type type; - if (tcb.type == null) { - type = Type.getObjectType("java/lang/Throwable"); - } else { - type = Type.getObjectType(tcb.type); - } - int jump = insns.indexOf(tcb.handler); - if (newControlFlowExceptionEdge(insn, tcb)) { - handler.init(f); - handler.clearStack(); - handler.push(interpreter.newValue(type)); - merge(jump, handler, subroutine); - } - } - } - } catch (AnalyzerException e) { - throw new AnalyzerException(e.node, "Error at instruction " - + insn + ": " + e.getMessage(), e); - } catch (Exception e) { - throw new AnalyzerException(insnNode, "Error at instruction " - + insn + ": " + e.getMessage(), e); - } - } - - return frames; - } - - private void findSubroutine(int insn, final Subroutine sub, - final List<AbstractInsnNode> calls) throws AnalyzerException { - while (true) { - if (insn < 0 || insn >= n) { - throw new AnalyzerException(null, - "Execution can fall off end of the code"); - } - if (subroutines[insn] != null) { - return; - } - subroutines[insn] = sub.copy(); - AbstractInsnNode node = insns.get(insn); - - // calls findSubroutine recursively on normal successors - if (node instanceof JumpInsnNode) { - if (node.getOpcode() == JSR) { - // do not follow a JSR, it leads to another subroutine! - calls.add(node); - } else { - JumpInsnNode jnode = (JumpInsnNode) node; - findSubroutine(insns.indexOf(jnode.label), sub, calls); - } - } else if (node instanceof TableSwitchInsnNode) { - TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node; - findSubroutine(insns.indexOf(tsnode.dflt), sub, calls); - for (int i = tsnode.labels.size() - 1; i >= 0; --i) { - LabelNode l = tsnode.labels.get(i); - findSubroutine(insns.indexOf(l), sub, calls); - } - } else if (node instanceof LookupSwitchInsnNode) { - LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node; - findSubroutine(insns.indexOf(lsnode.dflt), sub, calls); - for (int i = lsnode.labels.size() - 1; i >= 0; --i) { - LabelNode l = lsnode.labels.get(i); - findSubroutine(insns.indexOf(l), sub, calls); - } - } - - // calls findSubroutine recursively on exception handler successors - List<TryCatchBlockNode> insnHandlers = handlers[insn]; - if (insnHandlers != null) { - for (int i = 0; i < insnHandlers.size(); ++i) { - TryCatchBlockNode tcb = insnHandlers.get(i); - findSubroutine(insns.indexOf(tcb.handler), sub, calls); - } - } - - // if insn does not falls through to the next instruction, return. - switch (node.getOpcode()) { - case GOTO: - case RET: - case TABLESWITCH: - case LOOKUPSWITCH: - case IRETURN: - case LRETURN: - case FRETURN: - case DRETURN: - case ARETURN: - case RETURN: - case ATHROW: - return; - } - insn++; - } - } - - /** - * Returns the symbolic stack frame for each instruction of the last - * recently analyzed method. - * - * @return the symbolic state of the execution stack frame at each bytecode - * instruction of the method. The size of the returned array is - * equal to the number of instructions (and labels) of the method. A - * given frame is <tt>null</tt> if the corresponding instruction - * cannot be reached, or if an error occurred during the analysis of - * the method. - */ - public Frame<V>[] getFrames() { - return frames; - } - - /** - * Returns the exception handlers for the given instruction. - * - * @param insn - * the index of an instruction of the last recently analyzed - * method. - * @return a list of {@link TryCatchBlockNode} objects. - */ - public List<TryCatchBlockNode> getHandlers(final int insn) { - return handlers[insn]; - } - - /** - * Initializes this analyzer. This method is called just before the - * execution of control flow analysis loop in #analyze. The default - * implementation of this method does nothing. - * - * @param owner - * the internal name of the class to which the method belongs. - * @param m - * the method to be analyzed. - * @throws AnalyzerException - * if a problem occurs. - */ - protected void init(String owner, MethodNode m) throws AnalyzerException { - } - - /** - * Constructs a new frame with the given size. - * - * @param nLocals - * the maximum number of local variables of the frame. - * @param nStack - * the maximum stack size of the frame. - * @return the created frame. - */ - protected Frame<V> newFrame(final int nLocals, final int nStack) { - return new Frame<V>(nLocals, nStack); - } - - /** - * Constructs a new frame that is identical to the given frame. - * - * @param src - * a frame. - * @return the created frame. - */ - protected Frame<V> newFrame(final Frame<? extends V> src) { - return new Frame<V>(src); - } - - /** - * Creates a control flow graph edge. The default implementation of this - * method does nothing. It can be overridden in order to construct the - * control flow graph of a method (this method is called by the - * {@link #analyze analyze} method during its visit of the method's code). - * - * @param insn - * an instruction index. - * @param successor - * index of a successor instruction. - */ - protected void newControlFlowEdge(final int insn, final int successor) { - } - - /** - * Creates a control flow graph edge corresponding to an exception handler. - * The default implementation of this method does nothing. It can be - * overridden in order to construct the control flow graph of a method (this - * method is called by the {@link #analyze analyze} method during its visit - * of the method's code). - * - * @param insn - * an instruction index. - * @param successor - * index of a successor instruction. - * @return true if this edge must be considered in the data flow analysis - * performed by this analyzer, or false otherwise. The default - * implementation of this method always returns true. - */ - protected boolean newControlFlowExceptionEdge(final int insn, - final int successor) { - return true; - } - - /** - * Creates a control flow graph edge corresponding to an exception handler. - * The default implementation of this method delegates to - * {@link #newControlFlowExceptionEdge(int, int) - * newControlFlowExceptionEdge(int, int)}. It can be overridden in order to - * construct the control flow graph of a method (this method is called by - * the {@link #analyze analyze} method during its visit of the method's - * code). - * - * @param insn - * an instruction index. - * @param tcb - * TryCatchBlockNode corresponding to this edge. - * @return true if this edge must be considered in the data flow analysis - * performed by this analyzer, or false otherwise. The default - * implementation of this method delegates to - * {@link #newControlFlowExceptionEdge(int, int) - * newControlFlowExceptionEdge(int, int)}. - */ - protected boolean newControlFlowExceptionEdge(final int insn, - final TryCatchBlockNode tcb) { - return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler)); - } - - // ------------------------------------------------------------------------- - - private void merge(final int insn, final Frame<V> frame, - final Subroutine subroutine) throws AnalyzerException { - Frame<V> oldFrame = frames[insn]; - Subroutine oldSubroutine = subroutines[insn]; - boolean changes; - - if (oldFrame == null) { - frames[insn] = newFrame(frame); - changes = true; - } else { - changes = oldFrame.merge(frame, interpreter); - } - - if (oldSubroutine == null) { - if (subroutine != null) { - subroutines[insn] = subroutine.copy(); - changes = true; - } - } else { - if (subroutine != null) { - changes |= oldSubroutine.merge(subroutine); - } - } - if (changes && !queued[insn]) { - queued[insn] = true; - queue[top++] = insn; - } - } - - private void merge(final int insn, final Frame<V> beforeJSR, - final Frame<V> afterRET, final Subroutine subroutineBeforeJSR, - final boolean[] access) throws AnalyzerException { - Frame<V> oldFrame = frames[insn]; - Subroutine oldSubroutine = subroutines[insn]; - boolean changes; - - afterRET.merge(beforeJSR, access); - - if (oldFrame == null) { - frames[insn] = newFrame(afterRET); - changes = true; - } else { - changes = oldFrame.merge(afterRET, interpreter); - } - - if (oldSubroutine != null && subroutineBeforeJSR != null) { - changes |= oldSubroutine.merge(subroutineBeforeJSR); - } - if (changes && !queued[insn]) { - queued[insn] = true; - queue[top++] = insn; - } - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/AnalyzerException.java b/src/asm/scala/tools/asm/tree/analysis/AnalyzerException.java deleted file mode 100644 index 52b2a11d6f..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/AnalyzerException.java +++ /dev/null @@ -1,62 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import scala.tools.asm.tree.AbstractInsnNode; - -/** - * Thrown if a problem occurs during the analysis of a method. - * - * @author Bing Ran - * @author Eric Bruneton - */ -@SuppressWarnings("serial") -public class AnalyzerException extends Exception { - - public final AbstractInsnNode node; - - public AnalyzerException(final AbstractInsnNode node, final String msg) { - super(msg); - this.node = node; - } - - public AnalyzerException(final AbstractInsnNode node, final String msg, - final Throwable exception) { - super(msg, exception); - this.node = node; - } - - public AnalyzerException(final AbstractInsnNode node, final String msg, - final Object expected, final Value encountered) { - super((msg == null ? "Expected " : msg + ": expected ") + expected - + ", but found " + encountered); - this.node = node; - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/BasicInterpreter.java b/src/asm/scala/tools/asm/tree/analysis/BasicInterpreter.java deleted file mode 100644 index 7d0b7b0694..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/BasicInterpreter.java +++ /dev/null @@ -1,358 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import java.util.List; - -import scala.tools.asm.Handle; -import scala.tools.asm.Opcodes; -import scala.tools.asm.Type; -import scala.tools.asm.tree.AbstractInsnNode; -import scala.tools.asm.tree.FieldInsnNode; -import scala.tools.asm.tree.IntInsnNode; -import scala.tools.asm.tree.InvokeDynamicInsnNode; -import scala.tools.asm.tree.LdcInsnNode; -import scala.tools.asm.tree.MethodInsnNode; -import scala.tools.asm.tree.MultiANewArrayInsnNode; -import scala.tools.asm.tree.TypeInsnNode; - -/** - * An {@link Interpreter} for {@link BasicValue} values. - * - * @author Eric Bruneton - * @author Bing Ran - */ -public class BasicInterpreter extends Interpreter<BasicValue> implements - Opcodes { - - public BasicInterpreter() { - super(ASM5); - } - - protected BasicInterpreter(final int api) { - super(api); - } - - @Override - public BasicValue newValue(final Type type) { - if (type == null) { - return BasicValue.UNINITIALIZED_VALUE; - } - switch (type.getSort()) { - case Type.VOID: - return null; - case Type.BOOLEAN: - case Type.CHAR: - case Type.BYTE: - case Type.SHORT: - case Type.INT: - return BasicValue.INT_VALUE; - case Type.FLOAT: - return BasicValue.FLOAT_VALUE; - case Type.LONG: - return BasicValue.LONG_VALUE; - case Type.DOUBLE: - return BasicValue.DOUBLE_VALUE; - case Type.ARRAY: - case Type.OBJECT: - return BasicValue.REFERENCE_VALUE; - default: - throw new Error("Internal error"); - } - } - - @Override - public BasicValue newOperation(final AbstractInsnNode insn) - throws AnalyzerException { - switch (insn.getOpcode()) { - case ACONST_NULL: - return newValue(Type.getObjectType("null")); - case ICONST_M1: - case ICONST_0: - case ICONST_1: - case ICONST_2: - case ICONST_3: - case ICONST_4: - case ICONST_5: - return BasicValue.INT_VALUE; - case LCONST_0: - case LCONST_1: - return BasicValue.LONG_VALUE; - case FCONST_0: - case FCONST_1: - case FCONST_2: - return BasicValue.FLOAT_VALUE; - case DCONST_0: - case DCONST_1: - return BasicValue.DOUBLE_VALUE; - case BIPUSH: - case SIPUSH: - return BasicValue.INT_VALUE; - case LDC: - Object cst = ((LdcInsnNode) insn).cst; - if (cst instanceof Integer) { - return BasicValue.INT_VALUE; - } else if (cst instanceof Float) { - return BasicValue.FLOAT_VALUE; - } else if (cst instanceof Long) { - return BasicValue.LONG_VALUE; - } else if (cst instanceof Double) { - return BasicValue.DOUBLE_VALUE; - } else if (cst instanceof String) { - return newValue(Type.getObjectType("java/lang/String")); - } else if (cst instanceof Type) { - int sort = ((Type) cst).getSort(); - if (sort == Type.OBJECT || sort == Type.ARRAY) { - return newValue(Type.getObjectType("java/lang/Class")); - } else if (sort == Type.METHOD) { - return newValue(Type - .getObjectType("java/lang/invoke/MethodType")); - } else { - throw new IllegalArgumentException("Illegal LDC constant " - + cst); - } - } else if (cst instanceof Handle) { - return newValue(Type - .getObjectType("java/lang/invoke/MethodHandle")); - } else { - throw new IllegalArgumentException("Illegal LDC constant " - + cst); - } - case JSR: - return BasicValue.RETURNADDRESS_VALUE; - case GETSTATIC: - return newValue(Type.getType(((FieldInsnNode) insn).desc)); - case NEW: - return newValue(Type.getObjectType(((TypeInsnNode) insn).desc)); - default: - throw new Error("Internal error."); - } - } - - @Override - public BasicValue copyOperation(final AbstractInsnNode insn, - final BasicValue value) throws AnalyzerException { - return value; - } - - @Override - public BasicValue unaryOperation(final AbstractInsnNode insn, - final BasicValue value) throws AnalyzerException { - switch (insn.getOpcode()) { - case INEG: - case IINC: - case L2I: - case F2I: - case D2I: - case I2B: - case I2C: - case I2S: - return BasicValue.INT_VALUE; - case FNEG: - case I2F: - case L2F: - case D2F: - return BasicValue.FLOAT_VALUE; - case LNEG: - case I2L: - case F2L: - case D2L: - return BasicValue.LONG_VALUE; - case DNEG: - case I2D: - case L2D: - case F2D: - return BasicValue.DOUBLE_VALUE; - case IFEQ: - case IFNE: - case IFLT: - case IFGE: - case IFGT: - case IFLE: - case TABLESWITCH: - case LOOKUPSWITCH: - case IRETURN: - case LRETURN: - case FRETURN: - case DRETURN: - case ARETURN: - case PUTSTATIC: - return null; - case GETFIELD: - return newValue(Type.getType(((FieldInsnNode) insn).desc)); - case NEWARRAY: - switch (((IntInsnNode) insn).operand) { - case T_BOOLEAN: - return newValue(Type.getType("[Z")); - case T_CHAR: - return newValue(Type.getType("[C")); - case T_BYTE: - return newValue(Type.getType("[B")); - case T_SHORT: - return newValue(Type.getType("[S")); - case T_INT: - return newValue(Type.getType("[I")); - case T_FLOAT: - return newValue(Type.getType("[F")); - case T_DOUBLE: - return newValue(Type.getType("[D")); - case T_LONG: - return newValue(Type.getType("[J")); - default: - throw new AnalyzerException(insn, "Invalid array type"); - } - case ANEWARRAY: - String desc = ((TypeInsnNode) insn).desc; - return newValue(Type.getType("[" + Type.getObjectType(desc))); - case ARRAYLENGTH: - return BasicValue.INT_VALUE; - case ATHROW: - return null; - case CHECKCAST: - desc = ((TypeInsnNode) insn).desc; - return newValue(Type.getObjectType(desc)); - case INSTANCEOF: - return BasicValue.INT_VALUE; - case MONITORENTER: - case MONITOREXIT: - case IFNULL: - case IFNONNULL: - return null; - default: - throw new Error("Internal error."); - } - } - - @Override - public BasicValue binaryOperation(final AbstractInsnNode insn, - final BasicValue value1, final BasicValue value2) - throws AnalyzerException { - switch (insn.getOpcode()) { - case IALOAD: - case BALOAD: - case CALOAD: - case SALOAD: - case IADD: - case ISUB: - case IMUL: - case IDIV: - case IREM: - case ISHL: - case ISHR: - case IUSHR: - case IAND: - case IOR: - case IXOR: - return BasicValue.INT_VALUE; - case FALOAD: - case FADD: - case FSUB: - case FMUL: - case FDIV: - case FREM: - return BasicValue.FLOAT_VALUE; - case LALOAD: - case LADD: - case LSUB: - case LMUL: - case LDIV: - case LREM: - case LSHL: - case LSHR: - case LUSHR: - case LAND: - case LOR: - case LXOR: - return BasicValue.LONG_VALUE; - case DALOAD: - case DADD: - case DSUB: - case DMUL: - case DDIV: - case DREM: - return BasicValue.DOUBLE_VALUE; - case AALOAD: - return BasicValue.REFERENCE_VALUE; - case LCMP: - case FCMPL: - case FCMPG: - case DCMPL: - case DCMPG: - return BasicValue.INT_VALUE; - case IF_ICMPEQ: - case IF_ICMPNE: - case IF_ICMPLT: - case IF_ICMPGE: - case IF_ICMPGT: - case IF_ICMPLE: - case IF_ACMPEQ: - case IF_ACMPNE: - case PUTFIELD: - return null; - default: - throw new Error("Internal error."); - } - } - - @Override - public BasicValue ternaryOperation(final AbstractInsnNode insn, - final BasicValue value1, final BasicValue value2, - final BasicValue value3) throws AnalyzerException { - return null; - } - - @Override - public BasicValue naryOperation(final AbstractInsnNode insn, - final List<? extends BasicValue> values) throws AnalyzerException { - int opcode = insn.getOpcode(); - if (opcode == MULTIANEWARRAY) { - return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); - } else if (opcode == INVOKEDYNAMIC) { - return newValue(Type - .getReturnType(((InvokeDynamicInsnNode) insn).desc)); - } else { - return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); - } - } - - @Override - public void returnOperation(final AbstractInsnNode insn, - final BasicValue value, final BasicValue expected) - throws AnalyzerException { - } - - @Override - public BasicValue merge(final BasicValue v, final BasicValue w) { - if (!v.equals(w)) { - return BasicValue.UNINITIALIZED_VALUE; - } - return v; - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/BasicValue.java b/src/asm/scala/tools/asm/tree/analysis/BasicValue.java deleted file mode 100644 index 439941fb9f..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/BasicValue.java +++ /dev/null @@ -1,111 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import scala.tools.asm.Type; - -/** - * A {@link Value} that is represented by its type in a seven types type system. - * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE, - * REFERENCE and RETURNADDRESS types. - * - * @author Eric Bruneton - */ -public class BasicValue implements Value { - - public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null); - - public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE); - - public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE); - - public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE); - - public static final BasicValue DOUBLE_VALUE = new BasicValue( - Type.DOUBLE_TYPE); - - public static final BasicValue REFERENCE_VALUE = new BasicValue( - Type.getObjectType("java/lang/Object")); - - public static final BasicValue RETURNADDRESS_VALUE = new BasicValue( - Type.VOID_TYPE); - - private final Type type; - - public BasicValue(final Type type) { - this.type = type; - } - - public Type getType() { - return type; - } - - public int getSize() { - return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1; - } - - public boolean isReference() { - return type != null - && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY); - } - - @Override - public boolean equals(final Object value) { - if (value == this) { - return true; - } else if (value instanceof BasicValue) { - if (type == null) { - return ((BasicValue) value).type == null; - } else { - return type.equals(((BasicValue) value).type); - } - } else { - return false; - } - } - - @Override - public int hashCode() { - return type == null ? 0 : type.hashCode(); - } - - @Override - public String toString() { - if (this == UNINITIALIZED_VALUE) { - return "."; - } else if (this == RETURNADDRESS_VALUE) { - return "A"; - } else if (this == REFERENCE_VALUE) { - return "R"; - } else { - return type.getDescriptor(); - } - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/BasicVerifier.java b/src/asm/scala/tools/asm/tree/analysis/BasicVerifier.java deleted file mode 100644 index b852f20acf..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/BasicVerifier.java +++ /dev/null @@ -1,433 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import java.util.List; - -import scala.tools.asm.Type; -import scala.tools.asm.tree.AbstractInsnNode; -import scala.tools.asm.tree.FieldInsnNode; -import scala.tools.asm.tree.InvokeDynamicInsnNode; -import scala.tools.asm.tree.MethodInsnNode; - -/** - * An extended {@link BasicInterpreter} that checks that bytecode instructions - * are correctly used. - * - * @author Eric Bruneton - * @author Bing Ran - */ -public class BasicVerifier extends BasicInterpreter { - - public BasicVerifier() { - super(ASM5); - } - - protected BasicVerifier(final int api) { - super(api); - } - - @Override - public BasicValue copyOperation(final AbstractInsnNode insn, - final BasicValue value) throws AnalyzerException { - Value expected; - switch (insn.getOpcode()) { - case ILOAD: - case ISTORE: - expected = BasicValue.INT_VALUE; - break; - case FLOAD: - case FSTORE: - expected = BasicValue.FLOAT_VALUE; - break; - case LLOAD: - case LSTORE: - expected = BasicValue.LONG_VALUE; - break; - case DLOAD: - case DSTORE: - expected = BasicValue.DOUBLE_VALUE; - break; - case ALOAD: - if (!value.isReference()) { - throw new AnalyzerException(insn, null, "an object reference", - value); - } - return value; - case ASTORE: - if (!value.isReference() - && !BasicValue.RETURNADDRESS_VALUE.equals(value)) { - throw new AnalyzerException(insn, null, - "an object reference or a return address", value); - } - return value; - default: - return value; - } - if (!expected.equals(value)) { - throw new AnalyzerException(insn, null, expected, value); - } - return value; - } - - @Override - public BasicValue unaryOperation(final AbstractInsnNode insn, - final BasicValue value) throws AnalyzerException { - BasicValue expected; - switch (insn.getOpcode()) { - case INEG: - case IINC: - case I2F: - case I2L: - case I2D: - case I2B: - case I2C: - case I2S: - case IFEQ: - case IFNE: - case IFLT: - case IFGE: - case IFGT: - case IFLE: - case TABLESWITCH: - case LOOKUPSWITCH: - case IRETURN: - case NEWARRAY: - case ANEWARRAY: - expected = BasicValue.INT_VALUE; - break; - case FNEG: - case F2I: - case F2L: - case F2D: - case FRETURN: - expected = BasicValue.FLOAT_VALUE; - break; - case LNEG: - case L2I: - case L2F: - case L2D: - case LRETURN: - expected = BasicValue.LONG_VALUE; - break; - case DNEG: - case D2I: - case D2F: - case D2L: - case DRETURN: - expected = BasicValue.DOUBLE_VALUE; - break; - case GETFIELD: - expected = newValue(Type - .getObjectType(((FieldInsnNode) insn).owner)); - break; - case CHECKCAST: - if (!value.isReference()) { - throw new AnalyzerException(insn, null, "an object reference", - value); - } - return super.unaryOperation(insn, value); - case ARRAYLENGTH: - if (!isArrayValue(value)) { - throw new AnalyzerException(insn, null, "an array reference", - value); - } - return super.unaryOperation(insn, value); - case ARETURN: - case ATHROW: - case INSTANCEOF: - case MONITORENTER: - case MONITOREXIT: - case IFNULL: - case IFNONNULL: - if (!value.isReference()) { - throw new AnalyzerException(insn, null, "an object reference", - value); - } - return super.unaryOperation(insn, value); - case PUTSTATIC: - expected = newValue(Type.getType(((FieldInsnNode) insn).desc)); - break; - default: - throw new Error("Internal error."); - } - if (!isSubTypeOf(value, expected)) { - throw new AnalyzerException(insn, null, expected, value); - } - return super.unaryOperation(insn, value); - } - - @Override - public BasicValue binaryOperation(final AbstractInsnNode insn, - final BasicValue value1, final BasicValue value2) - throws AnalyzerException { - BasicValue expected1; - BasicValue expected2; - switch (insn.getOpcode()) { - case IALOAD: - expected1 = newValue(Type.getType("[I")); - expected2 = BasicValue.INT_VALUE; - break; - case BALOAD: - if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) { - expected1 = newValue(Type.getType("[Z")); - } else { - expected1 = newValue(Type.getType("[B")); - } - expected2 = BasicValue.INT_VALUE; - break; - case CALOAD: - expected1 = newValue(Type.getType("[C")); - expected2 = BasicValue.INT_VALUE; - break; - case SALOAD: - expected1 = newValue(Type.getType("[S")); - expected2 = BasicValue.INT_VALUE; - break; - case LALOAD: - expected1 = newValue(Type.getType("[J")); - expected2 = BasicValue.INT_VALUE; - break; - case FALOAD: - expected1 = newValue(Type.getType("[F")); - expected2 = BasicValue.INT_VALUE; - break; - case DALOAD: - expected1 = newValue(Type.getType("[D")); - expected2 = BasicValue.INT_VALUE; - break; - case AALOAD: - expected1 = newValue(Type.getType("[Ljava/lang/Object;")); - expected2 = BasicValue.INT_VALUE; - break; - case IADD: - case ISUB: - case IMUL: - case IDIV: - case IREM: - case ISHL: - case ISHR: - case IUSHR: - case IAND: - case IOR: - case IXOR: - case IF_ICMPEQ: - case IF_ICMPNE: - case IF_ICMPLT: - case IF_ICMPGE: - case IF_ICMPGT: - case IF_ICMPLE: - expected1 = BasicValue.INT_VALUE; - expected2 = BasicValue.INT_VALUE; - break; - case FADD: - case FSUB: - case FMUL: - case FDIV: - case FREM: - case FCMPL: - case FCMPG: - expected1 = BasicValue.FLOAT_VALUE; - expected2 = BasicValue.FLOAT_VALUE; - break; - case LADD: - case LSUB: - case LMUL: - case LDIV: - case LREM: - case LAND: - case LOR: - case LXOR: - case LCMP: - expected1 = BasicValue.LONG_VALUE; - expected2 = BasicValue.LONG_VALUE; - break; - case LSHL: - case LSHR: - case LUSHR: - expected1 = BasicValue.LONG_VALUE; - expected2 = BasicValue.INT_VALUE; - break; - case DADD: - case DSUB: - case DMUL: - case DDIV: - case DREM: - case DCMPL: - case DCMPG: - expected1 = BasicValue.DOUBLE_VALUE; - expected2 = BasicValue.DOUBLE_VALUE; - break; - case IF_ACMPEQ: - case IF_ACMPNE: - expected1 = BasicValue.REFERENCE_VALUE; - expected2 = BasicValue.REFERENCE_VALUE; - break; - case PUTFIELD: - FieldInsnNode fin = (FieldInsnNode) insn; - expected1 = newValue(Type.getObjectType(fin.owner)); - expected2 = newValue(Type.getType(fin.desc)); - break; - default: - throw new Error("Internal error."); - } - if (!isSubTypeOf(value1, expected1)) { - throw new AnalyzerException(insn, "First argument", expected1, - value1); - } else if (!isSubTypeOf(value2, expected2)) { - throw new AnalyzerException(insn, "Second argument", expected2, - value2); - } - if (insn.getOpcode() == AALOAD) { - return getElementValue(value1); - } else { - return super.binaryOperation(insn, value1, value2); - } - } - - @Override - public BasicValue ternaryOperation(final AbstractInsnNode insn, - final BasicValue value1, final BasicValue value2, - final BasicValue value3) throws AnalyzerException { - BasicValue expected1; - BasicValue expected3; - switch (insn.getOpcode()) { - case IASTORE: - expected1 = newValue(Type.getType("[I")); - expected3 = BasicValue.INT_VALUE; - break; - case BASTORE: - if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) { - expected1 = newValue(Type.getType("[Z")); - } else { - expected1 = newValue(Type.getType("[B")); - } - expected3 = BasicValue.INT_VALUE; - break; - case CASTORE: - expected1 = newValue(Type.getType("[C")); - expected3 = BasicValue.INT_VALUE; - break; - case SASTORE: - expected1 = newValue(Type.getType("[S")); - expected3 = BasicValue.INT_VALUE; - break; - case LASTORE: - expected1 = newValue(Type.getType("[J")); - expected3 = BasicValue.LONG_VALUE; - break; - case FASTORE: - expected1 = newValue(Type.getType("[F")); - expected3 = BasicValue.FLOAT_VALUE; - break; - case DASTORE: - expected1 = newValue(Type.getType("[D")); - expected3 = BasicValue.DOUBLE_VALUE; - break; - case AASTORE: - expected1 = value1; - expected3 = BasicValue.REFERENCE_VALUE; - break; - default: - throw new Error("Internal error."); - } - if (!isSubTypeOf(value1, expected1)) { - throw new AnalyzerException(insn, "First argument", "a " - + expected1 + " array reference", value1); - } else if (!BasicValue.INT_VALUE.equals(value2)) { - throw new AnalyzerException(insn, "Second argument", - BasicValue.INT_VALUE, value2); - } else if (!isSubTypeOf(value3, expected3)) { - throw new AnalyzerException(insn, "Third argument", expected3, - value3); - } - return null; - } - - @Override - public BasicValue naryOperation(final AbstractInsnNode insn, - final List<? extends BasicValue> values) throws AnalyzerException { - int opcode = insn.getOpcode(); - if (opcode == MULTIANEWARRAY) { - for (int i = 0; i < values.size(); ++i) { - if (!BasicValue.INT_VALUE.equals(values.get(i))) { - throw new AnalyzerException(insn, null, - BasicValue.INT_VALUE, values.get(i)); - } - } - } else { - int i = 0; - int j = 0; - if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) { - Type owner = Type.getObjectType(((MethodInsnNode) insn).owner); - if (!isSubTypeOf(values.get(i++), newValue(owner))) { - throw new AnalyzerException(insn, "Method owner", - newValue(owner), values.get(0)); - } - } - String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc - : ((MethodInsnNode) insn).desc; - Type[] args = Type.getArgumentTypes(desc); - while (i < values.size()) { - BasicValue expected = newValue(args[j++]); - BasicValue encountered = values.get(i++); - if (!isSubTypeOf(encountered, expected)) { - throw new AnalyzerException(insn, "Argument " + j, - expected, encountered); - } - } - } - return super.naryOperation(insn, values); - } - - @Override - public void returnOperation(final AbstractInsnNode insn, - final BasicValue value, final BasicValue expected) - throws AnalyzerException { - if (!isSubTypeOf(value, expected)) { - throw new AnalyzerException(insn, "Incompatible return type", - expected, value); - } - } - - protected boolean isArrayValue(final BasicValue value) { - return value.isReference(); - } - - protected BasicValue getElementValue(final BasicValue objectArrayValue) - throws AnalyzerException { - return BasicValue.REFERENCE_VALUE; - } - - protected boolean isSubTypeOf(final BasicValue value, - final BasicValue expected) { - return value.equals(expected); - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/Frame.java b/src/asm/scala/tools/asm/tree/analysis/Frame.java deleted file mode 100644 index 0b7f4ba53b..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/Frame.java +++ /dev/null @@ -1,738 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import java.util.ArrayList; -import java.util.List; - -import scala.tools.asm.Opcodes; -import scala.tools.asm.Type; -import scala.tools.asm.tree.AbstractInsnNode; -import scala.tools.asm.tree.IincInsnNode; -import scala.tools.asm.tree.InvokeDynamicInsnNode; -import scala.tools.asm.tree.MethodInsnNode; -import scala.tools.asm.tree.MultiANewArrayInsnNode; -import scala.tools.asm.tree.VarInsnNode; - -/** - * A symbolic execution stack frame. A stack frame contains a set of local - * variable slots, and an operand stack. Warning: long and double values are - * represented by <i>two</i> slots in local variables, and by <i>one</i> slot in - * the operand stack. - * - * @param <V> - * type of the Value used for the analysis. - * - * @author Eric Bruneton - */ -public class Frame<V extends Value> { - - /** - * The expected return type of the analyzed method, or <tt>null</tt> if the - * method returns void. - */ - private V returnValue; - - /** - * The local variables and operand stack of this frame. - */ - private V[] values; - - /** - * The number of local variables of this frame. - */ - private int locals; - - /** - * The number of elements in the operand stack. - */ - private int top; - - /** - * Constructs a new frame with the given size. - * - * @param nLocals - * the maximum number of local variables of the frame. - * @param nStack - * the maximum stack size of the frame. - */ - public Frame(final int nLocals, final int nStack) { - this.values = (V[]) new Value[nLocals + nStack]; - this.locals = nLocals; - } - - /** - * Constructs a new frame that is identical to the given frame. - * - * @param src - * a frame. - */ - public Frame(final Frame<? extends V> src) { - this(src.locals, src.values.length - src.locals); - init(src); - } - - /** - * Copies the state of the given frame into this frame. - * - * @param src - * a frame. - * @return this frame. - */ - public Frame<V> init(final Frame<? extends V> src) { - returnValue = src.returnValue; - System.arraycopy(src.values, 0, values, 0, values.length); - top = src.top; - return this; - } - - /** - * Sets the expected return type of the analyzed method. - * - * @param v - * the expected return type of the analyzed method, or - * <tt>null</tt> if the method returns void. - */ - public void setReturn(final V v) { - returnValue = v; - } - - /** - * Returns the maximum number of local variables of this frame. - * - * @return the maximum number of local variables of this frame. - */ - public int getLocals() { - return locals; - } - - /** - * Returns the maximum stack size of this frame. - * - * @return the maximum stack size of this frame. - */ - public int getMaxStackSize() { - return values.length - locals; - } - - /** - * Returns the value of the given local variable. - * - * @param i - * a local variable index. - * @return the value of the given local variable. - * @throws IndexOutOfBoundsException - * if the variable does not exist. - */ - public V getLocal(final int i) throws IndexOutOfBoundsException { - if (i >= locals) { - throw new IndexOutOfBoundsException( - "Trying to access an inexistant local variable"); - } - return values[i]; - } - - /** - * Sets the value of the given local variable. - * - * @param i - * a local variable index. - * @param value - * the new value of this local variable. - * @throws IndexOutOfBoundsException - * if the variable does not exist. - */ - public void setLocal(final int i, final V value) - throws IndexOutOfBoundsException { - if (i >= locals) { - throw new IndexOutOfBoundsException( - "Trying to access an inexistant local variable " + i); - } - values[i] = value; - } - - /** - * Returns the number of values in the operand stack of this frame. Long and - * double values are treated as single values. - * - * @return the number of values in the operand stack of this frame. - */ - public int getStackSize() { - return top; - } - - /** - * Returns the value of the given operand stack slot. - * - * @param i - * the index of an operand stack slot. - * @return the value of the given operand stack slot. - * @throws IndexOutOfBoundsException - * if the operand stack slot does not exist. - */ - public V getStack(final int i) throws IndexOutOfBoundsException { - return values[i + locals]; - } - - /** - * Clears the operand stack of this frame. - */ - public void clearStack() { - top = 0; - } - - /** - * Pops a value from the operand stack of this frame. - * - * @return the value that has been popped from the stack. - * @throws IndexOutOfBoundsException - * if the operand stack is empty. - */ - public V pop() throws IndexOutOfBoundsException { - if (top == 0) { - throw new IndexOutOfBoundsException( - "Cannot pop operand off an empty stack."); - } - return values[--top + locals]; - } - - /** - * Pushes a value into the operand stack of this frame. - * - * @param value - * the value that must be pushed into the stack. - * @throws IndexOutOfBoundsException - * if the operand stack is full. - */ - public void push(final V value) throws IndexOutOfBoundsException { - if (top + locals >= values.length) { - throw new IndexOutOfBoundsException( - "Insufficient maximum stack size."); - } - values[top++ + locals] = value; - } - - public void execute(final AbstractInsnNode insn, - final Interpreter<V> interpreter) throws AnalyzerException { - V value1, value2, value3, value4; - List<V> values; - int var; - - switch (insn.getOpcode()) { - case Opcodes.NOP: - break; - case Opcodes.ACONST_NULL: - case Opcodes.ICONST_M1: - case Opcodes.ICONST_0: - case Opcodes.ICONST_1: - case Opcodes.ICONST_2: - case Opcodes.ICONST_3: - case Opcodes.ICONST_4: - case Opcodes.ICONST_5: - case Opcodes.LCONST_0: - case Opcodes.LCONST_1: - case Opcodes.FCONST_0: - case Opcodes.FCONST_1: - case Opcodes.FCONST_2: - case Opcodes.DCONST_0: - case Opcodes.DCONST_1: - case Opcodes.BIPUSH: - case Opcodes.SIPUSH: - case Opcodes.LDC: - push(interpreter.newOperation(insn)); - break; - case Opcodes.ILOAD: - case Opcodes.LLOAD: - case Opcodes.FLOAD: - case Opcodes.DLOAD: - case Opcodes.ALOAD: - push(interpreter.copyOperation(insn, - getLocal(((VarInsnNode) insn).var))); - break; - case Opcodes.IALOAD: - case Opcodes.LALOAD: - case Opcodes.FALOAD: - case Opcodes.DALOAD: - case Opcodes.AALOAD: - case Opcodes.BALOAD: - case Opcodes.CALOAD: - case Opcodes.SALOAD: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.ISTORE: - case Opcodes.LSTORE: - case Opcodes.FSTORE: - case Opcodes.DSTORE: - case Opcodes.ASTORE: - value1 = interpreter.copyOperation(insn, pop()); - var = ((VarInsnNode) insn).var; - setLocal(var, value1); - if (value1.getSize() == 2) { - setLocal(var + 1, interpreter.newValue(null)); - } - if (var > 0) { - Value local = getLocal(var - 1); - if (local != null && local.getSize() == 2) { - setLocal(var - 1, interpreter.newValue(null)); - } - } - break; - case Opcodes.IASTORE: - case Opcodes.LASTORE: - case Opcodes.FASTORE: - case Opcodes.DASTORE: - case Opcodes.AASTORE: - case Opcodes.BASTORE: - case Opcodes.CASTORE: - case Opcodes.SASTORE: - value3 = pop(); - value2 = pop(); - value1 = pop(); - interpreter.ternaryOperation(insn, value1, value2, value3); - break; - case Opcodes.POP: - if (pop().getSize() == 2) { - throw new AnalyzerException(insn, "Illegal use of POP"); - } - break; - case Opcodes.POP2: - if (pop().getSize() == 1) { - if (pop().getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of POP2"); - } - } - break; - case Opcodes.DUP: - value1 = pop(); - if (value1.getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of DUP"); - } - push(value1); - push(interpreter.copyOperation(insn, value1)); - break; - case Opcodes.DUP_X1: - value1 = pop(); - value2 = pop(); - if (value1.getSize() != 1 || value2.getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of DUP_X1"); - } - push(interpreter.copyOperation(insn, value1)); - push(value2); - push(value1); - break; - case Opcodes.DUP_X2: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { - push(interpreter.copyOperation(insn, value1)); - push(value3); - push(value2); - push(value1); - break; - } - } else { - push(interpreter.copyOperation(insn, value1)); - push(value2); - push(value1); - break; - } - } - throw new AnalyzerException(insn, "Illegal use of DUP_X2"); - case Opcodes.DUP2: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - push(value2); - push(value1); - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - break; - } - } else { - push(value1); - push(interpreter.copyOperation(insn, value1)); - break; - } - throw new AnalyzerException(insn, "Illegal use of DUP2"); - case Opcodes.DUP2_X1: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - push(value3); - push(value2); - push(value1); - break; - } - } - } else { - value2 = pop(); - if (value2.getSize() == 1) { - push(interpreter.copyOperation(insn, value1)); - push(value2); - push(value1); - break; - } - } - throw new AnalyzerException(insn, "Illegal use of DUP2_X1"); - case Opcodes.DUP2_X2: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { - value4 = pop(); - if (value4.getSize() == 1) { - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - push(value4); - push(value3); - push(value2); - push(value1); - break; - } - } else { - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - push(value3); - push(value2); - push(value1); - break; - } - } - } else { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { - push(interpreter.copyOperation(insn, value1)); - push(value3); - push(value2); - push(value1); - break; - } - } else { - push(interpreter.copyOperation(insn, value1)); - push(value2); - push(value1); - break; - } - } - throw new AnalyzerException(insn, "Illegal use of DUP2_X2"); - case Opcodes.SWAP: - value2 = pop(); - value1 = pop(); - if (value1.getSize() != 1 || value2.getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of SWAP"); - } - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - break; - case Opcodes.IADD: - case Opcodes.LADD: - case Opcodes.FADD: - case Opcodes.DADD: - case Opcodes.ISUB: - case Opcodes.LSUB: - case Opcodes.FSUB: - case Opcodes.DSUB: - case Opcodes.IMUL: - case Opcodes.LMUL: - case Opcodes.FMUL: - case Opcodes.DMUL: - case Opcodes.IDIV: - case Opcodes.LDIV: - case Opcodes.FDIV: - case Opcodes.DDIV: - case Opcodes.IREM: - case Opcodes.LREM: - case Opcodes.FREM: - case Opcodes.DREM: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.INEG: - case Opcodes.LNEG: - case Opcodes.FNEG: - case Opcodes.DNEG: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.ISHL: - case Opcodes.LSHL: - case Opcodes.ISHR: - case Opcodes.LSHR: - case Opcodes.IUSHR: - case Opcodes.LUSHR: - case Opcodes.IAND: - case Opcodes.LAND: - case Opcodes.IOR: - case Opcodes.LOR: - case Opcodes.IXOR: - case Opcodes.LXOR: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.IINC: - var = ((IincInsnNode) insn).var; - setLocal(var, interpreter.unaryOperation(insn, getLocal(var))); - break; - case Opcodes.I2L: - case Opcodes.I2F: - case Opcodes.I2D: - case Opcodes.L2I: - case Opcodes.L2F: - case Opcodes.L2D: - case Opcodes.F2I: - case Opcodes.F2L: - case Opcodes.F2D: - case Opcodes.D2I: - case Opcodes.D2L: - case Opcodes.D2F: - case Opcodes.I2B: - case Opcodes.I2C: - case Opcodes.I2S: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.LCMP: - case Opcodes.FCMPL: - case Opcodes.FCMPG: - case Opcodes.DCMPL: - case Opcodes.DCMPG: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.IFEQ: - case Opcodes.IFNE: - case Opcodes.IFLT: - case Opcodes.IFGE: - case Opcodes.IFGT: - case Opcodes.IFLE: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.IF_ICMPEQ: - case Opcodes.IF_ICMPNE: - case Opcodes.IF_ICMPLT: - case Opcodes.IF_ICMPGE: - case Opcodes.IF_ICMPGT: - case Opcodes.IF_ICMPLE: - case Opcodes.IF_ACMPEQ: - case Opcodes.IF_ACMPNE: - value2 = pop(); - value1 = pop(); - interpreter.binaryOperation(insn, value1, value2); - break; - case Opcodes.GOTO: - break; - case Opcodes.JSR: - push(interpreter.newOperation(insn)); - break; - case Opcodes.RET: - break; - case Opcodes.TABLESWITCH: - case Opcodes.LOOKUPSWITCH: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.IRETURN: - case Opcodes.LRETURN: - case Opcodes.FRETURN: - case Opcodes.DRETURN: - case Opcodes.ARETURN: - value1 = pop(); - interpreter.unaryOperation(insn, value1); - interpreter.returnOperation(insn, value1, returnValue); - break; - case Opcodes.RETURN: - if (returnValue != null) { - throw new AnalyzerException(insn, "Incompatible return type"); - } - break; - case Opcodes.GETSTATIC: - push(interpreter.newOperation(insn)); - break; - case Opcodes.PUTSTATIC: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.GETFIELD: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.PUTFIELD: - value2 = pop(); - value1 = pop(); - interpreter.binaryOperation(insn, value1, value2); - break; - case Opcodes.INVOKEVIRTUAL: - case Opcodes.INVOKESPECIAL: - case Opcodes.INVOKESTATIC: - case Opcodes.INVOKEINTERFACE: { - values = new ArrayList<V>(); - String desc = ((MethodInsnNode) insn).desc; - for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { - values.add(0, pop()); - } - if (insn.getOpcode() != Opcodes.INVOKESTATIC) { - values.add(0, pop()); - } - if (Type.getReturnType(desc) == Type.VOID_TYPE) { - interpreter.naryOperation(insn, values); - } else { - push(interpreter.naryOperation(insn, values)); - } - break; - } - case Opcodes.INVOKEDYNAMIC: { - values = new ArrayList<V>(); - String desc = ((InvokeDynamicInsnNode) insn).desc; - for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { - values.add(0, pop()); - } - if (Type.getReturnType(desc) == Type.VOID_TYPE) { - interpreter.naryOperation(insn, values); - } else { - push(interpreter.naryOperation(insn, values)); - } - break; - } - case Opcodes.NEW: - push(interpreter.newOperation(insn)); - break; - case Opcodes.NEWARRAY: - case Opcodes.ANEWARRAY: - case Opcodes.ARRAYLENGTH: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.ATHROW: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.CHECKCAST: - case Opcodes.INSTANCEOF: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.MONITORENTER: - case Opcodes.MONITOREXIT: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.MULTIANEWARRAY: - values = new ArrayList<V>(); - for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) { - values.add(0, pop()); - } - push(interpreter.naryOperation(insn, values)); - break; - case Opcodes.IFNULL: - case Opcodes.IFNONNULL: - interpreter.unaryOperation(insn, pop()); - break; - default: - throw new RuntimeException("Illegal opcode " + insn.getOpcode()); - } - } - - /** - * Merges this frame with the given frame. - * - * @param frame - * a frame. - * @param interpreter - * the interpreter used to merge values. - * @return <tt>true</tt> if this frame has been changed as a result of the - * merge operation, or <tt>false</tt> otherwise. - * @throws AnalyzerException - * if the frames have incompatible sizes. - */ - public boolean merge(final Frame<? extends V> frame, - final Interpreter<V> interpreter) throws AnalyzerException { - if (top != frame.top) { - throw new AnalyzerException(null, "Incompatible stack heights"); - } - boolean changes = false; - for (int i = 0; i < locals + top; ++i) { - V v = interpreter.merge(values[i], frame.values[i]); - if (!v.equals(values[i])) { - values[i] = v; - changes = true; - } - } - return changes; - } - - /** - * Merges this frame with the given frame (case of a RET instruction). - * - * @param frame - * a frame - * @param access - * the local variables that have been accessed by the subroutine - * to which the RET instruction corresponds. - * @return <tt>true</tt> if this frame has been changed as a result of the - * merge operation, or <tt>false</tt> otherwise. - */ - public boolean merge(final Frame<? extends V> frame, final boolean[] access) { - boolean changes = false; - for (int i = 0; i < locals; ++i) { - if (!access[i] && !values[i].equals(frame.values[i])) { - values[i] = frame.values[i]; - changes = true; - } - } - return changes; - } - - /** - * Returns a string representation of this frame. - * - * @return a string representation of this frame. - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < getLocals(); ++i) { - sb.append(getLocal(i)); - } - sb.append(' '); - for (int i = 0; i < getStackSize(); ++i) { - sb.append(getStack(i).toString()); - } - return sb.toString(); - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/Interpreter.java b/src/asm/scala/tools/asm/tree/analysis/Interpreter.java deleted file mode 100644 index 00fe6c8bff..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/Interpreter.java +++ /dev/null @@ -1,226 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import java.util.List; - -import scala.tools.asm.Type; -import scala.tools.asm.tree.AbstractInsnNode; - -/** - * A semantic bytecode interpreter. More precisely, this interpreter only - * manages the computation of values from other values: it does not manage the - * transfer of values to or from the stack, and to or from the local variables. - * This separation allows a generic bytecode {@link Analyzer} to work with - * various semantic interpreters, without needing to duplicate the code to - * simulate the transfer of values. - * - * @param <V> - * type of the Value used for the analysis. - * - * @author Eric Bruneton - */ -public abstract class Interpreter<V extends Value> { - - protected final int api; - - protected Interpreter(final int api) { - this.api = api; - } - - /** - * Creates a new value that represents the given type. - * - * Called for method parameters (including <code>this</code>), exception - * handler variable and with <code>null</code> type for variables reserved - * by long and double types. - * - * @param type - * a primitive or reference type, or <tt>null</tt> to represent - * an uninitialized value. - * @return a value that represents the given type. The size of the returned - * value must be equal to the size of the given type. - */ - public abstract V newValue(Type type); - - /** - * Interprets a bytecode instruction without arguments. This method is - * called for the following opcodes: - * - * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, - * ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, - * DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW - * - * @param insn - * the bytecode instruction to be interpreted. - * @return the result of the interpretation of the given instruction. - * @throws AnalyzerException - * if an error occurred during the interpretation. - */ - public abstract V newOperation(AbstractInsnNode insn) - throws AnalyzerException; - - /** - * Interprets a bytecode instruction that moves a value on the stack or to - * or from local variables. This method is called for the following opcodes: - * - * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, - * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP - * - * @param insn - * the bytecode instruction to be interpreted. - * @param value - * the value that must be moved by the instruction. - * @return the result of the interpretation of the given instruction. The - * returned value must be <tt>equal</tt> to the given value. - * @throws AnalyzerException - * if an error occurred during the interpretation. - */ - public abstract V copyOperation(AbstractInsnNode insn, V value) - throws AnalyzerException; - - /** - * Interprets a bytecode instruction with a single argument. This method is - * called for the following opcodes: - * - * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, - * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, - * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, - * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST, - * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL - * - * @param insn - * the bytecode instruction to be interpreted. - * @param value - * the argument of the instruction to be interpreted. - * @return the result of the interpretation of the given instruction. - * @throws AnalyzerException - * if an error occurred during the interpretation. - */ - public abstract V unaryOperation(AbstractInsnNode insn, V value) - throws AnalyzerException; - - /** - * Interprets a bytecode instruction with two arguments. This method is - * called for the following opcodes: - * - * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD, - * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, - * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR, - * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL, - * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, - * IF_ACMPEQ, IF_ACMPNE, PUTFIELD - * - * @param insn - * the bytecode instruction to be interpreted. - * @param value1 - * the first argument of the instruction to be interpreted. - * @param value2 - * the second argument of the instruction to be interpreted. - * @return the result of the interpretation of the given instruction. - * @throws AnalyzerException - * if an error occurred during the interpretation. - */ - public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2) - throws AnalyzerException; - - /** - * Interprets a bytecode instruction with three arguments. This method is - * called for the following opcodes: - * - * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE - * - * @param insn - * the bytecode instruction to be interpreted. - * @param value1 - * the first argument of the instruction to be interpreted. - * @param value2 - * the second argument of the instruction to be interpreted. - * @param value3 - * the third argument of the instruction to be interpreted. - * @return the result of the interpretation of the given instruction. - * @throws AnalyzerException - * if an error occurred during the interpretation. - */ - public abstract V ternaryOperation(AbstractInsnNode insn, V value1, - V value2, V value3) throws AnalyzerException; - - /** - * Interprets a bytecode instruction with a variable number of arguments. - * This method is called for the following opcodes: - * - * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE, - * MULTIANEWARRAY and INVOKEDYNAMIC - * - * @param insn - * the bytecode instruction to be interpreted. - * @param values - * the arguments of the instruction to be interpreted. - * @return the result of the interpretation of the given instruction. - * @throws AnalyzerException - * if an error occurred during the interpretation. - */ - public abstract V naryOperation(AbstractInsnNode insn, - List<? extends V> values) throws AnalyzerException; - - /** - * Interprets a bytecode return instruction. This method is called for the - * following opcodes: - * - * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN - * - * @param insn - * the bytecode instruction to be interpreted. - * @param value - * the argument of the instruction to be interpreted. - * @param expected - * the expected return type of the analyzed method. - * @throws AnalyzerException - * if an error occurred during the interpretation. - */ - public abstract void returnOperation(AbstractInsnNode insn, V value, - V expected) throws AnalyzerException; - - /** - * Merges two values. The merge operation must return a value that - * represents both values (for instance, if the two values are two types, - * the merged value must be a common super type of the two types. If the two - * values are integer intervals, the merged value must be an interval that - * contains the previous ones. Likewise for other types of values). - * - * @param v - * a value. - * @param w - * another value. - * @return the merged value. If the merged value is equal to <tt>v</tt>, - * this method <i>must</i> return <tt>v</tt>. - */ - public abstract V merge(V v, V w); -} diff --git a/src/asm/scala/tools/asm/tree/analysis/SimpleVerifier.java b/src/asm/scala/tools/asm/tree/analysis/SimpleVerifier.java deleted file mode 100644 index a345981f36..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/SimpleVerifier.java +++ /dev/null @@ -1,320 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import java.util.List; - -import scala.tools.asm.Type; - -/** - * An extended {@link BasicVerifier} that performs more precise verifications. - * This verifier computes exact class types, instead of using a single "object - * reference" type (as done in the {@link BasicVerifier}). - * - * @author Eric Bruneton - * @author Bing Ran - */ -public class SimpleVerifier extends BasicVerifier { - - /** - * The class that is verified. - */ - private final Type currentClass; - - /** - * The super class of the class that is verified. - */ - private final Type currentSuperClass; - - /** - * The interfaces implemented by the class that is verified. - */ - private final List<Type> currentClassInterfaces; - - /** - * If the class that is verified is an interface. - */ - private final boolean isInterface; - - /** - * The loader to use for referenced classes. - */ - private ClassLoader loader = getClass().getClassLoader(); - - /** - * Constructs a new {@link SimpleVerifier}. - */ - public SimpleVerifier() { - this(null, null, false); - } - - /** - * Constructs a new {@link SimpleVerifier} to verify a specific class. This - * class will not be loaded into the JVM since it may be incorrect. - * - * @param currentClass - * the class that is verified. - * @param currentSuperClass - * the super class of the class that is verified. - * @param isInterface - * if the class that is verified is an interface. - */ - public SimpleVerifier(final Type currentClass, - final Type currentSuperClass, final boolean isInterface) { - this(currentClass, currentSuperClass, null, isInterface); - } - - /** - * Constructs a new {@link SimpleVerifier} to verify a specific class. This - * class will not be loaded into the JVM since it may be incorrect. - * - * @param currentClass - * the class that is verified. - * @param currentSuperClass - * the super class of the class that is verified. - * @param currentClassInterfaces - * the interfaces implemented by the class that is verified. - * @param isInterface - * if the class that is verified is an interface. - */ - public SimpleVerifier(final Type currentClass, - final Type currentSuperClass, - final List<Type> currentClassInterfaces, final boolean isInterface) { - this(ASM5, currentClass, currentSuperClass, currentClassInterfaces, - isInterface); - } - - protected SimpleVerifier(final int api, final Type currentClass, - final Type currentSuperClass, - final List<Type> currentClassInterfaces, final boolean isInterface) { - super(api); - this.currentClass = currentClass; - this.currentSuperClass = currentSuperClass; - this.currentClassInterfaces = currentClassInterfaces; - this.isInterface = isInterface; - } - - /** - * Set the <code>ClassLoader</code> which will be used to load referenced - * classes. This is useful if you are verifying multiple interdependent - * classes. - * - * @param loader - * a <code>ClassLoader</code> to use - */ - public void setClassLoader(final ClassLoader loader) { - this.loader = loader; - } - - @Override - public BasicValue newValue(final Type type) { - if (type == null) { - return BasicValue.UNINITIALIZED_VALUE; - } - - boolean isArray = type.getSort() == Type.ARRAY; - if (isArray) { - switch (type.getElementType().getSort()) { - case Type.BOOLEAN: - case Type.CHAR: - case Type.BYTE: - case Type.SHORT: - return new BasicValue(type); - } - } - - BasicValue v = super.newValue(type); - if (BasicValue.REFERENCE_VALUE.equals(v)) { - if (isArray) { - v = newValue(type.getElementType()); - String desc = v.getType().getDescriptor(); - for (int i = 0; i < type.getDimensions(); ++i) { - desc = '[' + desc; - } - v = new BasicValue(Type.getType(desc)); - } else { - v = new BasicValue(type); - } - } - return v; - } - - @Override - protected boolean isArrayValue(final BasicValue value) { - Type t = value.getType(); - return t != null - && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY); - } - - @Override - protected BasicValue getElementValue(final BasicValue objectArrayValue) - throws AnalyzerException { - Type arrayType = objectArrayValue.getType(); - if (arrayType != null) { - if (arrayType.getSort() == Type.ARRAY) { - return newValue(Type.getType(arrayType.getDescriptor() - .substring(1))); - } else if ("Lnull;".equals(arrayType.getDescriptor())) { - return objectArrayValue; - } - } - throw new Error("Internal error"); - } - - @Override - protected boolean isSubTypeOf(final BasicValue value, - final BasicValue expected) { - Type expectedType = expected.getType(); - Type type = value.getType(); - switch (expectedType.getSort()) { - case Type.INT: - case Type.FLOAT: - case Type.LONG: - case Type.DOUBLE: - return type.equals(expectedType); - case Type.ARRAY: - case Type.OBJECT: - if ("Lnull;".equals(type.getDescriptor())) { - return true; - } else if (type.getSort() == Type.OBJECT - || type.getSort() == Type.ARRAY) { - return isAssignableFrom(expectedType, type); - } else { - return false; - } - default: - throw new Error("Internal error"); - } - } - - @Override - public BasicValue merge(final BasicValue v, final BasicValue w) { - if (!v.equals(w)) { - Type t = v.getType(); - Type u = w.getType(); - if (t != null - && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) { - if (u != null - && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) { - if ("Lnull;".equals(t.getDescriptor())) { - return w; - } - if ("Lnull;".equals(u.getDescriptor())) { - return v; - } - if (isAssignableFrom(t, u)) { - return v; - } - if (isAssignableFrom(u, t)) { - return w; - } - // TODO case of array classes of the same dimension - // TODO should we look also for a common super interface? - // problem: there may be several possible common super - // interfaces - do { - if (t == null || isInterface(t)) { - return BasicValue.REFERENCE_VALUE; - } - t = getSuperClass(t); - if (isAssignableFrom(t, u)) { - return newValue(t); - } - } while (true); - } - } - return BasicValue.UNINITIALIZED_VALUE; - } - return v; - } - - protected boolean isInterface(final Type t) { - if (currentClass != null && t.equals(currentClass)) { - return isInterface; - } - return getClass(t).isInterface(); - } - - protected Type getSuperClass(final Type t) { - if (currentClass != null && t.equals(currentClass)) { - return currentSuperClass; - } - Class<?> c = getClass(t).getSuperclass(); - return c == null ? null : Type.getType(c); - } - - protected boolean isAssignableFrom(final Type t, final Type u) { - if (t.equals(u)) { - return true; - } - if (currentClass != null && t.equals(currentClass)) { - if (getSuperClass(u) == null) { - return false; - } else { - if (isInterface) { - return u.getSort() == Type.OBJECT - || u.getSort() == Type.ARRAY; - } - return isAssignableFrom(t, getSuperClass(u)); - } - } - if (currentClass != null && u.equals(currentClass)) { - if (isAssignableFrom(t, currentSuperClass)) { - return true; - } - if (currentClassInterfaces != null) { - for (int i = 0; i < currentClassInterfaces.size(); ++i) { - Type v = currentClassInterfaces.get(i); - if (isAssignableFrom(t, v)) { - return true; - } - } - } - return false; - } - Class<?> tc = getClass(t); - if (tc.isInterface()) { - tc = Object.class; - } - return tc.isAssignableFrom(getClass(u)); - } - - protected Class<?> getClass(final Type t) { - try { - if (t.getSort() == Type.ARRAY) { - return Class.forName(t.getDescriptor().replace('/', '.'), - false, loader); - } - return Class.forName(t.getClassName(), false, loader); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e.toString()); - } - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/SmallSet.java b/src/asm/scala/tools/asm/tree/analysis/SmallSet.java deleted file mode 100644 index 205878d18c..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/SmallSet.java +++ /dev/null @@ -1,134 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import java.util.AbstractSet; -import java.util.HashSet; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Set; - -/** - * A set of at most two elements. - * - * @author Eric Bruneton - */ -class SmallSet<E> extends AbstractSet<E> implements Iterator<E> { - - // if e1 is null, e2 must be null; otherwise e2 must be different from e1 - - E e1, e2; - - static final <T> Set<T> emptySet() { - return new SmallSet<T>(null, null); - } - - SmallSet(final E e1, final E e2) { - this.e1 = e1; - this.e2 = e2; - } - - // ------------------------------------------------------------------------- - // Implementation of inherited abstract methods - // ------------------------------------------------------------------------- - - @Override - public Iterator<E> iterator() { - return new SmallSet<E>(e1, e2); - } - - @Override - public int size() { - return e1 == null ? 0 : (e2 == null ? 1 : 2); - } - - // ------------------------------------------------------------------------- - // Implementation of the Iterator interface - // ------------------------------------------------------------------------- - - public boolean hasNext() { - return e1 != null; - } - - public E next() { - if (e1 == null) { - throw new NoSuchElementException(); - } - E e = e1; - e1 = e2; - e2 = null; - return e; - } - - public void remove() { - } - - // ------------------------------------------------------------------------- - // Utility methods - // ------------------------------------------------------------------------- - - Set<E> union(final SmallSet<E> s) { - if ((s.e1 == e1 && s.e2 == e2) || (s.e1 == e2 && s.e2 == e1)) { - return this; // if the two sets are equal, return this - } - if (s.e1 == null) { - return this; // if s is empty, return this - } - if (e1 == null) { - return s; // if this is empty, return s - } - if (s.e2 == null) { // s contains exactly one element - if (e2 == null) { - return new SmallSet<E>(e1, s.e1); // necessarily e1 != s.e1 - } else if (s.e1 == e1 || s.e1 == e2) { // s is included in this - return this; - } - } - if (e2 == null) { // this contains exactly one element - // if (s.e2 == null) { // cannot happen - // return new SmallSet(e1, s.e1); // necessarily e1 != s.e1 - // } else - if (e1 == s.e1 || e1 == s.e2) { // this in included in s - return s; - } - } - // here we know that there are at least 3 distinct elements - HashSet<E> r = new HashSet<E>(4); - r.add(e1); - if (e2 != null) { - r.add(e2); - } - r.add(s.e1); - if (s.e2 != null) { - r.add(s.e2); - } - return r; - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/SourceInterpreter.java b/src/asm/scala/tools/asm/tree/analysis/SourceInterpreter.java deleted file mode 100644 index 7d739d3df9..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/SourceInterpreter.java +++ /dev/null @@ -1,198 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import scala.tools.asm.Opcodes; -import scala.tools.asm.Type; -import scala.tools.asm.tree.AbstractInsnNode; -import scala.tools.asm.tree.FieldInsnNode; -import scala.tools.asm.tree.InvokeDynamicInsnNode; -import scala.tools.asm.tree.LdcInsnNode; -import scala.tools.asm.tree.MethodInsnNode; - -/** - * An {@link Interpreter} for {@link SourceValue} values. - * - * @author Eric Bruneton - */ -public class SourceInterpreter extends Interpreter<SourceValue> implements - Opcodes { - - public SourceInterpreter() { - super(ASM5); - } - - protected SourceInterpreter(final int api) { - super(api); - } - - @Override - public SourceValue newValue(final Type type) { - if (type == Type.VOID_TYPE) { - return null; - } - return new SourceValue(type == null ? 1 : type.getSize()); - } - - @Override - public SourceValue newOperation(final AbstractInsnNode insn) { - int size; - switch (insn.getOpcode()) { - case LCONST_0: - case LCONST_1: - case DCONST_0: - case DCONST_1: - size = 2; - break; - case LDC: - Object cst = ((LdcInsnNode) insn).cst; - size = cst instanceof Long || cst instanceof Double ? 2 : 1; - break; - case GETSTATIC: - size = Type.getType(((FieldInsnNode) insn).desc).getSize(); - break; - default: - size = 1; - } - return new SourceValue(size, insn); - } - - @Override - public SourceValue copyOperation(final AbstractInsnNode insn, - final SourceValue value) { - return new SourceValue(value.getSize(), insn); - } - - @Override - public SourceValue unaryOperation(final AbstractInsnNode insn, - final SourceValue value) { - int size; - switch (insn.getOpcode()) { - case LNEG: - case DNEG: - case I2L: - case I2D: - case L2D: - case F2L: - case F2D: - case D2L: - size = 2; - break; - case GETFIELD: - size = Type.getType(((FieldInsnNode) insn).desc).getSize(); - break; - default: - size = 1; - } - return new SourceValue(size, insn); - } - - @Override - public SourceValue binaryOperation(final AbstractInsnNode insn, - final SourceValue value1, final SourceValue value2) { - int size; - switch (insn.getOpcode()) { - case LALOAD: - case DALOAD: - case LADD: - case DADD: - case LSUB: - case DSUB: - case LMUL: - case DMUL: - case LDIV: - case DDIV: - case LREM: - case DREM: - case LSHL: - case LSHR: - case LUSHR: - case LAND: - case LOR: - case LXOR: - size = 2; - break; - default: - size = 1; - } - return new SourceValue(size, insn); - } - - @Override - public SourceValue ternaryOperation(final AbstractInsnNode insn, - final SourceValue value1, final SourceValue value2, - final SourceValue value3) { - return new SourceValue(1, insn); - } - - @Override - public SourceValue naryOperation(final AbstractInsnNode insn, - final List<? extends SourceValue> values) { - int size; - int opcode = insn.getOpcode(); - if (opcode == MULTIANEWARRAY) { - size = 1; - } else { - String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc - : ((MethodInsnNode) insn).desc; - size = Type.getReturnType(desc).getSize(); - } - return new SourceValue(size, insn); - } - - @Override - public void returnOperation(final AbstractInsnNode insn, - final SourceValue value, final SourceValue expected) { - } - - @Override - public SourceValue merge(final SourceValue d, final SourceValue w) { - if (d.insns instanceof SmallSet && w.insns instanceof SmallSet) { - Set<AbstractInsnNode> s = ((SmallSet<AbstractInsnNode>) d.insns) - .union((SmallSet<AbstractInsnNode>) w.insns); - if (s == d.insns && d.size == w.size) { - return d; - } else { - return new SourceValue(Math.min(d.size, w.size), s); - } - } - if (d.size != w.size || !d.insns.containsAll(w.insns)) { - HashSet<AbstractInsnNode> s = new HashSet<AbstractInsnNode>(); - s.addAll(d.insns); - s.addAll(w.insns); - return new SourceValue(Math.min(d.size, w.size), s); - } - return d; - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/SourceValue.java b/src/asm/scala/tools/asm/tree/analysis/SourceValue.java deleted file mode 100644 index 40d6b68180..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/SourceValue.java +++ /dev/null @@ -1,97 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import java.util.Set; - -import scala.tools.asm.tree.AbstractInsnNode; - -/** - * A {@link Value} that is represented by its type in a two types type system. - * This type system distinguishes the ONEWORD and TWOWORDS types. - * - * @author Eric Bruneton - */ -public class SourceValue implements Value { - - /** - * The size of this value. - */ - public final int size; - - /** - * The instructions that can produce this value. For example, for the Java - * code below, the instructions that can produce the value of <tt>i</tt> at - * line 5 are the txo ISTORE instructions at line 1 and 3: - * - * <pre> - * 1: i = 0; - * 2: if (...) { - * 3: i = 1; - * 4: } - * 5: return i; - * </pre> - * - * This field is a set of {@link AbstractInsnNode} objects. - */ - public final Set<AbstractInsnNode> insns; - - public SourceValue(final int size) { - this(size, SmallSet.<AbstractInsnNode> emptySet()); - } - - public SourceValue(final int size, final AbstractInsnNode insn) { - this.size = size; - this.insns = new SmallSet<AbstractInsnNode>(insn, null); - } - - public SourceValue(final int size, final Set<AbstractInsnNode> insns) { - this.size = size; - this.insns = insns; - } - - public int getSize() { - return size; - } - - @Override - public boolean equals(final Object value) { - if (!(value instanceof SourceValue)) { - return false; - } - SourceValue v = (SourceValue) value; - return size == v.size && insns.equals(v.insns); - } - - @Override - public int hashCode() { - return insns.hashCode(); - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/Subroutine.java b/src/asm/scala/tools/asm/tree/analysis/Subroutine.java deleted file mode 100644 index d734bbd499..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/Subroutine.java +++ /dev/null @@ -1,90 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -import java.util.ArrayList; -import java.util.List; - -import scala.tools.asm.tree.JumpInsnNode; -import scala.tools.asm.tree.LabelNode; - -/** - * A method subroutine (corresponds to a JSR instruction). - * - * @author Eric Bruneton - */ -class Subroutine { - - LabelNode start; - - boolean[] access; - - List<JumpInsnNode> callers; - - private Subroutine() { - } - - Subroutine(final LabelNode start, final int maxLocals, - final JumpInsnNode caller) { - this.start = start; - this.access = new boolean[maxLocals]; - this.callers = new ArrayList<JumpInsnNode>(); - callers.add(caller); - } - - public Subroutine copy() { - Subroutine result = new Subroutine(); - result.start = start; - result.access = new boolean[access.length]; - System.arraycopy(access, 0, result.access, 0, access.length); - result.callers = new ArrayList<JumpInsnNode>(callers); - return result; - } - - public boolean merge(final Subroutine subroutine) throws AnalyzerException { - boolean changes = false; - for (int i = 0; i < access.length; ++i) { - if (subroutine.access[i] && !access[i]) { - access[i] = true; - changes = true; - } - } - if (subroutine.start == start) { - for (int i = 0; i < subroutine.callers.size(); ++i) { - JumpInsnNode caller = subroutine.callers.get(i); - if (!callers.contains(caller)) { - callers.add(caller); - changes = true; - } - } - } - return changes; - } -} diff --git a/src/asm/scala/tools/asm/tree/analysis/Value.java b/src/asm/scala/tools/asm/tree/analysis/Value.java deleted file mode 100644 index 1edf475ce7..0000000000 --- a/src/asm/scala/tools/asm/tree/analysis/Value.java +++ /dev/null @@ -1,45 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.tree.analysis; - -/** - * An immutable symbolic value for semantic interpretation of bytecode. - * - * @author Eric Bruneton - */ -public interface Value { - - /** - * Returns the size of this value in words. - * - * @return either 1 or 2. - */ - int getSize(); -} diff --git a/src/asm/scala/tools/asm/util/ASMifiable.java b/src/asm/scala/tools/asm/util/ASMifiable.java deleted file mode 100644 index 95cc6e3a74..0000000000 --- a/src/asm/scala/tools/asm/util/ASMifiable.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import java.util.Map; - -import scala.tools.asm.Label; - -/** - * An {@link scala.tools.asm.Attribute Attribute} that can print the ASM code - * to create an equivalent attribute. - * - * @author Eugene Kuleshov - */ -public interface ASMifiable { - - /** - * Prints the ASM code to create an attribute equal to this attribute. - * - * @param buf - * a buffer used for printing Java code. - * @param varName - * name of the variable in a printed code used to store attribute - * instance. - * @param labelNames - * map of label instances to their names. - */ - void asmify(StringBuffer buf, String varName, Map<Label, String> labelNames); -} diff --git a/src/asm/scala/tools/asm/util/ASMifier.java b/src/asm/scala/tools/asm/util/ASMifier.java deleted file mode 100644 index 521e07541b..0000000000 --- a/src/asm/scala/tools/asm/util/ASMifier.java +++ /dev/null @@ -1,1284 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import java.io.FileInputStream; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.Map; - -import scala.tools.asm.Attribute; -import scala.tools.asm.ClassReader; -import scala.tools.asm.Handle; -import scala.tools.asm.Label; -import scala.tools.asm.Opcodes; -import scala.tools.asm.Type; -import scala.tools.asm.TypePath; - -/** - * A {@link Printer} that prints the ASM code to generate the classes if visits. - * - * @author Eric Bruneton - */ -public class ASMifier extends Printer { - - /** - * The name of the visitor variable in the produced code. - */ - protected final String name; - - /** - * Identifier of the annotation visitor variable in the produced code. - */ - protected final int id; - - /** - * The label names. This map associates String values to Label keys. It is - * used only in ASMifierMethodVisitor. - */ - protected Map<Label, String> labelNames; - - /** - * Pseudo access flag used to distinguish class access flags. - */ - private static final int ACCESS_CLASS = 262144; - - /** - * Pseudo access flag used to distinguish field access flags. - */ - private static final int ACCESS_FIELD = 524288; - - /** - * Pseudo access flag used to distinguish inner class flags. - */ - private static final int ACCESS_INNER = 1048576; - - /** - * Constructs a new {@link ASMifier}. <i>Subclasses must not use this - * constructor</i>. Instead, they must use the - * {@link #ASMifier(int, String, int)} version. - * - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public ASMifier() { - this(Opcodes.ASM5, "cw", 0); - if (getClass() != ASMifier.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs a new {@link ASMifier}. - * - * @param api - * the ASM API version implemented by this class. Must be one of - * {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param name - * the name of the visitor variable in the produced code. - * @param id - * identifier of the annotation visitor variable in the produced - * code. - */ - protected ASMifier(final int api, final String name, final int id) { - super(api); - this.name = name; - this.id = id; - } - - /** - * Prints the ASM source code to generate the given class to the standard - * output. - * <p> - * Usage: ASMifier [-debug] <binary class name or class file name> - * - * @param args - * the command line arguments. - * - * @throws Exception - * if the class cannot be found, or if an IO exception occurs. - */ - public static void main(final String[] args) throws Exception { - int i = 0; - int flags = ClassReader.SKIP_DEBUG; - - boolean ok = true; - if (args.length < 1 || args.length > 2) { - ok = false; - } - if (ok && "-debug".equals(args[0])) { - i = 1; - flags = 0; - if (args.length != 2) { - ok = false; - } - } - if (!ok) { - System.err - .println("Prints the ASM code to generate the given class."); - System.err.println("Usage: ASMifier [-debug] " - + "<fully qualified class name or class file name>"); - return; - } - ClassReader cr; - if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1 - || args[i].indexOf('/') > -1) { - cr = new ClassReader(new FileInputStream(args[i])); - } else { - cr = new ClassReader(args[i]); - } - cr.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter( - System.out)), flags); - } - - // ------------------------------------------------------------------------ - // Classes - // ------------------------------------------------------------------------ - - @Override - public void visit(final int version, final int access, final String name, - final String signature, final String superName, - final String[] interfaces) { - String simpleName; - int n = name.lastIndexOf('/'); - if (n == -1) { - simpleName = name; - } else { - text.add("package asm." + name.substring(0, n).replace('/', '.') - + ";\n"); - simpleName = name.substring(n + 1); - } - text.add("import java.util.*;\n"); - text.add("import scala.tools.asm.*;\n"); - text.add("public class " + simpleName + "Dump implements Opcodes {\n\n"); - text.add("public static byte[] dump () throws Exception {\n\n"); - text.add("ClassWriter cw = new ClassWriter(0);\n"); - text.add("FieldVisitor fv;\n"); - text.add("MethodVisitor mv;\n"); - text.add("AnnotationVisitor av0;\n\n"); - - buf.setLength(0); - buf.append("cw.visit("); - switch (version) { - case Opcodes.V1_1: - buf.append("V1_1"); - break; - case Opcodes.V1_2: - buf.append("V1_2"); - break; - case Opcodes.V1_3: - buf.append("V1_3"); - break; - case Opcodes.V1_4: - buf.append("V1_4"); - break; - case Opcodes.V1_5: - buf.append("V1_5"); - break; - case Opcodes.V1_6: - buf.append("V1_6"); - break; - case Opcodes.V1_7: - buf.append("V1_7"); - break; - default: - buf.append(version); - break; - } - buf.append(", "); - appendAccess(access | ACCESS_CLASS); - buf.append(", "); - appendConstant(name); - buf.append(", "); - appendConstant(signature); - buf.append(", "); - appendConstant(superName); - buf.append(", "); - if (interfaces != null && interfaces.length > 0) { - buf.append("new String[] {"); - for (int i = 0; i < interfaces.length; ++i) { - buf.append(i == 0 ? " " : ", "); - appendConstant(interfaces[i]); - } - buf.append(" }"); - } else { - buf.append("null"); - } - buf.append(");\n\n"); - text.add(buf.toString()); - } - - @Override - public void visitSource(final String file, final String debug) { - buf.setLength(0); - buf.append("cw.visitSource("); - appendConstant(file); - buf.append(", "); - appendConstant(debug); - buf.append(");\n\n"); - text.add(buf.toString()); - } - - @Override - public void visitOuterClass(final String owner, final String name, - final String desc) { - buf.setLength(0); - buf.append("cw.visitOuterClass("); - appendConstant(owner); - buf.append(", "); - appendConstant(name); - buf.append(", "); - appendConstant(desc); - buf.append(");\n\n"); - text.add(buf.toString()); - } - - @Override - public ASMifier visitClassAnnotation(final String desc, - final boolean visible) { - return visitAnnotation(desc, visible); - } - - @Override - public ASMifier visitClassTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - return visitTypeAnnotation(typeRef, typePath, desc, visible); - } - - @Override - public void visitClassAttribute(final Attribute attr) { - visitAttribute(attr); - } - - @Override - public void visitInnerClass(final String name, final String outerName, - final String innerName, final int access) { - buf.setLength(0); - buf.append("cw.visitInnerClass("); - appendConstant(name); - buf.append(", "); - appendConstant(outerName); - buf.append(", "); - appendConstant(innerName); - buf.append(", "); - appendAccess(access | ACCESS_INNER); - buf.append(");\n\n"); - text.add(buf.toString()); - } - - @Override - public ASMifier visitField(final int access, final String name, - final String desc, final String signature, final Object value) { - buf.setLength(0); - buf.append("{\n"); - buf.append("fv = cw.visitField("); - appendAccess(access | ACCESS_FIELD); - buf.append(", "); - appendConstant(name); - buf.append(", "); - appendConstant(desc); - buf.append(", "); - appendConstant(signature); - buf.append(", "); - appendConstant(value); - buf.append(");\n"); - text.add(buf.toString()); - ASMifier a = createASMifier("fv", 0); - text.add(a.getText()); - text.add("}\n"); - return a; - } - - @Override - public ASMifier visitMethod(final int access, final String name, - final String desc, final String signature, final String[] exceptions) { - buf.setLength(0); - buf.append("{\n"); - buf.append("mv = cw.visitMethod("); - appendAccess(access); - buf.append(", "); - appendConstant(name); - buf.append(", "); - appendConstant(desc); - buf.append(", "); - appendConstant(signature); - buf.append(", "); - if (exceptions != null && exceptions.length > 0) { - buf.append("new String[] {"); - for (int i = 0; i < exceptions.length; ++i) { - buf.append(i == 0 ? " " : ", "); - appendConstant(exceptions[i]); - } - buf.append(" }"); - } else { - buf.append("null"); - } - buf.append(");\n"); - text.add(buf.toString()); - ASMifier a = createASMifier("mv", 0); - text.add(a.getText()); - text.add("}\n"); - return a; - } - - @Override - public void visitClassEnd() { - text.add("cw.visitEnd();\n\n"); - text.add("return cw.toByteArray();\n"); - text.add("}\n"); - text.add("}\n"); - } - - // ------------------------------------------------------------------------ - // Annotations - // ------------------------------------------------------------------------ - - @Override - public void visit(final String name, final Object value) { - buf.setLength(0); - buf.append("av").append(id).append(".visit("); - appendConstant(buf, name); - buf.append(", "); - appendConstant(buf, value); - buf.append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitEnum(final String name, final String desc, - final String value) { - buf.setLength(0); - buf.append("av").append(id).append(".visitEnum("); - appendConstant(buf, name); - buf.append(", "); - appendConstant(buf, desc); - buf.append(", "); - appendConstant(buf, value); - buf.append(");\n"); - text.add(buf.toString()); - } - - @Override - public ASMifier visitAnnotation(final String name, final String desc) { - buf.setLength(0); - buf.append("{\n"); - buf.append("AnnotationVisitor av").append(id + 1).append(" = av"); - buf.append(id).append(".visitAnnotation("); - appendConstant(buf, name); - buf.append(", "); - appendConstant(buf, desc); - buf.append(");\n"); - text.add(buf.toString()); - ASMifier a = createASMifier("av", id + 1); - text.add(a.getText()); - text.add("}\n"); - return a; - } - - @Override - public ASMifier visitArray(final String name) { - buf.setLength(0); - buf.append("{\n"); - buf.append("AnnotationVisitor av").append(id + 1).append(" = av"); - buf.append(id).append(".visitArray("); - appendConstant(buf, name); - buf.append(");\n"); - text.add(buf.toString()); - ASMifier a = createASMifier("av", id + 1); - text.add(a.getText()); - text.add("}\n"); - return a; - } - - @Override - public void visitAnnotationEnd() { - buf.setLength(0); - buf.append("av").append(id).append(".visitEnd();\n"); - text.add(buf.toString()); - } - - // ------------------------------------------------------------------------ - // Fields - // ------------------------------------------------------------------------ - - @Override - public ASMifier visitFieldAnnotation(final String desc, - final boolean visible) { - return visitAnnotation(desc, visible); - } - - @Override - public ASMifier visitFieldTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - return visitTypeAnnotation(typeRef, typePath, desc, visible); - } - - @Override - public void visitFieldAttribute(final Attribute attr) { - visitAttribute(attr); - } - - @Override - public void visitFieldEnd() { - buf.setLength(0); - buf.append(name).append(".visitEnd();\n"); - text.add(buf.toString()); - } - - // ------------------------------------------------------------------------ - // Methods - // ------------------------------------------------------------------------ - - @Override - public void visitParameter(String parameterName, int access) { - buf.setLength(0); - buf.append(name).append(".visitParameter("); - appendString(buf, parameterName); - buf.append(", "); - appendAccess(access); - text.add(buf.append(");\n").toString()); - } - - @Override - public ASMifier visitAnnotationDefault() { - buf.setLength(0); - buf.append("{\n").append("av0 = ").append(name) - .append(".visitAnnotationDefault();\n"); - text.add(buf.toString()); - ASMifier a = createASMifier("av", 0); - text.add(a.getText()); - text.add("}\n"); - return a; - } - - @Override - public ASMifier visitMethodAnnotation(final String desc, - final boolean visible) { - return visitAnnotation(desc, visible); - } - - @Override - public ASMifier visitMethodTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - return visitTypeAnnotation(typeRef, typePath, desc, visible); - } - - @Override - public ASMifier visitParameterAnnotation(final int parameter, - final String desc, final boolean visible) { - buf.setLength(0); - buf.append("{\n").append("av0 = ").append(name) - .append(".visitParameterAnnotation(").append(parameter) - .append(", "); - appendConstant(desc); - buf.append(", ").append(visible).append(");\n"); - text.add(buf.toString()); - ASMifier a = createASMifier("av", 0); - text.add(a.getText()); - text.add("}\n"); - return a; - } - - @Override - public void visitMethodAttribute(final Attribute attr) { - visitAttribute(attr); - } - - @Override - public void visitCode() { - text.add(name + ".visitCode();\n"); - } - - @Override - public void visitFrame(final int type, final int nLocal, - final Object[] local, final int nStack, final Object[] stack) { - buf.setLength(0); - switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - declareFrameTypes(nLocal, local); - declareFrameTypes(nStack, stack); - if (type == Opcodes.F_NEW) { - buf.append(name).append(".visitFrame(Opcodes.F_NEW, "); - } else { - buf.append(name).append(".visitFrame(Opcodes.F_FULL, "); - } - buf.append(nLocal).append(", new Object[] {"); - appendFrameTypes(nLocal, local); - buf.append("}, ").append(nStack).append(", new Object[] {"); - appendFrameTypes(nStack, stack); - buf.append('}'); - break; - case Opcodes.F_APPEND: - declareFrameTypes(nLocal, local); - buf.append(name).append(".visitFrame(Opcodes.F_APPEND,") - .append(nLocal).append(", new Object[] {"); - appendFrameTypes(nLocal, local); - buf.append("}, 0, null"); - break; - case Opcodes.F_CHOP: - buf.append(name).append(".visitFrame(Opcodes.F_CHOP,") - .append(nLocal).append(", null, 0, null"); - break; - case Opcodes.F_SAME: - buf.append(name).append( - ".visitFrame(Opcodes.F_SAME, 0, null, 0, null"); - break; - case Opcodes.F_SAME1: - declareFrameTypes(1, stack); - buf.append(name).append( - ".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"); - appendFrameTypes(1, stack); - buf.append('}'); - break; - } - buf.append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitInsn(final int opcode) { - buf.setLength(0); - buf.append(name).append(".visitInsn(").append(OPCODES[opcode]) - .append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitIntInsn(final int opcode, final int operand) { - buf.setLength(0); - buf.append(name) - .append(".visitIntInsn(") - .append(OPCODES[opcode]) - .append(", ") - .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer - .toString(operand)).append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitVarInsn(final int opcode, final int var) { - buf.setLength(0); - buf.append(name).append(".visitVarInsn(").append(OPCODES[opcode]) - .append(", ").append(var).append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitTypeInsn(final int opcode, final String type) { - buf.setLength(0); - buf.append(name).append(".visitTypeInsn(").append(OPCODES[opcode]) - .append(", "); - appendConstant(type); - buf.append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitFieldInsn(final int opcode, final String owner, - final String name, final String desc) { - buf.setLength(0); - buf.append(this.name).append(".visitFieldInsn(") - .append(OPCODES[opcode]).append(", "); - appendConstant(owner); - buf.append(", "); - appendConstant(name); - buf.append(", "); - appendConstant(desc); - buf.append(");\n"); - text.add(buf.toString()); - } - - @Deprecated - @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc) { - if (api >= Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc); - return; - } - doVisitMethodInsn(opcode, owner, name, desc, - opcode == Opcodes.INVOKEINTERFACE); - } - - @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc, final boolean itf) { - if (api < Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - doVisitMethodInsn(opcode, owner, name, desc, itf); - } - - private void doVisitMethodInsn(final int opcode, final String owner, - final String name, final String desc, final boolean itf) { - buf.setLength(0); - buf.append(this.name).append(".visitMethodInsn(") - .append(OPCODES[opcode]).append(", "); - appendConstant(owner); - buf.append(", "); - appendConstant(name); - buf.append(", "); - appendConstant(desc); - buf.append(", "); - buf.append(itf ? "true" : "false"); - buf.append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, - Object... bsmArgs) { - buf.setLength(0); - buf.append(this.name).append(".visitInvokeDynamicInsn("); - appendConstant(name); - buf.append(", "); - appendConstant(desc); - buf.append(", "); - appendConstant(bsm); - buf.append(", new Object[]{"); - for (int i = 0; i < bsmArgs.length; ++i) { - appendConstant(bsmArgs[i]); - if (i != bsmArgs.length - 1) { - buf.append(", "); - } - } - buf.append("});\n"); - text.add(buf.toString()); - } - - @Override - public void visitJumpInsn(final int opcode, final Label label) { - buf.setLength(0); - declareLabel(label); - buf.append(name).append(".visitJumpInsn(").append(OPCODES[opcode]) - .append(", "); - appendLabel(label); - buf.append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitLabel(final Label label) { - buf.setLength(0); - declareLabel(label); - buf.append(name).append(".visitLabel("); - appendLabel(label); - buf.append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitLdcInsn(final Object cst) { - buf.setLength(0); - buf.append(name).append(".visitLdcInsn("); - appendConstant(cst); - buf.append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitIincInsn(final int var, final int increment) { - buf.setLength(0); - buf.append(name).append(".visitIincInsn(").append(var).append(", ") - .append(increment).append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitTableSwitchInsn(final int min, final int max, - final Label dflt, final Label... labels) { - buf.setLength(0); - for (int i = 0; i < labels.length; ++i) { - declareLabel(labels[i]); - } - declareLabel(dflt); - - buf.append(name).append(".visitTableSwitchInsn(").append(min) - .append(", ").append(max).append(", "); - appendLabel(dflt); - buf.append(", new Label[] {"); - for (int i = 0; i < labels.length; ++i) { - buf.append(i == 0 ? " " : ", "); - appendLabel(labels[i]); - } - buf.append(" });\n"); - text.add(buf.toString()); - } - - @Override - public void visitLookupSwitchInsn(final Label dflt, final int[] keys, - final Label[] labels) { - buf.setLength(0); - for (int i = 0; i < labels.length; ++i) { - declareLabel(labels[i]); - } - declareLabel(dflt); - - buf.append(name).append(".visitLookupSwitchInsn("); - appendLabel(dflt); - buf.append(", new int[] {"); - for (int i = 0; i < keys.length; ++i) { - buf.append(i == 0 ? " " : ", ").append(keys[i]); - } - buf.append(" }, new Label[] {"); - for (int i = 0; i < labels.length; ++i) { - buf.append(i == 0 ? " " : ", "); - appendLabel(labels[i]); - } - buf.append(" });\n"); - text.add(buf.toString()); - } - - @Override - public void visitMultiANewArrayInsn(final String desc, final int dims) { - buf.setLength(0); - buf.append(name).append(".visitMultiANewArrayInsn("); - appendConstant(desc); - buf.append(", ").append(dims).append(");\n"); - text.add(buf.toString()); - } - - @Override - public ASMifier visitInsnAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - return visitTypeAnnotation("visitInsnAnnotation", typeRef, typePath, - desc, visible); - } - - @Override - public void visitTryCatchBlock(final Label start, final Label end, - final Label handler, final String type) { - buf.setLength(0); - declareLabel(start); - declareLabel(end); - declareLabel(handler); - buf.append(name).append(".visitTryCatchBlock("); - appendLabel(start); - buf.append(", "); - appendLabel(end); - buf.append(", "); - appendLabel(handler); - buf.append(", "); - appendConstant(type); - buf.append(");\n"); - text.add(buf.toString()); - } - - @Override - public ASMifier visitTryCatchAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - return visitTypeAnnotation("visitTryCatchAnnotation", typeRef, - typePath, desc, visible); - } - - @Override - public void visitLocalVariable(final String name, final String desc, - final String signature, final Label start, final Label end, - final int index) { - buf.setLength(0); - buf.append(this.name).append(".visitLocalVariable("); - appendConstant(name); - buf.append(", "); - appendConstant(desc); - buf.append(", "); - appendConstant(signature); - buf.append(", "); - appendLabel(start); - buf.append(", "); - appendLabel(end); - buf.append(", ").append(index).append(");\n"); - text.add(buf.toString()); - } - - @Override - public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath, - Label[] start, Label[] end, int[] index, String desc, - boolean visible) { - buf.setLength(0); - buf.append("{\n").append("av0 = ").append(name) - .append(".visitLocalVariableAnnotation("); - buf.append(typeRef); - buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); - buf.append("new Label[] {"); - for (int i = 0; i < start.length; ++i) { - buf.append(i == 0 ? " " : ", "); - appendLabel(start[i]); - } - buf.append(" }, new Label[] {"); - for (int i = 0; i < end.length; ++i) { - buf.append(i == 0 ? " " : ", "); - appendLabel(end[i]); - } - buf.append(" }, new int[] {"); - for (int i = 0; i < index.length; ++i) { - buf.append(i == 0 ? " " : ", ").append(index[i]); - } - buf.append(" }, "); - appendConstant(desc); - buf.append(", ").append(visible).append(");\n"); - text.add(buf.toString()); - ASMifier a = createASMifier("av", 0); - text.add(a.getText()); - text.add("}\n"); - return a; - } - - @Override - public void visitLineNumber(final int line, final Label start) { - buf.setLength(0); - buf.append(name).append(".visitLineNumber(").append(line).append(", "); - appendLabel(start); - buf.append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitMaxs(final int maxStack, final int maxLocals) { - buf.setLength(0); - buf.append(name).append(".visitMaxs(").append(maxStack).append(", ") - .append(maxLocals).append(");\n"); - text.add(buf.toString()); - } - - @Override - public void visitMethodEnd() { - buf.setLength(0); - buf.append(name).append(".visitEnd();\n"); - text.add(buf.toString()); - } - - // ------------------------------------------------------------------------ - // Common methods - // ------------------------------------------------------------------------ - - public ASMifier visitAnnotation(final String desc, final boolean visible) { - buf.setLength(0); - buf.append("{\n").append("av0 = ").append(name) - .append(".visitAnnotation("); - appendConstant(desc); - buf.append(", ").append(visible).append(");\n"); - text.add(buf.toString()); - ASMifier a = createASMifier("av", 0); - text.add(a.getText()); - text.add("}\n"); - return a; - } - - public ASMifier visitTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - return visitTypeAnnotation("visitTypeAnnotation", typeRef, typePath, - desc, visible); - } - - public ASMifier visitTypeAnnotation(final String method, final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - buf.setLength(0); - buf.append("{\n").append("av0 = ").append(name).append(".") - .append(method).append("("); - buf.append(typeRef); - buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); - appendConstant(desc); - buf.append(", ").append(visible).append(");\n"); - text.add(buf.toString()); - ASMifier a = createASMifier("av", 0); - text.add(a.getText()); - text.add("}\n"); - return a; - } - - public void visitAttribute(final Attribute attr) { - buf.setLength(0); - buf.append("// ATTRIBUTE ").append(attr.type).append('\n'); - if (attr instanceof ASMifiable) { - if (labelNames == null) { - labelNames = new HashMap<Label, String>(); - } - buf.append("{\n"); - ((ASMifiable) attr).asmify(buf, "attr", labelNames); - buf.append(name).append(".visitAttribute(attr);\n"); - buf.append("}\n"); - } - text.add(buf.toString()); - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - protected ASMifier createASMifier(final String name, final int id) { - return new ASMifier(Opcodes.ASM5, name, id); - } - - /** - * Appends a string representation of the given access modifiers to - * {@link #buf buf}. - * - * @param access - * some access modifiers. - */ - void appendAccess(final int access) { - boolean first = true; - if ((access & Opcodes.ACC_PUBLIC) != 0) { - buf.append("ACC_PUBLIC"); - first = false; - } - if ((access & Opcodes.ACC_PRIVATE) != 0) { - buf.append("ACC_PRIVATE"); - first = false; - } - if ((access & Opcodes.ACC_PROTECTED) != 0) { - buf.append("ACC_PROTECTED"); - first = false; - } - if ((access & Opcodes.ACC_FINAL) != 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_FINAL"); - first = false; - } - if ((access & Opcodes.ACC_STATIC) != 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_STATIC"); - first = false; - } - if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { - if (!first) { - buf.append(" + "); - } - if ((access & ACCESS_CLASS) == 0) { - buf.append("ACC_SYNCHRONIZED"); - } else { - buf.append("ACC_SUPER"); - } - first = false; - } - if ((access & Opcodes.ACC_VOLATILE) != 0 - && (access & ACCESS_FIELD) != 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_VOLATILE"); - first = false; - } - if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0 - && (access & ACCESS_FIELD) == 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_BRIDGE"); - first = false; - } - if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0 - && (access & ACCESS_FIELD) == 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_VARARGS"); - first = false; - } - if ((access & Opcodes.ACC_TRANSIENT) != 0 - && (access & ACCESS_FIELD) != 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_TRANSIENT"); - first = false; - } - if ((access & Opcodes.ACC_NATIVE) != 0 && (access & ACCESS_CLASS) == 0 - && (access & ACCESS_FIELD) == 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_NATIVE"); - first = false; - } - if ((access & Opcodes.ACC_ENUM) != 0 - && ((access & ACCESS_CLASS) != 0 - || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0)) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_ENUM"); - first = false; - } - if ((access & Opcodes.ACC_ANNOTATION) != 0 - && ((access & ACCESS_CLASS) != 0 || (access & ACCESS_INNER) != 0)) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_ANNOTATION"); - first = false; - } - if ((access & Opcodes.ACC_ABSTRACT) != 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_ABSTRACT"); - first = false; - } - if ((access & Opcodes.ACC_INTERFACE) != 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_INTERFACE"); - first = false; - } - if ((access & Opcodes.ACC_STRICT) != 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_STRICT"); - first = false; - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_SYNTHETIC"); - first = false; - } - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_DEPRECATED"); - first = false; - } - if ((access & Opcodes.ACC_MANDATED) != 0) { - if (!first) { - buf.append(" + "); - } - buf.append("ACC_MANDATED"); - first = false; - } - if (first) { - buf.append('0'); - } - } - - /** - * Appends a string representation of the given constant to the given - * buffer. - * - * @param cst - * an {@link Integer}, {@link Float}, {@link Long}, - * {@link Double} or {@link String} object. May be <tt>null</tt>. - */ - protected void appendConstant(final Object cst) { - appendConstant(buf, cst); - } - - /** - * Appends a string representation of the given constant to the given - * buffer. - * - * @param buf - * a string buffer. - * @param cst - * an {@link Integer}, {@link Float}, {@link Long}, - * {@link Double} or {@link String} object. May be <tt>null</tt>. - */ - static void appendConstant(final StringBuffer buf, final Object cst) { - if (cst == null) { - buf.append("null"); - } else if (cst instanceof String) { - appendString(buf, (String) cst); - } else if (cst instanceof Type) { - buf.append("Type.getType(\""); - buf.append(((Type) cst).getDescriptor()); - buf.append("\")"); - } else if (cst instanceof Handle) { - buf.append("new Handle("); - Handle h = (Handle) cst; - buf.append("Opcodes.").append(HANDLE_TAG[h.getTag()]) - .append(", \""); - buf.append(h.getOwner()).append("\", \""); - buf.append(h.getName()).append("\", \""); - buf.append(h.getDesc()).append("\")"); - } else if (cst instanceof Byte) { - buf.append("new Byte((byte)").append(cst).append(')'); - } else if (cst instanceof Boolean) { - buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE" - : "Boolean.FALSE"); - } else if (cst instanceof Short) { - buf.append("new Short((short)").append(cst).append(')'); - } else if (cst instanceof Character) { - int c = ((Character) cst).charValue(); - buf.append("new Character((char)").append(c).append(')'); - } else if (cst instanceof Integer) { - buf.append("new Integer(").append(cst).append(')'); - } else if (cst instanceof Float) { - buf.append("new Float(\"").append(cst).append("\")"); - } else if (cst instanceof Long) { - buf.append("new Long(").append(cst).append("L)"); - } else if (cst instanceof Double) { - buf.append("new Double(\"").append(cst).append("\")"); - } else if (cst instanceof byte[]) { - byte[] v = (byte[]) cst; - buf.append("new byte[] {"); - for (int i = 0; i < v.length; i++) { - buf.append(i == 0 ? "" : ",").append(v[i]); - } - buf.append('}'); - } else if (cst instanceof boolean[]) { - boolean[] v = (boolean[]) cst; - buf.append("new boolean[] {"); - for (int i = 0; i < v.length; i++) { - buf.append(i == 0 ? "" : ",").append(v[i]); - } - buf.append('}'); - } else if (cst instanceof short[]) { - short[] v = (short[]) cst; - buf.append("new short[] {"); - for (int i = 0; i < v.length; i++) { - buf.append(i == 0 ? "" : ",").append("(short)").append(v[i]); - } - buf.append('}'); - } else if (cst instanceof char[]) { - char[] v = (char[]) cst; - buf.append("new char[] {"); - for (int i = 0; i < v.length; i++) { - buf.append(i == 0 ? "" : ",").append("(char)") - .append((int) v[i]); - } - buf.append('}'); - } else if (cst instanceof int[]) { - int[] v = (int[]) cst; - buf.append("new int[] {"); - for (int i = 0; i < v.length; i++) { - buf.append(i == 0 ? "" : ",").append(v[i]); - } - buf.append('}'); - } else if (cst instanceof long[]) { - long[] v = (long[]) cst; - buf.append("new long[] {"); - for (int i = 0; i < v.length; i++) { - buf.append(i == 0 ? "" : ",").append(v[i]).append('L'); - } - buf.append('}'); - } else if (cst instanceof float[]) { - float[] v = (float[]) cst; - buf.append("new float[] {"); - for (int i = 0; i < v.length; i++) { - buf.append(i == 0 ? "" : ",").append(v[i]).append('f'); - } - buf.append('}'); - } else if (cst instanceof double[]) { - double[] v = (double[]) cst; - buf.append("new double[] {"); - for (int i = 0; i < v.length; i++) { - buf.append(i == 0 ? "" : ",").append(v[i]).append('d'); - } - buf.append('}'); - } - } - - private void declareFrameTypes(final int n, final Object[] o) { - for (int i = 0; i < n; ++i) { - if (o[i] instanceof Label) { - declareLabel((Label) o[i]); - } - } - } - - private void appendFrameTypes(final int n, final Object[] o) { - for (int i = 0; i < n; ++i) { - if (i > 0) { - buf.append(", "); - } - if (o[i] instanceof String) { - appendConstant(o[i]); - } else if (o[i] instanceof Integer) { - switch (((Integer) o[i]).intValue()) { - case 0: - buf.append("Opcodes.TOP"); - break; - case 1: - buf.append("Opcodes.INTEGER"); - break; - case 2: - buf.append("Opcodes.FLOAT"); - break; - case 3: - buf.append("Opcodes.DOUBLE"); - break; - case 4: - buf.append("Opcodes.LONG"); - break; - case 5: - buf.append("Opcodes.NULL"); - break; - case 6: - buf.append("Opcodes.UNINITIALIZED_THIS"); - break; - } - } else { - appendLabel((Label) o[i]); - } - } - } - - /** - * Appends a declaration of the given label to {@link #buf buf}. This - * declaration is of the form "Label lXXX = new Label();". Does nothing if - * the given label has already been declared. - * - * @param l - * a label. - */ - protected void declareLabel(final Label l) { - if (labelNames == null) { - labelNames = new HashMap<Label, String>(); - } - String name = labelNames.get(l); - if (name == null) { - name = "l" + labelNames.size(); - labelNames.put(l, name); - buf.append("Label ").append(name).append(" = new Label();\n"); - } - } - - /** - * Appends the name of the given label to {@link #buf buf}. The given label - * <i>must</i> already have a name. One way to ensure this is to always call - * {@link #declareLabel declared} before calling this method. - * - * @param l - * a label. - */ - protected void appendLabel(final Label l) { - buf.append(labelNames.get(l)); - } -} diff --git a/src/asm/scala/tools/asm/util/CheckAnnotationAdapter.java b/src/asm/scala/tools/asm/util/CheckAnnotationAdapter.java deleted file mode 100644 index 70441d1df4..0000000000 --- a/src/asm/scala/tools/asm/util/CheckAnnotationAdapter.java +++ /dev/null @@ -1,136 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.Type; - -/** - * An {@link AnnotationVisitor} that checks that its methods are properly used. - * - * @author Eric Bruneton - */ -public class CheckAnnotationAdapter extends AnnotationVisitor { - - private final boolean named; - - private boolean end; - - public CheckAnnotationAdapter(final AnnotationVisitor av) { - this(av, true); - } - - CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) { - super(Opcodes.ASM5, av); - this.named = named; - } - - @Override - public void visit(final String name, final Object value) { - checkEnd(); - checkName(name); - if (!(value instanceof Byte || value instanceof Boolean - || value instanceof Character || value instanceof Short - || value instanceof Integer || value instanceof Long - || value instanceof Float || value instanceof Double - || value instanceof String || value instanceof Type - || value instanceof byte[] || value instanceof boolean[] - || value instanceof char[] || value instanceof short[] - || value instanceof int[] || value instanceof long[] - || value instanceof float[] || value instanceof double[])) { - throw new IllegalArgumentException("Invalid annotation value"); - } - if (value instanceof Type) { - int sort = ((Type) value).getSort(); - if (sort == Type.METHOD) { - throw new IllegalArgumentException("Invalid annotation value"); - } - } - if (av != null) { - av.visit(name, value); - } - } - - @Override - public void visitEnum(final String name, final String desc, - final String value) { - checkEnd(); - checkName(name); - CheckMethodAdapter.checkDesc(desc, false); - if (value == null) { - throw new IllegalArgumentException("Invalid enum value"); - } - if (av != null) { - av.visitEnum(name, desc, value); - } - } - - @Override - public AnnotationVisitor visitAnnotation(final String name, - final String desc) { - checkEnd(); - checkName(name); - CheckMethodAdapter.checkDesc(desc, false); - return new CheckAnnotationAdapter(av == null ? null - : av.visitAnnotation(name, desc)); - } - - @Override - public AnnotationVisitor visitArray(final String name) { - checkEnd(); - checkName(name); - return new CheckAnnotationAdapter(av == null ? null - : av.visitArray(name), false); - } - - @Override - public void visitEnd() { - checkEnd(); - end = true; - if (av != null) { - av.visitEnd(); - } - } - - private void checkEnd() { - if (end) { - throw new IllegalStateException( - "Cannot call a visit method after visitEnd has been called"); - } - } - - private void checkName(final String name) { - if (named && name == null) { - throw new IllegalArgumentException( - "Annotation value name must not be null"); - } - } -} diff --git a/src/asm/scala/tools/asm/util/CheckClassAdapter.java b/src/asm/scala/tools/asm/util/CheckClassAdapter.java deleted file mode 100644 index 88afdb0441..0000000000 --- a/src/asm/scala/tools/asm/util/CheckClassAdapter.java +++ /dev/null @@ -1,1009 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import java.io.FileInputStream; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Attribute; -import scala.tools.asm.ClassReader; -import scala.tools.asm.ClassVisitor; -import scala.tools.asm.FieldVisitor; -import scala.tools.asm.Label; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.Type; -import scala.tools.asm.TypePath; -import scala.tools.asm.TypeReference; -import scala.tools.asm.tree.ClassNode; -import scala.tools.asm.tree.MethodNode; -import scala.tools.asm.tree.analysis.Analyzer; -import scala.tools.asm.tree.analysis.BasicValue; -import scala.tools.asm.tree.analysis.Frame; -import scala.tools.asm.tree.analysis.SimpleVerifier; - -/** - * A {@link ClassVisitor} that checks that its methods are properly used. More - * precisely this class adapter checks each method call individually, based - * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i> - * of method calls. For example, the invalid sequence - * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC, - * "i", "D", null)</tt> will <i>not</i> be detected by this class adapter. - * - * <p> - * <code>CheckClassAdapter</code> can be also used to verify bytecode - * transformations in order to make sure transformed bytecode is sane. For - * example: - * - * <pre> - * InputStream is = ...; // get bytes for the source class - * ClassReader cr = new ClassReader(is); - * ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); - * ClassVisitor cv = new <b>MyClassAdapter</b>(new CheckClassAdapter(cw)); - * cr.accept(cv, 0); - * - * StringWriter sw = new StringWriter(); - * PrintWriter pw = new PrintWriter(sw); - * CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, pw); - * assertTrue(sw.toString(), sw.toString().length()==0); - * </pre> - * - * Above code runs transformed bytecode trough the - * <code>CheckClassAdapter</code>. It won't be exactly the same verification as - * JVM does, but it run data flow analysis for the code of each method and - * checks that expectations are met for each method instruction. - * - * <p> - * If method bytecode has errors, assertion text will show the erroneous - * instruction number and dump of the failed method with information about - * locals and stack slot for each instruction. For example (format is - - * insnNumber locals : stack): - * - * <pre> - * org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found . - * at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289) - * at org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135) - * ... - * remove()V - * 00000 LinkedBlockingQueue$Itr . . . . . . . . : - * ICONST_0 - * 00001 LinkedBlockingQueue$Itr . . . . . . . . : I - * ISTORE 2 - * 00001 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . : - * ... - * - * 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . : - * ILOAD 1 - * 00072 <b>?</b> - * INVOKESPECIAL java/lang/Integer.<init> (I)V - * ... - * </pre> - * - * In the above output you can see that variable 1 loaded by - * <code>ILOAD 1</code> instruction at position <code>00071</code> is not - * initialized. You can also see that at the beginning of the method (code - * inserted by the transformation) variable 2 is initialized. - * - * <p> - * Note that when used like that, <code>CheckClassAdapter.verify()</code> can - * trigger additional class loading, because it is using - * <code>SimpleVerifier</code>. - * - * @author Eric Bruneton - */ -public class CheckClassAdapter extends ClassVisitor { - - /** - * The class version number. - */ - private int version; - - /** - * <tt>true</tt> if the visit method has been called. - */ - private boolean start; - - /** - * <tt>true</tt> if the visitSource method has been called. - */ - private boolean source; - - /** - * <tt>true</tt> if the visitOuterClass method has been called. - */ - private boolean outer; - - /** - * <tt>true</tt> if the visitEnd method has been called. - */ - private boolean end; - - /** - * The already visited labels. This map associate Integer values to Label - * keys. - */ - private Map<Label, Integer> labels; - - /** - * <tt>true</tt> if the method code must be checked with a BasicVerifier. - */ - private boolean checkDataFlow; - - /** - * Checks a given class. - * <p> - * Usage: CheckClassAdapter <binary class name or class file name> - * - * @param args - * the command line arguments. - * - * @throws Exception - * if the class cannot be found, or if an IO exception occurs. - */ - public static void main(final String[] args) throws Exception { - if (args.length != 1) { - System.err.println("Verifies the given class."); - System.err.println("Usage: CheckClassAdapter " - + "<fully qualified class name or class file name>"); - return; - } - ClassReader cr; - if (args[0].endsWith(".class")) { - cr = new ClassReader(new FileInputStream(args[0])); - } else { - cr = new ClassReader(args[0]); - } - - verify(cr, false, new PrintWriter(System.err)); - } - - /** - * Checks a given class. - * - * @param cr - * a <code>ClassReader</code> that contains bytecode for the - * analysis. - * @param loader - * a <code>ClassLoader</code> which will be used to load - * referenced classes. This is useful if you are verifiying - * multiple interdependent classes. - * @param dump - * true if bytecode should be printed out not only when errors - * are found. - * @param pw - * write where results going to be printed - */ - public static void verify(final ClassReader cr, final ClassLoader loader, - final boolean dump, final PrintWriter pw) { - ClassNode cn = new ClassNode(); - cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG); - - Type syperType = cn.superName == null ? null : Type - .getObjectType(cn.superName); - List<MethodNode> methods = cn.methods; - - List<Type> interfaces = new ArrayList<Type>(); - for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) { - interfaces.add(Type.getObjectType(i.next())); - } - - for (int i = 0; i < methods.size(); ++i) { - MethodNode method = methods.get(i); - SimpleVerifier verifier = new SimpleVerifier( - Type.getObjectType(cn.name), syperType, interfaces, - (cn.access & Opcodes.ACC_INTERFACE) != 0); - Analyzer<BasicValue> a = new Analyzer<BasicValue>(verifier); - if (loader != null) { - verifier.setClassLoader(loader); - } - try { - a.analyze(cn.name, method); - if (!dump) { - continue; - } - } catch (Exception e) { - e.printStackTrace(pw); - } - printAnalyzerResult(method, a, pw); - } - pw.flush(); - } - - /** - * Checks a given class - * - * @param cr - * a <code>ClassReader</code> that contains bytecode for the - * analysis. - * @param dump - * true if bytecode should be printed out not only when errors - * are found. - * @param pw - * write where results going to be printed - */ - public static void verify(final ClassReader cr, final boolean dump, - final PrintWriter pw) { - verify(cr, null, dump, pw); - } - - static void printAnalyzerResult(MethodNode method, Analyzer<BasicValue> a, - final PrintWriter pw) { - Frame<BasicValue>[] frames = a.getFrames(); - Textifier t = new Textifier(); - TraceMethodVisitor mv = new TraceMethodVisitor(t); - - pw.println(method.name + method.desc); - for (int j = 0; j < method.instructions.size(); ++j) { - method.instructions.get(j).accept(mv); - - StringBuilder sb = new StringBuilder(); - Frame<BasicValue> f = frames[j]; - if (f == null) { - sb.append('?'); - } else { - for (int k = 0; k < f.getLocals(); ++k) { - sb.append(getShortName(f.getLocal(k).toString())) - .append(' '); - } - sb.append(" : "); - for (int k = 0; k < f.getStackSize(); ++k) { - sb.append(getShortName(f.getStack(k).toString())) - .append(' '); - } - } - while (sb.length() < method.maxStack + method.maxLocals + 1) { - sb.append(' '); - } - pw.print(Integer.toString(j + 100000).substring(1)); - pw.print(" " + sb + " : " + t.text.get(t.text.size() - 1)); - } - for (int j = 0; j < method.tryCatchBlocks.size(); ++j) { - method.tryCatchBlocks.get(j).accept(mv); - pw.print(" " + t.text.get(t.text.size() - 1)); - } - pw.println(); - } - - private static String getShortName(final String name) { - int n = name.lastIndexOf('/'); - int k = name.length(); - if (name.charAt(k - 1) == ';') { - k--; - } - return n == -1 ? name : name.substring(n + 1, k); - } - - /** - * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use - * this constructor</i>. Instead, they must use the - * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version. - * - * @param cv - * the class visitor to which this adapter must delegate calls. - */ - public CheckClassAdapter(final ClassVisitor cv) { - this(cv, true); - } - - /** - * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use - * this constructor</i>. Instead, they must use the - * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version. - * - * @param cv - * the class visitor to which this adapter must delegate calls. - * @param checkDataFlow - * <tt>true</tt> to perform basic data flow checks, or - * <tt>false</tt> to not perform any data flow check (see - * {@link CheckMethodAdapter}). This option requires valid - * maxLocals and maxStack values. - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) { - this(Opcodes.ASM5, cv, checkDataFlow); - if (getClass() != CheckClassAdapter.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs a new {@link CheckClassAdapter}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param cv - * the class visitor to which this adapter must delegate calls. - * @param checkDataFlow - * <tt>true</tt> to perform basic data flow checks, or - * <tt>false</tt> to not perform any data flow check (see - * {@link CheckMethodAdapter}). This option requires valid - * maxLocals and maxStack values. - */ - protected CheckClassAdapter(final int api, final ClassVisitor cv, - final boolean checkDataFlow) { - super(api, cv); - this.labels = new HashMap<Label, Integer>(); - this.checkDataFlow = checkDataFlow; - } - - // ------------------------------------------------------------------------ - // Implementation of the ClassVisitor interface - // ------------------------------------------------------------------------ - - @Override - public void visit(final int version, final int access, final String name, - final String signature, final String superName, - final String[] interfaces) { - if (start) { - throw new IllegalStateException("visit must be called only once"); - } - start = true; - checkState(); - checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL - + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE - + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC - + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM - + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - if (name == null || !name.endsWith("package-info")) { - CheckMethodAdapter.checkInternalName(name, "class name"); - } - if ("java/lang/Object".equals(name)) { - if (superName != null) { - throw new IllegalArgumentException( - "The super class name of the Object class must be 'null'"); - } - } else { - CheckMethodAdapter.checkInternalName(superName, "super class name"); - } - if (signature != null) { - checkClassSignature(signature); - } - if ((access & Opcodes.ACC_INTERFACE) != 0) { - if (!"java/lang/Object".equals(superName)) { - throw new IllegalArgumentException( - "The super class name of interfaces must be 'java/lang/Object'"); - } - } - if (interfaces != null) { - for (int i = 0; i < interfaces.length; ++i) { - CheckMethodAdapter.checkInternalName(interfaces[i], - "interface name at index " + i); - } - } - this.version = version; - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public void visitSource(final String file, final String debug) { - checkState(); - if (source) { - throw new IllegalStateException( - "visitSource can be called only once."); - } - source = true; - super.visitSource(file, debug); - } - - @Override - public void visitOuterClass(final String owner, final String name, - final String desc) { - checkState(); - if (outer) { - throw new IllegalStateException( - "visitOuterClass can be called only once."); - } - outer = true; - if (owner == null) { - throw new IllegalArgumentException("Illegal outer class owner"); - } - if (desc != null) { - CheckMethodAdapter.checkMethodDesc(desc); - } - super.visitOuterClass(owner, name, desc); - } - - @Override - public void visitInnerClass(final String name, final String outerName, - final String innerName, final int access) { - checkState(); - CheckMethodAdapter.checkInternalName(name, "class name"); - if (outerName != null) { - CheckMethodAdapter.checkInternalName(outerName, "outer class name"); - } - if (innerName != null) { - int start = 0; - while (start < innerName.length() - && Character.isDigit(innerName.charAt(start))) { - start++; - } - if (start == 0 || start < innerName.length()) { - CheckMethodAdapter.checkIdentifier(innerName, start, -1, - "inner class name"); - } - } - checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE - + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC - + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE - + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC - + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM); - super.visitInnerClass(name, outerName, innerName, access); - } - - @Override - public FieldVisitor visitField(final int access, final String name, - final String desc, final String signature, final Object value) { - checkState(); - checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE - + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC - + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE - + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC - + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - CheckMethodAdapter.checkUnqualifiedName(version, name, "field name"); - CheckMethodAdapter.checkDesc(desc, false); - if (signature != null) { - checkFieldSignature(signature); - } - if (value != null) { - CheckMethodAdapter.checkConstant(value); - } - FieldVisitor av = super - .visitField(access, name, desc, signature, value); - return new CheckFieldAdapter(av); - } - - @Override - public MethodVisitor visitMethod(final int access, final String name, - final String desc, final String signature, final String[] exceptions) { - checkState(); - checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE - + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC - + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED - + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE - + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT - + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE - if (!"<init>".equals(name) && !"<clinit>".equals(name)) { - CheckMethodAdapter.checkMethodIdentifier(version, name, - "method name"); - } - CheckMethodAdapter.checkMethodDesc(desc); - if (signature != null) { - checkMethodSignature(signature); - } - if (exceptions != null) { - for (int i = 0; i < exceptions.length; ++i) { - CheckMethodAdapter.checkInternalName(exceptions[i], - "exception name at index " + i); - } - } - CheckMethodAdapter cma; - if (checkDataFlow) { - cma = new CheckMethodAdapter(access, name, desc, super.visitMethod( - access, name, desc, signature, exceptions), labels); - } else { - cma = new CheckMethodAdapter(super.visitMethod(access, name, desc, - signature, exceptions), labels); - } - cma.version = version; - return cma; - } - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - checkState(); - CheckMethodAdapter.checkDesc(desc, false); - return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible)); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - checkState(); - int sort = typeRef >>> 24; - if (sort != TypeReference.CLASS_TYPE_PARAMETER - && sort != TypeReference.CLASS_TYPE_PARAMETER_BOUND - && sort != TypeReference.CLASS_EXTENDS) { - throw new IllegalArgumentException("Invalid type reference sort 0x" - + Integer.toHexString(sort)); - } - checkTypeRefAndPath(typeRef, typePath); - CheckMethodAdapter.checkDesc(desc, false); - return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef, - typePath, desc, visible)); - } - - @Override - public void visitAttribute(final Attribute attr) { - checkState(); - if (attr == null) { - throw new IllegalArgumentException( - "Invalid attribute (must not be null)"); - } - super.visitAttribute(attr); - } - - @Override - public void visitEnd() { - checkState(); - end = true; - super.visitEnd(); - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - /** - * Checks that the visit method has been called and that visitEnd has not - * been called. - */ - private void checkState() { - if (!start) { - throw new IllegalStateException( - "Cannot visit member before visit has been called."); - } - if (end) { - throw new IllegalStateException( - "Cannot visit member after visitEnd has been called."); - } - } - - /** - * Checks that the given access flags do not contain invalid flags. This - * method also checks that mutually incompatible flags are not set - * simultaneously. - * - * @param access - * the access flags to be checked - * @param possibleAccess - * the valid access flags. - */ - static void checkAccess(final int access, final int possibleAccess) { - if ((access & ~possibleAccess) != 0) { - throw new IllegalArgumentException("Invalid access flags: " - + access); - } - int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1; - int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1; - int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1; - if (pub + pri + pro > 1) { - throw new IllegalArgumentException( - "public private and protected are mutually exclusive: " - + access); - } - int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1; - int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1; - if (fin + abs > 1) { - throw new IllegalArgumentException( - "final and abstract are mutually exclusive: " + access); - } - } - - /** - * Checks a class signature. - * - * @param signature - * a string containing the signature that must be checked. - */ - public static void checkClassSignature(final String signature) { - // ClassSignature: - // FormalTypeParameters? ClassTypeSignature ClassTypeSignature* - - int pos = 0; - if (getChar(signature, 0) == '<') { - pos = checkFormalTypeParameters(signature, pos); - } - pos = checkClassTypeSignature(signature, pos); - while (getChar(signature, pos) == 'L') { - pos = checkClassTypeSignature(signature, pos); - } - if (pos != signature.length()) { - throw new IllegalArgumentException(signature + ": error at index " - + pos); - } - } - - /** - * Checks a method signature. - * - * @param signature - * a string containing the signature that must be checked. - */ - public static void checkMethodSignature(final String signature) { - // MethodTypeSignature: - // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) ( - // ^ClassTypeSignature | ^TypeVariableSignature )* - - int pos = 0; - if (getChar(signature, 0) == '<') { - pos = checkFormalTypeParameters(signature, pos); - } - pos = checkChar('(', signature, pos); - while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) { - pos = checkTypeSignature(signature, pos); - } - pos = checkChar(')', signature, pos); - if (getChar(signature, pos) == 'V') { - ++pos; - } else { - pos = checkTypeSignature(signature, pos); - } - while (getChar(signature, pos) == '^') { - ++pos; - if (getChar(signature, pos) == 'L') { - pos = checkClassTypeSignature(signature, pos); - } else { - pos = checkTypeVariableSignature(signature, pos); - } - } - if (pos != signature.length()) { - throw new IllegalArgumentException(signature + ": error at index " - + pos); - } - } - - /** - * Checks a field signature. - * - * @param signature - * a string containing the signature that must be checked. - */ - public static void checkFieldSignature(final String signature) { - int pos = checkFieldTypeSignature(signature, 0); - if (pos != signature.length()) { - throw new IllegalArgumentException(signature + ": error at index " - + pos); - } - } - - /** - * Checks the reference to a type in a type annotation. - * - * @param typeRef - * a reference to an annotated type. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - */ - static void checkTypeRefAndPath(int typeRef, TypePath typePath) { - int mask = 0; - switch (typeRef >>> 24) { - case TypeReference.CLASS_TYPE_PARAMETER: - case TypeReference.METHOD_TYPE_PARAMETER: - case TypeReference.METHOD_FORMAL_PARAMETER: - mask = 0xFFFF0000; - break; - case TypeReference.FIELD: - case TypeReference.METHOD_RETURN: - case TypeReference.METHOD_RECEIVER: - case TypeReference.LOCAL_VARIABLE: - case TypeReference.RESOURCE_VARIABLE: - case TypeReference.INSTANCEOF: - case TypeReference.NEW: - case TypeReference.CONSTRUCTOR_REFERENCE: - case TypeReference.METHOD_REFERENCE: - mask = 0xFF000000; - break; - case TypeReference.CLASS_EXTENDS: - case TypeReference.CLASS_TYPE_PARAMETER_BOUND: - case TypeReference.METHOD_TYPE_PARAMETER_BOUND: - case TypeReference.THROWS: - case TypeReference.EXCEPTION_PARAMETER: - mask = 0xFFFFFF00; - break; - case TypeReference.CAST: - case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: - case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT: - case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: - case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT: - mask = 0xFF0000FF; - break; - default: - throw new IllegalArgumentException("Invalid type reference sort 0x" - + Integer.toHexString(typeRef >>> 24)); - } - if ((typeRef & ~mask) != 0) { - throw new IllegalArgumentException("Invalid type reference 0x" - + Integer.toHexString(typeRef)); - } - if (typePath != null) { - for (int i = 0; i < typePath.getLength(); ++i) { - int step = typePath.getStep(i); - if (step != TypePath.ARRAY_ELEMENT - && step != TypePath.INNER_TYPE - && step != TypePath.TYPE_ARGUMENT - && step != TypePath.WILDCARD_BOUND) { - throw new IllegalArgumentException( - "Invalid type path step " + i + " in " + typePath); - } - if (step != TypePath.TYPE_ARGUMENT - && typePath.getStepArgument(i) != 0) { - throw new IllegalArgumentException( - "Invalid type path step argument for step " + i - + " in " + typePath); - } - } - } - } - - /** - * Checks the formal type parameters of a class or method signature. - * - * @param signature - * a string containing the signature that must be checked. - * @param pos - * index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkFormalTypeParameters(final String signature, int pos) { - // FormalTypeParameters: - // < FormalTypeParameter+ > - - pos = checkChar('<', signature, pos); - pos = checkFormalTypeParameter(signature, pos); - while (getChar(signature, pos) != '>') { - pos = checkFormalTypeParameter(signature, pos); - } - return pos + 1; - } - - /** - * Checks a formal type parameter of a class or method signature. - * - * @param signature - * a string containing the signature that must be checked. - * @param pos - * index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkFormalTypeParameter(final String signature, int pos) { - // FormalTypeParameter: - // Identifier : FieldTypeSignature? (: FieldTypeSignature)* - - pos = checkIdentifier(signature, pos); - pos = checkChar(':', signature, pos); - if ("L[T".indexOf(getChar(signature, pos)) != -1) { - pos = checkFieldTypeSignature(signature, pos); - } - while (getChar(signature, pos) == ':') { - pos = checkFieldTypeSignature(signature, pos + 1); - } - return pos; - } - - /** - * Checks a field type signature. - * - * @param signature - * a string containing the signature that must be checked. - * @param pos - * index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkFieldTypeSignature(final String signature, int pos) { - // FieldTypeSignature: - // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature - // - // ArrayTypeSignature: - // [ TypeSignature - - switch (getChar(signature, pos)) { - case 'L': - return checkClassTypeSignature(signature, pos); - case '[': - return checkTypeSignature(signature, pos + 1); - default: - return checkTypeVariableSignature(signature, pos); - } - } - - /** - * Checks a class type signature. - * - * @param signature - * a string containing the signature that must be checked. - * @param pos - * index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkClassTypeSignature(final String signature, int pos) { - // ClassTypeSignature: - // L Identifier ( / Identifier )* TypeArguments? ( . Identifier - // TypeArguments? )* ; - - pos = checkChar('L', signature, pos); - pos = checkIdentifier(signature, pos); - while (getChar(signature, pos) == '/') { - pos = checkIdentifier(signature, pos + 1); - } - if (getChar(signature, pos) == '<') { - pos = checkTypeArguments(signature, pos); - } - while (getChar(signature, pos) == '.') { - pos = checkIdentifier(signature, pos + 1); - if (getChar(signature, pos) == '<') { - pos = checkTypeArguments(signature, pos); - } - } - return checkChar(';', signature, pos); - } - - /** - * Checks the type arguments in a class type signature. - * - * @param signature - * a string containing the signature that must be checked. - * @param pos - * index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkTypeArguments(final String signature, int pos) { - // TypeArguments: - // < TypeArgument+ > - - pos = checkChar('<', signature, pos); - pos = checkTypeArgument(signature, pos); - while (getChar(signature, pos) != '>') { - pos = checkTypeArgument(signature, pos); - } - return pos + 1; - } - - /** - * Checks a type argument in a class type signature. - * - * @param signature - * a string containing the signature that must be checked. - * @param pos - * index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkTypeArgument(final String signature, int pos) { - // TypeArgument: - // * | ( ( + | - )? FieldTypeSignature ) - - char c = getChar(signature, pos); - if (c == '*') { - return pos + 1; - } else if (c == '+' || c == '-') { - pos++; - } - return checkFieldTypeSignature(signature, pos); - } - - /** - * Checks a type variable signature. - * - * @param signature - * a string containing the signature that must be checked. - * @param pos - * index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkTypeVariableSignature(final String signature, - int pos) { - // TypeVariableSignature: - // T Identifier ; - - pos = checkChar('T', signature, pos); - pos = checkIdentifier(signature, pos); - return checkChar(';', signature, pos); - } - - /** - * Checks a type signature. - * - * @param signature - * a string containing the signature that must be checked. - * @param pos - * index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkTypeSignature(final String signature, int pos) { - // TypeSignature: - // Z | C | B | S | I | F | J | D | FieldTypeSignature - - switch (getChar(signature, pos)) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - case 'F': - case 'J': - case 'D': - return pos + 1; - default: - return checkFieldTypeSignature(signature, pos); - } - } - - /** - * Checks an identifier. - * - * @param signature - * a string containing the signature that must be checked. - * @param pos - * index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkIdentifier(final String signature, int pos) { - if (!Character.isJavaIdentifierStart(getChar(signature, pos))) { - throw new IllegalArgumentException(signature - + ": identifier expected at index " + pos); - } - ++pos; - while (Character.isJavaIdentifierPart(getChar(signature, pos))) { - ++pos; - } - return pos; - } - - /** - * Checks a single character. - * - * @param signature - * a string containing the signature that must be checked. - * @param pos - * index of first character to be checked. - * @return the index of the first character after the checked part. - */ - private static int checkChar(final char c, final String signature, int pos) { - if (getChar(signature, pos) == c) { - return pos + 1; - } - throw new IllegalArgumentException(signature + ": '" + c - + "' expected at index " + pos); - } - - /** - * Returns the signature car at the given index. - * - * @param signature - * a signature. - * @param pos - * an index in signature. - * @return the character at the given index, or 0 if there is no such - * character. - */ - private static char getChar(final String signature, int pos) { - return pos < signature.length() ? signature.charAt(pos) : (char) 0; - } -} diff --git a/src/asm/scala/tools/asm/util/CheckFieldAdapter.java b/src/asm/scala/tools/asm/util/CheckFieldAdapter.java deleted file mode 100644 index e682df47af..0000000000 --- a/src/asm/scala/tools/asm/util/CheckFieldAdapter.java +++ /dev/null @@ -1,122 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Attribute; -import scala.tools.asm.FieldVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.TypePath; -import scala.tools.asm.TypeReference; - -/** - * A {@link FieldVisitor} that checks that its methods are properly used. - */ -public class CheckFieldAdapter extends FieldVisitor { - - private boolean end; - - /** - * Constructs a new {@link CheckFieldAdapter}. <i>Subclasses must not use - * this constructor</i>. Instead, they must use the - * {@link #CheckFieldAdapter(int, FieldVisitor)} version. - * - * @param fv - * the field visitor to which this adapter must delegate calls. - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public CheckFieldAdapter(final FieldVisitor fv) { - this(Opcodes.ASM5, fv); - if (getClass() != CheckFieldAdapter.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs a new {@link CheckFieldAdapter}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param fv - * the field visitor to which this adapter must delegate calls. - */ - protected CheckFieldAdapter(final int api, final FieldVisitor fv) { - super(api, fv); - } - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - checkEnd(); - CheckMethodAdapter.checkDesc(desc, false); - return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible)); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - checkEnd(); - int sort = typeRef >>> 24; - if (sort != TypeReference.FIELD) { - throw new IllegalArgumentException("Invalid type reference sort 0x" - + Integer.toHexString(sort)); - } - CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath); - CheckMethodAdapter.checkDesc(desc, false); - return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef, - typePath, desc, visible)); - } - - @Override - public void visitAttribute(final Attribute attr) { - checkEnd(); - if (attr == null) { - throw new IllegalArgumentException( - "Invalid attribute (must not be null)"); - } - super.visitAttribute(attr); - } - - @Override - public void visitEnd() { - checkEnd(); - end = true; - super.visitEnd(); - } - - private void checkEnd() { - if (end) { - throw new IllegalStateException( - "Cannot call a visit method after visitEnd has been called"); - } - } -} diff --git a/src/asm/scala/tools/asm/util/CheckMethodAdapter.java b/src/asm/scala/tools/asm/util/CheckMethodAdapter.java deleted file mode 100644 index 131dfa5e5b..0000000000 --- a/src/asm/scala/tools/asm/util/CheckMethodAdapter.java +++ /dev/null @@ -1,1542 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Attribute; -import scala.tools.asm.Handle; -import scala.tools.asm.Label; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.Type; -import scala.tools.asm.TypePath; -import scala.tools.asm.TypeReference; -import scala.tools.asm.tree.MethodNode; -import scala.tools.asm.tree.analysis.Analyzer; -import scala.tools.asm.tree.analysis.BasicValue; -import scala.tools.asm.tree.analysis.BasicVerifier; - -/** - * A {@link MethodVisitor} that checks that its methods are properly used. More - * precisely this method adapter checks each instruction individually, i.e., - * each visit method checks some preconditions based <i>only</i> on its - * arguments - such as the fact that the given opcode is correct for a given - * visit method. This adapter can also perform some basic data flow checks (more - * precisely those that can be performed without the full class hierarchy - see - * {@link scala.tools.asm.tree.analysis.BasicVerifier}). For instance in a - * method whose signature is <tt>void m ()</tt>, the invalid instruction - * IRETURN, or the invalid sequence IADD L2I will be detected if the data flow - * checks are enabled. These checks are enabled by using the - * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)} constructor. - * They are not performed if any other constructor is used. - * - * @author Eric Bruneton - */ -public class CheckMethodAdapter extends MethodVisitor { - - /** - * The class version number. - */ - public int version; - - /** - * The access flags of the method. - */ - private int access; - - /** - * <tt>true</tt> if the visitCode method has been called. - */ - private boolean startCode; - - /** - * <tt>true</tt> if the visitMaxs method has been called. - */ - private boolean endCode; - - /** - * <tt>true</tt> if the visitEnd method has been called. - */ - private boolean endMethod; - - /** - * Number of visited instructions. - */ - private int insnCount; - - /** - * The already visited labels. This map associate Integer values to pseudo - * code offsets. - */ - private final Map<Label, Integer> labels; - - /** - * The labels used in this method. Every used label must be visited with - * visitLabel before the end of the method (i.e. should be in #labels). - */ - private Set<Label> usedLabels; - - /** - * Number of visited frames in expanded form. - */ - private int expandedFrames; - - /** - * Number of visited frames in compressed form. - */ - private int compressedFrames; - - /** - * Number of instructions before the last visited frame. - */ - private int lastFrame = -1; - - /** - * The exception handler ranges. Each pair of list element contains the - * start and end labels of an exception handler block. - */ - private List<Label> handlers; - - /** - * Code of the visit method to be used for each opcode. - */ - private static final int[] TYPE; - - /** - * The Label.status field. - */ - private static Field labelStatusField; - - static { - String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD" - + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" - + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD" - + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA"; - TYPE = new int[s.length()]; - for (int i = 0; i < TYPE.length; ++i) { - TYPE[i] = s.charAt(i) - 'A' - 1; - } - } - - // code to generate the above string - // public static void main (String[] args) { - // int[] TYPE = new int[] { - // 0, //NOP - // 0, //ACONST_NULL - // 0, //ICONST_M1 - // 0, //ICONST_0 - // 0, //ICONST_1 - // 0, //ICONST_2 - // 0, //ICONST_3 - // 0, //ICONST_4 - // 0, //ICONST_5 - // 0, //LCONST_0 - // 0, //LCONST_1 - // 0, //FCONST_0 - // 0, //FCONST_1 - // 0, //FCONST_2 - // 0, //DCONST_0 - // 0, //DCONST_1 - // 1, //BIPUSH - // 1, //SIPUSH - // 7, //LDC - // -1, //LDC_W - // -1, //LDC2_W - // 2, //ILOAD - // 2, //LLOAD - // 2, //FLOAD - // 2, //DLOAD - // 2, //ALOAD - // -1, //ILOAD_0 - // -1, //ILOAD_1 - // -1, //ILOAD_2 - // -1, //ILOAD_3 - // -1, //LLOAD_0 - // -1, //LLOAD_1 - // -1, //LLOAD_2 - // -1, //LLOAD_3 - // -1, //FLOAD_0 - // -1, //FLOAD_1 - // -1, //FLOAD_2 - // -1, //FLOAD_3 - // -1, //DLOAD_0 - // -1, //DLOAD_1 - // -1, //DLOAD_2 - // -1, //DLOAD_3 - // -1, //ALOAD_0 - // -1, //ALOAD_1 - // -1, //ALOAD_2 - // -1, //ALOAD_3 - // 0, //IALOAD - // 0, //LALOAD - // 0, //FALOAD - // 0, //DALOAD - // 0, //AALOAD - // 0, //BALOAD - // 0, //CALOAD - // 0, //SALOAD - // 2, //ISTORE - // 2, //LSTORE - // 2, //FSTORE - // 2, //DSTORE - // 2, //ASTORE - // -1, //ISTORE_0 - // -1, //ISTORE_1 - // -1, //ISTORE_2 - // -1, //ISTORE_3 - // -1, //LSTORE_0 - // -1, //LSTORE_1 - // -1, //LSTORE_2 - // -1, //LSTORE_3 - // -1, //FSTORE_0 - // -1, //FSTORE_1 - // -1, //FSTORE_2 - // -1, //FSTORE_3 - // -1, //DSTORE_0 - // -1, //DSTORE_1 - // -1, //DSTORE_2 - // -1, //DSTORE_3 - // -1, //ASTORE_0 - // -1, //ASTORE_1 - // -1, //ASTORE_2 - // -1, //ASTORE_3 - // 0, //IASTORE - // 0, //LASTORE - // 0, //FASTORE - // 0, //DASTORE - // 0, //AASTORE - // 0, //BASTORE - // 0, //CASTORE - // 0, //SASTORE - // 0, //POP - // 0, //POP2 - // 0, //DUP - // 0, //DUP_X1 - // 0, //DUP_X2 - // 0, //DUP2 - // 0, //DUP2_X1 - // 0, //DUP2_X2 - // 0, //SWAP - // 0, //IADD - // 0, //LADD - // 0, //FADD - // 0, //DADD - // 0, //ISUB - // 0, //LSUB - // 0, //FSUB - // 0, //DSUB - // 0, //IMUL - // 0, //LMUL - // 0, //FMUL - // 0, //DMUL - // 0, //IDIV - // 0, //LDIV - // 0, //FDIV - // 0, //DDIV - // 0, //IREM - // 0, //LREM - // 0, //FREM - // 0, //DREM - // 0, //INEG - // 0, //LNEG - // 0, //FNEG - // 0, //DNEG - // 0, //ISHL - // 0, //LSHL - // 0, //ISHR - // 0, //LSHR - // 0, //IUSHR - // 0, //LUSHR - // 0, //IAND - // 0, //LAND - // 0, //IOR - // 0, //LOR - // 0, //IXOR - // 0, //LXOR - // 8, //IINC - // 0, //I2L - // 0, //I2F - // 0, //I2D - // 0, //L2I - // 0, //L2F - // 0, //L2D - // 0, //F2I - // 0, //F2L - // 0, //F2D - // 0, //D2I - // 0, //D2L - // 0, //D2F - // 0, //I2B - // 0, //I2C - // 0, //I2S - // 0, //LCMP - // 0, //FCMPL - // 0, //FCMPG - // 0, //DCMPL - // 0, //DCMPG - // 6, //IFEQ - // 6, //IFNE - // 6, //IFLT - // 6, //IFGE - // 6, //IFGT - // 6, //IFLE - // 6, //IF_ICMPEQ - // 6, //IF_ICMPNE - // 6, //IF_ICMPLT - // 6, //IF_ICMPGE - // 6, //IF_ICMPGT - // 6, //IF_ICMPLE - // 6, //IF_ACMPEQ - // 6, //IF_ACMPNE - // 6, //GOTO - // 6, //JSR - // 2, //RET - // 9, //TABLESWITCH - // 10, //LOOKUPSWITCH - // 0, //IRETURN - // 0, //LRETURN - // 0, //FRETURN - // 0, //DRETURN - // 0, //ARETURN - // 0, //RETURN - // 4, //GETSTATIC - // 4, //PUTSTATIC - // 4, //GETFIELD - // 4, //PUTFIELD - // 5, //INVOKEVIRTUAL - // 5, //INVOKESPECIAL - // 5, //INVOKESTATIC - // 5, //INVOKEINTERFACE - // -1, //INVOKEDYNAMIC - // 3, //NEW - // 1, //NEWARRAY - // 3, //ANEWARRAY - // 0, //ARRAYLENGTH - // 0, //ATHROW - // 3, //CHECKCAST - // 3, //INSTANCEOF - // 0, //MONITORENTER - // 0, //MONITOREXIT - // -1, //WIDE - // 11, //MULTIANEWARRAY - // 6, //IFNULL - // 6, //IFNONNULL - // -1, //GOTO_W - // -1 //JSR_W - // }; - // for (int i = 0; i < TYPE.length; ++i) { - // System.out.print((char)(TYPE[i] + 1 + 'A')); - // } - // System.out.println(); - // } - - /** - * Constructs a new {@link CheckMethodAdapter} object. This method adapter - * will not perform any data flow check (see - * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}). - * <i>Subclasses must not use this constructor</i>. Instead, they must use - * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version. - * - * @param mv - * the method visitor to which this adapter must delegate calls. - */ - public CheckMethodAdapter(final MethodVisitor mv) { - this(mv, new HashMap<Label, Integer>()); - } - - /** - * Constructs a new {@link CheckMethodAdapter} object. This method adapter - * will not perform any data flow check (see - * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}). - * <i>Subclasses must not use this constructor</i>. Instead, they must use - * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version. - * - * @param mv - * the method visitor to which this adapter must delegate calls. - * @param labels - * a map of already visited labels (in other methods). - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public CheckMethodAdapter(final MethodVisitor mv, - final Map<Label, Integer> labels) { - this(Opcodes.ASM5, mv, labels); - if (getClass() != CheckMethodAdapter.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs a new {@link CheckMethodAdapter} object. This method adapter - * will not perform any data flow check (see - * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}). - * - * @param mv - * the method visitor to which this adapter must delegate calls. - * @param labels - * a map of already visited labels (in other methods). - */ - protected CheckMethodAdapter(final int api, final MethodVisitor mv, - final Map<Label, Integer> labels) { - super(api, mv); - this.labels = labels; - this.usedLabels = new HashSet<Label>(); - this.handlers = new ArrayList<Label>(); - } - - /** - * Constructs a new {@link CheckMethodAdapter} object. This method adapter - * will perform basic data flow checks. For instance in a method whose - * signature is <tt>void m ()</tt>, the invalid instruction IRETURN, or the - * invalid sequence IADD L2I will be detected. - * - * @param access - * the method's access flags. - * @param name - * the method's name. - * @param desc - * the method's descriptor (see {@link Type Type}). - * @param cmv - * the method visitor to which this adapter must delegate calls. - * @param labels - * a map of already visited labels (in other methods). - */ - public CheckMethodAdapter(final int access, final String name, - final String desc, final MethodVisitor cmv, - final Map<Label, Integer> labels) { - this(new MethodNode(Opcodes.ASM5, access, name, desc, null, null) { - @Override - public void visitEnd() { - Analyzer<BasicValue> a = new Analyzer<BasicValue>( - new BasicVerifier()); - try { - a.analyze("dummy", this); - } catch (Exception e) { - if (e instanceof IndexOutOfBoundsException - && maxLocals == 0 && maxStack == 0) { - throw new RuntimeException( - "Data flow checking option requires valid, non zero maxLocals and maxStack values."); - } - e.printStackTrace(); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw, true); - CheckClassAdapter.printAnalyzerResult(this, a, pw); - pw.close(); - throw new RuntimeException(e.getMessage() + ' ' - + sw.toString()); - } - accept(cmv); - } - }, labels); - this.access = access; - } - - @Override - public void visitParameter(String name, int access) { - if (name != null) { - checkUnqualifiedName(version, name, "name"); - } - CheckClassAdapter.checkAccess(access, Opcodes.ACC_FINAL - + Opcodes.ACC_MANDATED + Opcodes.ACC_SYNTHETIC); - super.visitParameter(name, access); - } - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - checkEndMethod(); - checkDesc(desc, false); - return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible)); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - checkEndMethod(); - int sort = typeRef >>> 24; - if (sort != TypeReference.METHOD_TYPE_PARAMETER - && sort != TypeReference.METHOD_TYPE_PARAMETER_BOUND - && sort != TypeReference.METHOD_RETURN - && sort != TypeReference.METHOD_RECEIVER - && sort != TypeReference.METHOD_FORMAL_PARAMETER - && sort != TypeReference.THROWS) { - throw new IllegalArgumentException("Invalid type reference sort 0x" - + Integer.toHexString(sort)); - } - CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath); - CheckMethodAdapter.checkDesc(desc, false); - return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef, - typePath, desc, visible)); - } - - @Override - public AnnotationVisitor visitAnnotationDefault() { - checkEndMethod(); - return new CheckAnnotationAdapter(super.visitAnnotationDefault(), false); - } - - @Override - public AnnotationVisitor visitParameterAnnotation(final int parameter, - final String desc, final boolean visible) { - checkEndMethod(); - checkDesc(desc, false); - return new CheckAnnotationAdapter(super.visitParameterAnnotation( - parameter, desc, visible)); - } - - @Override - public void visitAttribute(final Attribute attr) { - checkEndMethod(); - if (attr == null) { - throw new IllegalArgumentException( - "Invalid attribute (must not be null)"); - } - super.visitAttribute(attr); - } - - @Override - public void visitCode() { - if ((access & Opcodes.ACC_ABSTRACT) != 0) { - throw new RuntimeException("Abstract methods cannot have code"); - } - startCode = true; - super.visitCode(); - } - - @Override - public void visitFrame(final int type, final int nLocal, - final Object[] local, final int nStack, final Object[] stack) { - if (insnCount == lastFrame) { - throw new IllegalStateException( - "At most one frame can be visited at a given code location."); - } - lastFrame = insnCount; - int mLocal; - int mStack; - switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - mLocal = Integer.MAX_VALUE; - mStack = Integer.MAX_VALUE; - break; - - case Opcodes.F_SAME: - mLocal = 0; - mStack = 0; - break; - - case Opcodes.F_SAME1: - mLocal = 0; - mStack = 1; - break; - - case Opcodes.F_APPEND: - case Opcodes.F_CHOP: - mLocal = 3; - mStack = 0; - break; - - default: - throw new IllegalArgumentException("Invalid frame type " + type); - } - - if (nLocal > mLocal) { - throw new IllegalArgumentException("Invalid nLocal=" + nLocal - + " for frame type " + type); - } - if (nStack > mStack) { - throw new IllegalArgumentException("Invalid nStack=" + nStack - + " for frame type " + type); - } - - if (type != Opcodes.F_CHOP) { - if (nLocal > 0 && (local == null || local.length < nLocal)) { - throw new IllegalArgumentException( - "Array local[] is shorter than nLocal"); - } - for (int i = 0; i < nLocal; ++i) { - checkFrameValue(local[i]); - } - } - if (nStack > 0 && (stack == null || stack.length < nStack)) { - throw new IllegalArgumentException( - "Array stack[] is shorter than nStack"); - } - for (int i = 0; i < nStack; ++i) { - checkFrameValue(stack[i]); - } - if (type == Opcodes.F_NEW) { - ++expandedFrames; - } else { - ++compressedFrames; - } - if (expandedFrames > 0 && compressedFrames > 0) { - throw new RuntimeException( - "Expanded and compressed frames must not be mixed."); - } - super.visitFrame(type, nLocal, local, nStack, stack); - } - - @Override - public void visitInsn(final int opcode) { - checkStartCode(); - checkEndCode(); - checkOpcode(opcode, 0); - super.visitInsn(opcode); - ++insnCount; - } - - @Override - public void visitIntInsn(final int opcode, final int operand) { - checkStartCode(); - checkEndCode(); - checkOpcode(opcode, 1); - switch (opcode) { - case Opcodes.BIPUSH: - checkSignedByte(operand, "Invalid operand"); - break; - case Opcodes.SIPUSH: - checkSignedShort(operand, "Invalid operand"); - break; - // case Constants.NEWARRAY: - default: - if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) { - throw new IllegalArgumentException( - "Invalid operand (must be an array type code T_...): " - + operand); - } - } - super.visitIntInsn(opcode, operand); - ++insnCount; - } - - @Override - public void visitVarInsn(final int opcode, final int var) { - checkStartCode(); - checkEndCode(); - checkOpcode(opcode, 2); - checkUnsignedShort(var, "Invalid variable index"); - super.visitVarInsn(opcode, var); - ++insnCount; - } - - @Override - public void visitTypeInsn(final int opcode, final String type) { - checkStartCode(); - checkEndCode(); - checkOpcode(opcode, 3); - checkInternalName(type, "type"); - if (opcode == Opcodes.NEW && type.charAt(0) == '[') { - throw new IllegalArgumentException( - "NEW cannot be used to create arrays: " + type); - } - super.visitTypeInsn(opcode, type); - ++insnCount; - } - - @Override - public void visitFieldInsn(final int opcode, final String owner, - final String name, final String desc) { - checkStartCode(); - checkEndCode(); - checkOpcode(opcode, 4); - checkInternalName(owner, "owner"); - checkUnqualifiedName(version, name, "name"); - checkDesc(desc, false); - super.visitFieldInsn(opcode, owner, name, desc); - ++insnCount; - } - - @Deprecated - @Override - public void visitMethodInsn(int opcode, String owner, String name, - String desc) { - if (api >= Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc); - return; - } - doVisitMethodInsn(opcode, owner, name, desc, - opcode == Opcodes.INVOKEINTERFACE); - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, - String desc, boolean itf) { - if (api < Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - doVisitMethodInsn(opcode, owner, name, desc, itf); - } - - private void doVisitMethodInsn(int opcode, final String owner, - final String name, final String desc, final boolean itf) { - checkStartCode(); - checkEndCode(); - checkOpcode(opcode, 5); - if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) { - checkMethodIdentifier(version, name, "name"); - } - checkInternalName(owner, "owner"); - checkMethodDesc(desc); - if (opcode == Opcodes.INVOKEVIRTUAL && itf) { - throw new IllegalArgumentException( - "INVOKEVIRTUAL can't be used with interfaces"); - } - if (opcode == Opcodes.INVOKEINTERFACE && !itf) { - throw new IllegalArgumentException( - "INVOKEINTERFACE can't be used with classes"); - } - // Calling super.visitMethodInsn requires to call the correct version - // depending on this.api (otherwise infinite loops can occur). To - // simplify and to make it easier to automatically remove the backward - // compatibility code, we inline the code of the overridden method here. - if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc, itf); - } - ++insnCount; - } - - @Override - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, - Object... bsmArgs) { - checkStartCode(); - checkEndCode(); - checkMethodIdentifier(version, name, "name"); - checkMethodDesc(desc); - if (bsm.getTag() != Opcodes.H_INVOKESTATIC - && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) { - throw new IllegalArgumentException("invalid handle tag " - + bsm.getTag()); - } - for (int i = 0; i < bsmArgs.length; i++) { - checkLDCConstant(bsmArgs[i]); - } - super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); - ++insnCount; - } - - @Override - public void visitJumpInsn(final int opcode, final Label label) { - checkStartCode(); - checkEndCode(); - checkOpcode(opcode, 6); - checkLabel(label, false, "label"); - checkNonDebugLabel(label); - super.visitJumpInsn(opcode, label); - usedLabels.add(label); - ++insnCount; - } - - @Override - public void visitLabel(final Label label) { - checkStartCode(); - checkEndCode(); - checkLabel(label, false, "label"); - if (labels.get(label) != null) { - throw new IllegalArgumentException("Already visited label"); - } - labels.put(label, new Integer(insnCount)); - super.visitLabel(label); - } - - @Override - public void visitLdcInsn(final Object cst) { - checkStartCode(); - checkEndCode(); - checkLDCConstant(cst); - super.visitLdcInsn(cst); - ++insnCount; - } - - @Override - public void visitIincInsn(final int var, final int increment) { - checkStartCode(); - checkEndCode(); - checkUnsignedShort(var, "Invalid variable index"); - checkSignedShort(increment, "Invalid increment"); - super.visitIincInsn(var, increment); - ++insnCount; - } - - @Override - public void visitTableSwitchInsn(final int min, final int max, - final Label dflt, final Label... labels) { - checkStartCode(); - checkEndCode(); - if (max < min) { - throw new IllegalArgumentException("Max = " + max - + " must be greater than or equal to min = " + min); - } - checkLabel(dflt, false, "default label"); - checkNonDebugLabel(dflt); - if (labels == null || labels.length != max - min + 1) { - throw new IllegalArgumentException( - "There must be max - min + 1 labels"); - } - for (int i = 0; i < labels.length; ++i) { - checkLabel(labels[i], false, "label at index " + i); - checkNonDebugLabel(labels[i]); - } - super.visitTableSwitchInsn(min, max, dflt, labels); - for (int i = 0; i < labels.length; ++i) { - usedLabels.add(labels[i]); - } - ++insnCount; - } - - @Override - public void visitLookupSwitchInsn(final Label dflt, final int[] keys, - final Label[] labels) { - checkEndCode(); - checkStartCode(); - checkLabel(dflt, false, "default label"); - checkNonDebugLabel(dflt); - if (keys == null || labels == null || keys.length != labels.length) { - throw new IllegalArgumentException( - "There must be the same number of keys and labels"); - } - for (int i = 0; i < labels.length; ++i) { - checkLabel(labels[i], false, "label at index " + i); - checkNonDebugLabel(labels[i]); - } - super.visitLookupSwitchInsn(dflt, keys, labels); - usedLabels.add(dflt); - for (int i = 0; i < labels.length; ++i) { - usedLabels.add(labels[i]); - } - ++insnCount; - } - - @Override - public void visitMultiANewArrayInsn(final String desc, final int dims) { - checkStartCode(); - checkEndCode(); - checkDesc(desc, false); - if (desc.charAt(0) != '[') { - throw new IllegalArgumentException( - "Invalid descriptor (must be an array type descriptor): " - + desc); - } - if (dims < 1) { - throw new IllegalArgumentException( - "Invalid dimensions (must be greater than 0): " + dims); - } - if (dims > desc.lastIndexOf('[') + 1) { - throw new IllegalArgumentException( - "Invalid dimensions (must not be greater than dims(desc)): " - + dims); - } - super.visitMultiANewArrayInsn(desc, dims); - ++insnCount; - } - - @Override - public AnnotationVisitor visitInsnAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - checkStartCode(); - checkEndCode(); - int sort = typeRef >>> 24; - if (sort != TypeReference.INSTANCEOF && sort != TypeReference.NEW - && sort != TypeReference.CONSTRUCTOR_REFERENCE - && sort != TypeReference.METHOD_REFERENCE - && sort != TypeReference.CAST - && sort != TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - && sort != TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT - && sort != TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - && sort != TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT) { - throw new IllegalArgumentException("Invalid type reference sort 0x" - + Integer.toHexString(sort)); - } - CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath); - CheckMethodAdapter.checkDesc(desc, false); - return new CheckAnnotationAdapter(super.visitInsnAnnotation(typeRef, - typePath, desc, visible)); - } - - @Override - public void visitTryCatchBlock(final Label start, final Label end, - final Label handler, final String type) { - checkStartCode(); - checkEndCode(); - checkLabel(start, false, "start label"); - checkLabel(end, false, "end label"); - checkLabel(handler, false, "handler label"); - checkNonDebugLabel(start); - checkNonDebugLabel(end); - checkNonDebugLabel(handler); - if (labels.get(start) != null || labels.get(end) != null - || labels.get(handler) != null) { - throw new IllegalStateException( - "Try catch blocks must be visited before their labels"); - } - if (type != null) { - checkInternalName(type, "type"); - } - super.visitTryCatchBlock(start, end, handler, type); - handlers.add(start); - handlers.add(end); - } - - @Override - public AnnotationVisitor visitTryCatchAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - checkStartCode(); - checkEndCode(); - int sort = typeRef >>> 24; - if (sort != TypeReference.EXCEPTION_PARAMETER) { - throw new IllegalArgumentException("Invalid type reference sort 0x" - + Integer.toHexString(sort)); - } - CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath); - CheckMethodAdapter.checkDesc(desc, false); - return new CheckAnnotationAdapter(super.visitTryCatchAnnotation( - typeRef, typePath, desc, visible)); - } - - @Override - public void visitLocalVariable(final String name, final String desc, - final String signature, final Label start, final Label end, - final int index) { - checkStartCode(); - checkEndCode(); - checkUnqualifiedName(version, name, "name"); - checkDesc(desc, false); - checkLabel(start, true, "start label"); - checkLabel(end, true, "end label"); - checkUnsignedShort(index, "Invalid variable index"); - int s = labels.get(start).intValue(); - int e = labels.get(end).intValue(); - if (e < s) { - throw new IllegalArgumentException( - "Invalid start and end labels (end must be greater than start)"); - } - super.visitLocalVariable(name, desc, signature, start, end, index); - } - - @Override - public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, - TypePath typePath, Label[] start, Label[] end, int[] index, - String desc, boolean visible) { - checkStartCode(); - checkEndCode(); - int sort = typeRef >>> 24; - if (sort != TypeReference.LOCAL_VARIABLE - && sort != TypeReference.RESOURCE_VARIABLE) { - throw new IllegalArgumentException("Invalid type reference sort 0x" - + Integer.toHexString(sort)); - } - CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath); - checkDesc(desc, false); - if (start == null || end == null || index == null - || end.length != start.length || index.length != start.length) { - throw new IllegalArgumentException( - "Invalid start, end and index arrays (must be non null and of identical length"); - } - for (int i = 0; i < start.length; ++i) { - checkLabel(start[i], true, "start label"); - checkLabel(end[i], true, "end label"); - checkUnsignedShort(index[i], "Invalid variable index"); - int s = labels.get(start[i]).intValue(); - int e = labels.get(end[i]).intValue(); - if (e < s) { - throw new IllegalArgumentException( - "Invalid start and end labels (end must be greater than start)"); - } - } - return super.visitLocalVariableAnnotation(typeRef, typePath, start, - end, index, desc, visible); - } - - @Override - public void visitLineNumber(final int line, final Label start) { - checkStartCode(); - checkEndCode(); - checkUnsignedShort(line, "Invalid line number"); - checkLabel(start, true, "start label"); - super.visitLineNumber(line, start); - } - - @Override - public void visitMaxs(final int maxStack, final int maxLocals) { - checkStartCode(); - checkEndCode(); - endCode = true; - for (Label l : usedLabels) { - if (labels.get(l) == null) { - throw new IllegalStateException("Undefined label used"); - } - } - for (int i = 0; i < handlers.size();) { - Integer start = labels.get(handlers.get(i++)); - Integer end = labels.get(handlers.get(i++)); - if (start == null || end == null) { - throw new IllegalStateException( - "Undefined try catch block labels"); - } - if (end.intValue() <= start.intValue()) { - throw new IllegalStateException( - "Emty try catch block handler range"); - } - } - checkUnsignedShort(maxStack, "Invalid max stack"); - checkUnsignedShort(maxLocals, "Invalid max locals"); - super.visitMaxs(maxStack, maxLocals); - } - - @Override - public void visitEnd() { - checkEndMethod(); - endMethod = true; - super.visitEnd(); - } - - // ------------------------------------------------------------------------- - - /** - * Checks that the visitCode method has been called. - */ - void checkStartCode() { - if (!startCode) { - throw new IllegalStateException( - "Cannot visit instructions before visitCode has been called."); - } - } - - /** - * Checks that the visitMaxs method has not been called. - */ - void checkEndCode() { - if (endCode) { - throw new IllegalStateException( - "Cannot visit instructions after visitMaxs has been called."); - } - } - - /** - * Checks that the visitEnd method has not been called. - */ - void checkEndMethod() { - if (endMethod) { - throw new IllegalStateException( - "Cannot visit elements after visitEnd has been called."); - } - } - - /** - * Checks a stack frame value. - * - * @param value - * the value to be checked. - */ - void checkFrameValue(final Object value) { - if (value == Opcodes.TOP || value == Opcodes.INTEGER - || value == Opcodes.FLOAT || value == Opcodes.LONG - || value == Opcodes.DOUBLE || value == Opcodes.NULL - || value == Opcodes.UNINITIALIZED_THIS) { - return; - } - if (value instanceof String) { - checkInternalName((String) value, "Invalid stack frame value"); - return; - } - if (!(value instanceof Label)) { - throw new IllegalArgumentException("Invalid stack frame value: " - + value); - } else { - usedLabels.add((Label) value); - } - } - - /** - * Checks that the type of the given opcode is equal to the given type. - * - * @param opcode - * the opcode to be checked. - * @param type - * the expected opcode type. - */ - static void checkOpcode(final int opcode, final int type) { - if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) { - throw new IllegalArgumentException("Invalid opcode: " + opcode); - } - } - - /** - * Checks that the given value is a signed byte. - * - * @param value - * the value to be checked. - * @param msg - * an message to be used in case of error. - */ - static void checkSignedByte(final int value, final String msg) { - if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { - throw new IllegalArgumentException(msg - + " (must be a signed byte): " + value); - } - } - - /** - * Checks that the given value is a signed short. - * - * @param value - * the value to be checked. - * @param msg - * an message to be used in case of error. - */ - static void checkSignedShort(final int value, final String msg) { - if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { - throw new IllegalArgumentException(msg - + " (must be a signed short): " + value); - } - } - - /** - * Checks that the given value is an unsigned short. - * - * @param value - * the value to be checked. - * @param msg - * an message to be used in case of error. - */ - static void checkUnsignedShort(final int value, final String msg) { - if (value < 0 || value > 65535) { - throw new IllegalArgumentException(msg - + " (must be an unsigned short): " + value); - } - } - - /** - * Checks that the given value is an {@link Integer}, a{@link Float}, a - * {@link Long}, a {@link Double} or a {@link String}. - * - * @param cst - * the value to be checked. - */ - static void checkConstant(final Object cst) { - if (!(cst instanceof Integer) && !(cst instanceof Float) - && !(cst instanceof Long) && !(cst instanceof Double) - && !(cst instanceof String)) { - throw new IllegalArgumentException("Invalid constant: " + cst); - } - } - - void checkLDCConstant(final Object cst) { - if (cst instanceof Type) { - int s = ((Type) cst).getSort(); - if (s != Type.OBJECT && s != Type.ARRAY && s != Type.METHOD) { - throw new IllegalArgumentException("Illegal LDC constant value"); - } - if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) { - throw new IllegalArgumentException( - "ldc of a constant class requires at least version 1.5"); - } - if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) { - throw new IllegalArgumentException( - "ldc of a method type requires at least version 1.7"); - } - } else if (cst instanceof Handle) { - if ((version & 0xFFFF) < Opcodes.V1_7) { - throw new IllegalArgumentException( - "ldc of a handle requires at least version 1.7"); - } - int tag = ((Handle) cst).getTag(); - if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) { - throw new IllegalArgumentException("invalid handle tag " + tag); - } - } else { - checkConstant(cst); - } - } - - /** - * Checks that the given string is a valid unqualified name. - * - * @param version - * the class version. - * @param name - * the string to be checked. - * @param msg - * a message to be used in case of error. - */ - static void checkUnqualifiedName(int version, final String name, - final String msg) { - if ((version & 0xFFFF) < Opcodes.V1_5) { - checkIdentifier(name, msg); - } else { - for (int i = 0; i < name.length(); ++i) { - if (".;[/".indexOf(name.charAt(i)) != -1) { - throw new IllegalArgumentException("Invalid " + msg - + " (must be a valid unqualified name): " + name); - } - } - } - } - - /** - * Checks that the given string is a valid Java identifier. - * - * @param name - * the string to be checked. - * @param msg - * a message to be used in case of error. - */ - static void checkIdentifier(final String name, final String msg) { - checkIdentifier(name, 0, -1, msg); - } - - /** - * Checks that the given substring is a valid Java identifier. - * - * @param name - * the string to be checked. - * @param start - * index of the first character of the identifier (inclusive). - * @param end - * index of the last character of the identifier (exclusive). -1 - * is equivalent to <tt>name.length()</tt> if name is not - * <tt>null</tt>. - * @param msg - * a message to be used in case of error. - */ - static void checkIdentifier(final String name, final int start, - final int end, final String msg) { - if (name == null || (end == -1 ? name.length() <= start : end <= start)) { - throw new IllegalArgumentException("Invalid " + msg - + " (must not be null or empty)"); - } - if (!Character.isJavaIdentifierStart(name.charAt(start))) { - throw new IllegalArgumentException("Invalid " + msg - + " (must be a valid Java identifier): " + name); - } - int max = end == -1 ? name.length() : end; - for (int i = start + 1; i < max; ++i) { - if (!Character.isJavaIdentifierPart(name.charAt(i))) { - throw new IllegalArgumentException("Invalid " + msg - + " (must be a valid Java identifier): " + name); - } - } - } - - /** - * Checks that the given string is a valid Java identifier. - * - * @param version - * the class version. - * @param name - * the string to be checked. - * @param msg - * a message to be used in case of error. - */ - static void checkMethodIdentifier(int version, final String name, - final String msg) { - if (name == null || name.length() == 0) { - throw new IllegalArgumentException("Invalid " + msg - + " (must not be null or empty)"); - } - if ((version & 0xFFFF) >= Opcodes.V1_5) { - for (int i = 0; i < name.length(); ++i) { - if (".;[/<>".indexOf(name.charAt(i)) != -1) { - throw new IllegalArgumentException("Invalid " + msg - + " (must be a valid unqualified name): " + name); - } - } - return; - } - if (!Character.isJavaIdentifierStart(name.charAt(0))) { - throw new IllegalArgumentException( - "Invalid " - + msg - + " (must be a '<init>', '<clinit>' or a valid Java identifier): " - + name); - } - for (int i = 1; i < name.length(); ++i) { - if (!Character.isJavaIdentifierPart(name.charAt(i))) { - throw new IllegalArgumentException( - "Invalid " - + msg - + " (must be '<init>' or '<clinit>' or a valid Java identifier): " - + name); - } - } - } - - /** - * Checks that the given string is a valid internal class name. - * - * @param name - * the string to be checked. - * @param msg - * a message to be used in case of error. - */ - static void checkInternalName(final String name, final String msg) { - if (name == null || name.length() == 0) { - throw new IllegalArgumentException("Invalid " + msg - + " (must not be null or empty)"); - } - if (name.charAt(0) == '[') { - checkDesc(name, false); - } else { - checkInternalName(name, 0, -1, msg); - } - } - - /** - * Checks that the given substring is a valid internal class name. - * - * @param name - * the string to be checked. - * @param start - * index of the first character of the identifier (inclusive). - * @param end - * index of the last character of the identifier (exclusive). -1 - * is equivalent to <tt>name.length()</tt> if name is not - * <tt>null</tt>. - * @param msg - * a message to be used in case of error. - */ - static void checkInternalName(final String name, final int start, - final int end, final String msg) { - int max = end == -1 ? name.length() : end; - try { - int begin = start; - int slash; - do { - slash = name.indexOf('/', begin + 1); - if (slash == -1 || slash > max) { - slash = max; - } - checkIdentifier(name, begin, slash, null); - begin = slash + 1; - } while (slash != max); - } catch (IllegalArgumentException unused) { - throw new IllegalArgumentException( - "Invalid " - + msg - + " (must be a fully qualified class name in internal form): " - + name); - } - } - - /** - * Checks that the given string is a valid type descriptor. - * - * @param desc - * the string to be checked. - * @param canBeVoid - * <tt>true</tt> if <tt>V</tt> can be considered valid. - */ - static void checkDesc(final String desc, final boolean canBeVoid) { - int end = checkDesc(desc, 0, canBeVoid); - if (end != desc.length()) { - throw new IllegalArgumentException("Invalid descriptor: " + desc); - } - } - - /** - * Checks that a the given substring is a valid type descriptor. - * - * @param desc - * the string to be checked. - * @param start - * index of the first character of the identifier (inclusive). - * @param canBeVoid - * <tt>true</tt> if <tt>V</tt> can be considered valid. - * @return the index of the last character of the type decriptor, plus one. - */ - static int checkDesc(final String desc, final int start, - final boolean canBeVoid) { - if (desc == null || start >= desc.length()) { - throw new IllegalArgumentException( - "Invalid type descriptor (must not be null or empty)"); - } - int index; - switch (desc.charAt(start)) { - case 'V': - if (canBeVoid) { - return start + 1; - } else { - throw new IllegalArgumentException("Invalid descriptor: " - + desc); - } - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - case 'F': - case 'J': - case 'D': - return start + 1; - case '[': - index = start + 1; - while (index < desc.length() && desc.charAt(index) == '[') { - ++index; - } - if (index < desc.length()) { - return checkDesc(desc, index, false); - } else { - throw new IllegalArgumentException("Invalid descriptor: " - + desc); - } - case 'L': - index = desc.indexOf(';', start); - if (index == -1 || index - start < 2) { - throw new IllegalArgumentException("Invalid descriptor: " - + desc); - } - try { - checkInternalName(desc, start + 1, index, null); - } catch (IllegalArgumentException unused) { - throw new IllegalArgumentException("Invalid descriptor: " - + desc); - } - return index + 1; - default: - throw new IllegalArgumentException("Invalid descriptor: " + desc); - } - } - - /** - * Checks that the given string is a valid method descriptor. - * - * @param desc - * the string to be checked. - */ - static void checkMethodDesc(final String desc) { - if (desc == null || desc.length() == 0) { - throw new IllegalArgumentException( - "Invalid method descriptor (must not be null or empty)"); - } - if (desc.charAt(0) != '(' || desc.length() < 3) { - throw new IllegalArgumentException("Invalid descriptor: " + desc); - } - int start = 1; - if (desc.charAt(start) != ')') { - do { - if (desc.charAt(start) == 'V') { - throw new IllegalArgumentException("Invalid descriptor: " - + desc); - } - start = checkDesc(desc, start, false); - } while (start < desc.length() && desc.charAt(start) != ')'); - } - start = checkDesc(desc, start + 1, true); - if (start != desc.length()) { - throw new IllegalArgumentException("Invalid descriptor: " + desc); - } - } - - /** - * Checks that the given label is not null. This method can also check that - * the label has been visited. - * - * @param label - * the label to be checked. - * @param checkVisited - * <tt>true</tt> to check that the label has been visited. - * @param msg - * a message to be used in case of error. - */ - void checkLabel(final Label label, final boolean checkVisited, - final String msg) { - if (label == null) { - throw new IllegalArgumentException("Invalid " + msg - + " (must not be null)"); - } - if (checkVisited && labels.get(label) == null) { - throw new IllegalArgumentException("Invalid " + msg - + " (must be visited first)"); - } - } - - /** - * Checks that the given label is not a label used only for debug purposes. - * - * @param label - * the label to be checked. - */ - private static void checkNonDebugLabel(final Label label) { - Field f = getLabelStatusField(); - int status = 0; - try { - status = f == null ? 0 : ((Integer) f.get(label)).intValue(); - } catch (IllegalAccessException e) { - throw new Error("Internal error"); - } - if ((status & 0x01) != 0) { - throw new IllegalArgumentException( - "Labels used for debug info cannot be reused for control flow"); - } - } - - /** - * Returns the Field object corresponding to the Label.status field. - * - * @return the Field object corresponding to the Label.status field. - */ - private static Field getLabelStatusField() { - if (labelStatusField == null) { - labelStatusField = getLabelField("a"); - if (labelStatusField == null) { - labelStatusField = getLabelField("status"); - } - } - return labelStatusField; - } - - /** - * Returns the field of the Label class whose name is given. - * - * @param name - * a field name. - * @return the field of the Label class whose name is given, or null. - */ - private static Field getLabelField(final String name) { - try { - Field f = Label.class.getDeclaredField(name); - f.setAccessible(true); - return f; - } catch (NoSuchFieldException e) { - return null; - } - } -} diff --git a/src/asm/scala/tools/asm/util/CheckSignatureAdapter.java b/src/asm/scala/tools/asm/util/CheckSignatureAdapter.java deleted file mode 100644 index 54c9033c90..0000000000 --- a/src/asm/scala/tools/asm/util/CheckSignatureAdapter.java +++ /dev/null @@ -1,330 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import scala.tools.asm.Opcodes; -import scala.tools.asm.signature.SignatureVisitor; - -/** - * A {@link SignatureVisitor} that checks that its methods are properly used. - * - * @author Eric Bruneton - */ -public class CheckSignatureAdapter extends SignatureVisitor { - - /** - * Type to be used to check class signatures. See - * {@link #CheckSignatureAdapter(int, SignatureVisitor) - * CheckSignatureAdapter}. - */ - public static final int CLASS_SIGNATURE = 0; - - /** - * Type to be used to check method signatures. See - * {@link #CheckSignatureAdapter(int, SignatureVisitor) - * CheckSignatureAdapter}. - */ - public static final int METHOD_SIGNATURE = 1; - - /** - * Type to be used to check type signatures.See - * {@link #CheckSignatureAdapter(int, SignatureVisitor) - * CheckSignatureAdapter}. - */ - public static final int TYPE_SIGNATURE = 2; - - private static final int EMPTY = 1; - - private static final int FORMAL = 2; - - private static final int BOUND = 4; - - private static final int SUPER = 8; - - private static final int PARAM = 16; - - private static final int RETURN = 32; - - private static final int SIMPLE_TYPE = 64; - - private static final int CLASS_TYPE = 128; - - private static final int END = 256; - - /** - * Type of the signature to be checked. - */ - private final int type; - - /** - * State of the automaton used to check the order of method calls. - */ - private int state; - - /** - * <tt>true</tt> if the checked type signature can be 'V'. - */ - private boolean canBeVoid; - - /** - * The visitor to which this adapter must delegate calls. May be - * <tt>null</tt>. - */ - private final SignatureVisitor sv; - - /** - * Creates a new {@link CheckSignatureAdapter} object. <i>Subclasses must - * not use this constructor</i>. Instead, they must use the - * {@link #CheckSignatureAdapter(int, int, SignatureVisitor)} version. - * - * @param type - * the type of signature to be checked. See - * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and - * {@link #TYPE_SIGNATURE}. - * @param sv - * the visitor to which this adapter must delegate calls. May be - * <tt>null</tt>. - */ - public CheckSignatureAdapter(final int type, final SignatureVisitor sv) { - this(Opcodes.ASM5, type, sv); - } - - /** - * Creates a new {@link CheckSignatureAdapter} object. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - * @param type - * the type of signature to be checked. See - * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and - * {@link #TYPE_SIGNATURE}. - * @param sv - * the visitor to which this adapter must delegate calls. May be - * <tt>null</tt>. - */ - protected CheckSignatureAdapter(final int api, final int type, - final SignatureVisitor sv) { - super(api); - this.type = type; - this.state = EMPTY; - this.sv = sv; - } - - // class and method signatures - - @Override - public void visitFormalTypeParameter(final String name) { - if (type == TYPE_SIGNATURE - || (state != EMPTY && state != FORMAL && state != BOUND)) { - throw new IllegalStateException(); - } - CheckMethodAdapter.checkIdentifier(name, "formal type parameter"); - state = FORMAL; - if (sv != null) { - sv.visitFormalTypeParameter(name); - } - } - - @Override - public SignatureVisitor visitClassBound() { - if (state != FORMAL) { - throw new IllegalStateException(); - } - state = BOUND; - SignatureVisitor v = sv == null ? null : sv.visitClassBound(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); - } - - @Override - public SignatureVisitor visitInterfaceBound() { - if (state != FORMAL && state != BOUND) { - throw new IllegalArgumentException(); - } - SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); - } - - // class signatures - - @Override - public SignatureVisitor visitSuperclass() { - if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) { - throw new IllegalArgumentException(); - } - state = SUPER; - SignatureVisitor v = sv == null ? null : sv.visitSuperclass(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); - } - - @Override - public SignatureVisitor visitInterface() { - if (state != SUPER) { - throw new IllegalStateException(); - } - SignatureVisitor v = sv == null ? null : sv.visitInterface(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); - } - - // method signatures - - @Override - public SignatureVisitor visitParameterType() { - if (type != METHOD_SIGNATURE - || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) { - throw new IllegalArgumentException(); - } - state = PARAM; - SignatureVisitor v = sv == null ? null : sv.visitParameterType(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); - } - - @Override - public SignatureVisitor visitReturnType() { - if (type != METHOD_SIGNATURE - || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) { - throw new IllegalArgumentException(); - } - state = RETURN; - SignatureVisitor v = sv == null ? null : sv.visitReturnType(); - CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v); - cv.canBeVoid = true; - return cv; - } - - @Override - public SignatureVisitor visitExceptionType() { - if (state != RETURN) { - throw new IllegalStateException(); - } - SignatureVisitor v = sv == null ? null : sv.visitExceptionType(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); - } - - // type signatures - - @Override - public void visitBaseType(final char descriptor) { - if (type != TYPE_SIGNATURE || state != EMPTY) { - throw new IllegalStateException(); - } - if (descriptor == 'V') { - if (!canBeVoid) { - throw new IllegalArgumentException(); - } - } else { - if ("ZCBSIFJD".indexOf(descriptor) == -1) { - throw new IllegalArgumentException(); - } - } - state = SIMPLE_TYPE; - if (sv != null) { - sv.visitBaseType(descriptor); - } - } - - @Override - public void visitTypeVariable(final String name) { - if (type != TYPE_SIGNATURE || state != EMPTY) { - throw new IllegalStateException(); - } - CheckMethodAdapter.checkIdentifier(name, "type variable"); - state = SIMPLE_TYPE; - if (sv != null) { - sv.visitTypeVariable(name); - } - } - - @Override - public SignatureVisitor visitArrayType() { - if (type != TYPE_SIGNATURE || state != EMPTY) { - throw new IllegalStateException(); - } - state = SIMPLE_TYPE; - SignatureVisitor v = sv == null ? null : sv.visitArrayType(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); - } - - @Override - public void visitClassType(final String name) { - if (type != TYPE_SIGNATURE || state != EMPTY) { - throw new IllegalStateException(); - } - CheckMethodAdapter.checkInternalName(name, "class name"); - state = CLASS_TYPE; - if (sv != null) { - sv.visitClassType(name); - } - } - - @Override - public void visitInnerClassType(final String name) { - if (state != CLASS_TYPE) { - throw new IllegalStateException(); - } - CheckMethodAdapter.checkIdentifier(name, "inner class name"); - if (sv != null) { - sv.visitInnerClassType(name); - } - } - - @Override - public void visitTypeArgument() { - if (state != CLASS_TYPE) { - throw new IllegalStateException(); - } - if (sv != null) { - sv.visitTypeArgument(); - } - } - - @Override - public SignatureVisitor visitTypeArgument(final char wildcard) { - if (state != CLASS_TYPE) { - throw new IllegalStateException(); - } - if ("+-=".indexOf(wildcard) == -1) { - throw new IllegalArgumentException(); - } - SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); - } - - @Override - public void visitEnd() { - if (state != CLASS_TYPE) { - throw new IllegalStateException(); - } - state = END; - if (sv != null) { - sv.visitEnd(); - } - } -} diff --git a/src/asm/scala/tools/asm/util/Printer.java b/src/asm/scala/tools/asm/util/Printer.java deleted file mode 100644 index 773f129ad9..0000000000 --- a/src/asm/scala/tools/asm/util/Printer.java +++ /dev/null @@ -1,589 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -import scala.tools.asm.Attribute; -import scala.tools.asm.Handle; -import scala.tools.asm.Label; -import scala.tools.asm.Opcodes; -import scala.tools.asm.TypePath; - -/** - * An abstract converter from visit events to text. - * - * @author Eric Bruneton - */ -public abstract class Printer { - - /** - * The names of the Java Virtual Machine opcodes. - */ - public static final String[] OPCODES; - - /** - * The names of the for <code>operand</code> parameter values of the - * {@link scala.tools.asm.MethodVisitor#visitIntInsn} method when - * <code>opcode</code> is <code>NEWARRAY</code>. - */ - public static final String[] TYPES; - - /** - * The names of the <code>tag</code> field values for - * {@link scala.tools.asm.Handle}. - */ - public static final String[] HANDLE_TAG; - - static { - String s = "NOP,ACONST_NULL,ICONST_M1,ICONST_0,ICONST_1,ICONST_2," - + "ICONST_3,ICONST_4,ICONST_5,LCONST_0,LCONST_1,FCONST_0," - + "FCONST_1,FCONST_2,DCONST_0,DCONST_1,BIPUSH,SIPUSH,LDC,,," - + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD," - + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE," - + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,IASTORE," - + "LASTORE,FASTORE,DASTORE,AASTORE,BASTORE,CASTORE,SASTORE,POP," - + "POP2,DUP,DUP_X1,DUP_X2,DUP2,DUP2_X1,DUP2_X2,SWAP,IADD,LADD," - + "FADD,DADD,ISUB,LSUB,FSUB,DSUB,IMUL,LMUL,FMUL,DMUL,IDIV,LDIV," - + "FDIV,DDIV,IREM,LREM,FREM,DREM,INEG,LNEG,FNEG,DNEG,ISHL,LSHL," - + "ISHR,LSHR,IUSHR,LUSHR,IAND,LAND,IOR,LOR,IXOR,LXOR,IINC,I2L," - + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP," - + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE," - + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE," - + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH," - + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC," - + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL," - + "INVOKESTATIC,INVOKEINTERFACE,INVOKEDYNAMIC,NEW,NEWARRAY," - + "ANEWARRAY,ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF," - + "MONITORENTER,MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,"; - OPCODES = new String[200]; - int i = 0; - int j = 0; - int l; - while ((l = s.indexOf(',', j)) > 0) { - OPCODES[i++] = j + 1 == l ? null : s.substring(j, l); - j = l + 1; - } - - s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,"; - TYPES = new String[12]; - j = 0; - i = 4; - while ((l = s.indexOf(',', j)) > 0) { - TYPES[i++] = s.substring(j, l); - j = l + 1; - } - - s = "H_GETFIELD,H_GETSTATIC,H_PUTFIELD,H_PUTSTATIC," - + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL," - + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,"; - HANDLE_TAG = new String[10]; - j = 0; - i = 1; - while ((l = s.indexOf(',', j)) > 0) { - HANDLE_TAG[i++] = s.substring(j, l); - j = l + 1; - } - } - - /** - * The ASM API version implemented by this class. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected final int api; - - /** - * A buffer that can be used to create strings. - */ - protected final StringBuffer buf; - - /** - * The text to be printed. Since the code of methods is not necessarily - * visited in sequential order, one method after the other, but can be - * interlaced (some instructions from method one, then some instructions - * from method two, then some instructions from method one again...), it is - * not possible to print the visited instructions directly to a sequential - * stream. A class is therefore printed in a two steps process: a string - * tree is constructed during the visit, and printed to a sequential stream - * at the end of the visit. This string tree is stored in this field, as a - * string list that can contain other string lists, which can themselves - * contain other string lists, and so on. - */ - public final List<Object> text; - - /** - * Constructs a new {@link Printer}. - */ - protected Printer(final int api) { - this.api = api; - this.buf = new StringBuffer(); - this.text = new ArrayList<Object>(); - } - - /** - * Class header. See {@link scala.tools.asm.ClassVisitor#visit}. - */ - public abstract void visit(final int version, final int access, - final String name, final String signature, final String superName, - final String[] interfaces); - - /** - * Class source. See {@link scala.tools.asm.ClassVisitor#visitSource}. - */ - public abstract void visitSource(final String file, final String debug); - - /** - * Class outer class. See - * {@link scala.tools.asm.ClassVisitor#visitOuterClass}. - */ - public abstract void visitOuterClass(final String owner, final String name, - final String desc); - - /** - * Class annotation. See - * {@link scala.tools.asm.ClassVisitor#visitAnnotation}. - */ - public abstract Printer visitClassAnnotation(final String desc, - final boolean visible); - - /** - * Class type annotation. See - * {@link scala.tools.asm.ClassVisitor#visitTypeAnnotation}. - */ - public Printer visitClassTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - throw new RuntimeException("Must be overridden"); - } - - /** - * Class attribute. See - * {@link scala.tools.asm.ClassVisitor#visitAttribute}. - */ - public abstract void visitClassAttribute(final Attribute attr); - - /** - * Class inner name. See - * {@link scala.tools.asm.ClassVisitor#visitInnerClass}. - */ - public abstract void visitInnerClass(final String name, - final String outerName, final String innerName, final int access); - - /** - * Class field. See {@link scala.tools.asm.ClassVisitor#visitField}. - */ - public abstract Printer visitField(final int access, final String name, - final String desc, final String signature, final Object value); - - /** - * Class method. See {@link scala.tools.asm.ClassVisitor#visitMethod}. - */ - public abstract Printer visitMethod(final int access, final String name, - final String desc, final String signature, final String[] exceptions); - - /** - * Class end. See {@link scala.tools.asm.ClassVisitor#visitEnd}. - */ - public abstract void visitClassEnd(); - - // ------------------------------------------------------------------------ - // Annotations - // ------------------------------------------------------------------------ - - /** - * Annotation value. See {@link scala.tools.asm.AnnotationVisitor#visit}. - */ - public abstract void visit(final String name, final Object value); - - /** - * Annotation enum value. See - * {@link scala.tools.asm.AnnotationVisitor#visitEnum}. - */ - public abstract void visitEnum(final String name, final String desc, - final String value); - - /** - * Nested annotation value. See - * {@link scala.tools.asm.AnnotationVisitor#visitAnnotation}. - */ - public abstract Printer visitAnnotation(final String name, final String desc); - - /** - * Annotation array value. See - * {@link scala.tools.asm.AnnotationVisitor#visitArray}. - */ - public abstract Printer visitArray(final String name); - - /** - * Annotation end. See {@link scala.tools.asm.AnnotationVisitor#visitEnd}. - */ - public abstract void visitAnnotationEnd(); - - // ------------------------------------------------------------------------ - // Fields - // ------------------------------------------------------------------------ - - /** - * Field annotation. See - * {@link scala.tools.asm.FieldVisitor#visitAnnotation}. - */ - public abstract Printer visitFieldAnnotation(final String desc, - final boolean visible); - - /** - * Field type annotation. See - * {@link scala.tools.asm.FieldVisitor#visitTypeAnnotation}. - */ - public Printer visitFieldTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - throw new RuntimeException("Must be overridden"); - } - - /** - * Field attribute. See - * {@link scala.tools.asm.FieldVisitor#visitAttribute}. - */ - public abstract void visitFieldAttribute(final Attribute attr); - - /** - * Field end. See {@link scala.tools.asm.FieldVisitor#visitEnd}. - */ - public abstract void visitFieldEnd(); - - // ------------------------------------------------------------------------ - // Methods - // ------------------------------------------------------------------------ - - /** - * Method parameter. See - * {@link scala.tools.asm.MethodVisitor#visitParameter(String, int)}. - */ - public void visitParameter(String name, int access) { - throw new RuntimeException("Must be overridden"); - } - - /** - * Method default annotation. See - * {@link scala.tools.asm.MethodVisitor#visitAnnotationDefault}. - */ - public abstract Printer visitAnnotationDefault(); - - /** - * Method annotation. See - * {@link scala.tools.asm.MethodVisitor#visitAnnotation}. - */ - public abstract Printer visitMethodAnnotation(final String desc, - final boolean visible); - - /** - * Method type annotation. See - * {@link scala.tools.asm.MethodVisitor#visitTypeAnnotation}. - */ - public Printer visitMethodTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - throw new RuntimeException("Must be overridden"); - } - - /** - * Method parameter annotation. See - * {@link scala.tools.asm.MethodVisitor#visitParameterAnnotation}. - */ - public abstract Printer visitParameterAnnotation(final int parameter, - final String desc, final boolean visible); - - /** - * Method attribute. See - * {@link scala.tools.asm.MethodVisitor#visitAttribute}. - */ - public abstract void visitMethodAttribute(final Attribute attr); - - /** - * Method start. See {@link scala.tools.asm.MethodVisitor#visitCode}. - */ - public abstract void visitCode(); - - /** - * Method stack frame. See - * {@link scala.tools.asm.MethodVisitor#visitFrame}. - */ - public abstract void visitFrame(final int type, final int nLocal, - final Object[] local, final int nStack, final Object[] stack); - - /** - * Method instruction. See {@link scala.tools.asm.MethodVisitor#visitInsn} - * . - */ - public abstract void visitInsn(final int opcode); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitIntInsn}. - */ - public abstract void visitIntInsn(final int opcode, final int operand); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitVarInsn}. - */ - public abstract void visitVarInsn(final int opcode, final int var); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitTypeInsn}. - */ - public abstract void visitTypeInsn(final int opcode, final String type); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitFieldInsn}. - */ - public abstract void visitFieldInsn(final int opcode, final String owner, - final String name, final String desc); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitMethodInsn}. - */ - @Deprecated - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc) { - if (api >= Opcodes.ASM5) { - boolean itf = opcode == Opcodes.INVOKEINTERFACE; - visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - throw new RuntimeException("Must be overridden"); - } - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitMethodInsn}. - */ - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc, final boolean itf) { - if (api < Opcodes.ASM5) { - if (itf != (opcode == Opcodes.INVOKEINTERFACE)) { - throw new IllegalArgumentException( - "INVOKESPECIAL/STATIC on interfaces require ASM 5"); - } - visitMethodInsn(opcode, owner, name, desc); - return; - } - throw new RuntimeException("Must be overridden"); - } - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitInvokeDynamicInsn}. - */ - public abstract void visitInvokeDynamicInsn(String name, String desc, - Handle bsm, Object... bsmArgs); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitJumpInsn}. - */ - public abstract void visitJumpInsn(final int opcode, final Label label); - - /** - * Method label. See {@link scala.tools.asm.MethodVisitor#visitLabel}. - */ - public abstract void visitLabel(final Label label); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitLdcInsn}. - */ - public abstract void visitLdcInsn(final Object cst); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitIincInsn}. - */ - public abstract void visitIincInsn(final int var, final int increment); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitTableSwitchInsn}. - */ - public abstract void visitTableSwitchInsn(final int min, final int max, - final Label dflt, final Label... labels); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitLookupSwitchInsn}. - */ - public abstract void visitLookupSwitchInsn(final Label dflt, - final int[] keys, final Label[] labels); - - /** - * Method instruction. See - * {@link scala.tools.asm.MethodVisitor#visitMultiANewArrayInsn}. - */ - public abstract void visitMultiANewArrayInsn(final String desc, - final int dims); - - /** - * Instruction type annotation. See - * {@link scala.tools.asm.MethodVisitor#visitInsnAnnotation}. - */ - public Printer visitInsnAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - throw new RuntimeException("Must be overridden"); - } - - /** - * Method exception handler. See - * {@link scala.tools.asm.MethodVisitor#visitTryCatchBlock}. - */ - public abstract void visitTryCatchBlock(final Label start, final Label end, - final Label handler, final String type); - - /** - * Try catch block type annotation. See - * {@link scala.tools.asm.MethodVisitor#visitTryCatchAnnotation}. - */ - public Printer visitTryCatchAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - throw new RuntimeException("Must be overridden"); - } - - /** - * Method debug info. See - * {@link scala.tools.asm.MethodVisitor#visitLocalVariable}. - */ - public abstract void visitLocalVariable(final String name, - final String desc, final String signature, final Label start, - final Label end, final int index); - - /** - * Local variable type annotation. See - * {@link scala.tools.asm.MethodVisitor#visitTryCatchAnnotation}. - */ - public Printer visitLocalVariableAnnotation(final int typeRef, - final TypePath typePath, final Label[] start, final Label[] end, - final int[] index, final String desc, final boolean visible) { - throw new RuntimeException("Must be overridden"); - } - - /** - * Method debug info. See - * {@link scala.tools.asm.MethodVisitor#visitLineNumber}. - */ - public abstract void visitLineNumber(final int line, final Label start); - - /** - * Method max stack and max locals. See - * {@link scala.tools.asm.MethodVisitor#visitMaxs}. - */ - public abstract void visitMaxs(final int maxStack, final int maxLocals); - - /** - * Method end. See {@link scala.tools.asm.MethodVisitor#visitEnd}. - */ - public abstract void visitMethodEnd(); - - /** - * Returns the text constructed by this visitor. - * - * @return the text constructed by this visitor. - */ - public List<Object> getText() { - return text; - } - - /** - * Prints the text constructed by this visitor. - * - * @param pw - * the print writer to be used. - */ - public void print(final PrintWriter pw) { - printList(pw, text); - } - - /** - * Appends a quoted string to a given buffer. - * - * @param buf - * the buffer where the string must be added. - * @param s - * the string to be added. - */ - public static void appendString(final StringBuffer buf, final String s) { - buf.append('\"'); - for (int i = 0; i < s.length(); ++i) { - char c = s.charAt(i); - if (c == '\n') { - buf.append("\\n"); - } else if (c == '\r') { - buf.append("\\r"); - } else if (c == '\\') { - buf.append("\\\\"); - } else if (c == '"') { - buf.append("\\\""); - } else if (c < 0x20 || c > 0x7f) { - buf.append("\\u"); - if (c < 0x10) { - buf.append("000"); - } else if (c < 0x100) { - buf.append("00"); - } else if (c < 0x1000) { - buf.append('0'); - } - buf.append(Integer.toString(c, 16)); - } else { - buf.append(c); - } - } - buf.append('\"'); - } - - /** - * Prints the given string tree. - * - * @param pw - * the writer to be used to print the tree. - * @param l - * a string tree, i.e., a string list that can contain other - * string lists, and so on recursively. - */ - static void printList(final PrintWriter pw, final List<?> l) { - for (int i = 0; i < l.size(); ++i) { - Object o = l.get(i); - if (o instanceof List) { - printList(pw, (List<?>) o); - } else { - pw.print(o.toString()); - } - } - } -} diff --git a/src/asm/scala/tools/asm/util/Textifiable.java b/src/asm/scala/tools/asm/util/Textifiable.java deleted file mode 100644 index 85e051e2f8..0000000000 --- a/src/asm/scala/tools/asm/util/Textifiable.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import java.util.Map; - -import scala.tools.asm.Label; - -/** - * An {@link scala.tools.asm.Attribute Attribute} that can print a readable - * representation of itself. - * - * Implementations should construct readable output from an attribute data - * structure. Such representation could be used in unit test assertions. - * - * @author Eugene Kuleshov - */ -public interface Textifiable { - - /** - * Build a human readable representation of this attribute. - * - * @param buf - * a buffer used for printing Java code. - * @param labelNames - * map of label instances to their names. - */ - void textify(StringBuffer buf, Map<Label, String> labelNames); -} diff --git a/src/asm/scala/tools/asm/util/Textifier.java b/src/asm/scala/tools/asm/util/Textifier.java deleted file mode 100644 index 373e46f5ed..0000000000 --- a/src/asm/scala/tools/asm/util/Textifier.java +++ /dev/null @@ -1,1459 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import java.io.FileInputStream; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.Map; - -import scala.tools.asm.Attribute; -import scala.tools.asm.ClassReader; -import scala.tools.asm.Handle; -import scala.tools.asm.Label; -import scala.tools.asm.Opcodes; -import scala.tools.asm.Type; -import scala.tools.asm.TypePath; -import scala.tools.asm.TypeReference; -import scala.tools.asm.signature.SignatureReader; - -/** - * A {@link Printer} that prints a disassembled view of the classes it visits. - * - * @author Eric Bruneton - */ -public class Textifier extends Printer { - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for internal - * type names in bytecode notation. - */ - public static final int INTERNAL_NAME = 0; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for field - * descriptors, formatted in bytecode notation - */ - public static final int FIELD_DESCRIPTOR = 1; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for field - * signatures, formatted in bytecode notation - */ - public static final int FIELD_SIGNATURE = 2; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for method - * descriptors, formatted in bytecode notation - */ - public static final int METHOD_DESCRIPTOR = 3; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for method - * signatures, formatted in bytecode notation - */ - public static final int METHOD_SIGNATURE = 4; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for class - * signatures, formatted in bytecode notation - */ - public static final int CLASS_SIGNATURE = 5; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for field or - * method return value signatures, formatted in default Java notation - * (non-bytecode) - */ - public static final int TYPE_DECLARATION = 6; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for class - * signatures, formatted in default Java notation (non-bytecode) - */ - public static final int CLASS_DECLARATION = 7; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for method - * parameter signatures, formatted in default Java notation (non-bytecode) - */ - public static final int PARAMETERS_DECLARATION = 8; - - /** - * Constant used in {@link #appendDescriptor appendDescriptor} for handle - * descriptors, formatted in bytecode notation - */ - public static final int HANDLE_DESCRIPTOR = 9; - - /** - * Tab for class members. - */ - protected String tab = " "; - - /** - * Tab for bytecode instructions. - */ - protected String tab2 = " "; - - /** - * Tab for table and lookup switch instructions. - */ - protected String tab3 = " "; - - /** - * Tab for labels. - */ - protected String ltab = " "; - - /** - * The label names. This map associate String values to Label keys. - */ - protected Map<Label, String> labelNames; - - /** - * Class access flags - */ - private int access; - - private int valueNumber = 0; - - /** - * Constructs a new {@link Textifier}. <i>Subclasses must not use this - * constructor</i>. Instead, they must use the {@link #Textifier(int)} - * version. - * - * @throws IllegalStateException - * If a subclass calls this constructor. - */ - public Textifier() { - this(Opcodes.ASM5); - if (getClass() != Textifier.class) { - throw new IllegalStateException(); - } - } - - /** - * Constructs a new {@link Textifier}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. - */ - protected Textifier(final int api) { - super(api); - } - - /** - * Prints a disassembled view of the given class to the standard output. - * <p> - * Usage: Textifier [-debug] <binary class name or class file name > - * - * @param args - * the command line arguments. - * - * @throws Exception - * if the class cannot be found, or if an IO exception occurs. - */ - public static void main(final String[] args) throws Exception { - int i = 0; - int flags = ClassReader.SKIP_DEBUG; - - boolean ok = true; - if (args.length < 1 || args.length > 2) { - ok = false; - } - if (ok && "-debug".equals(args[0])) { - i = 1; - flags = 0; - if (args.length != 2) { - ok = false; - } - } - if (!ok) { - System.err - .println("Prints a disassembled view of the given class."); - System.err.println("Usage: Textifier [-debug] " - + "<fully qualified class name or class file name>"); - return; - } - ClassReader cr; - if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1 - || args[i].indexOf('/') > -1) { - cr = new ClassReader(new FileInputStream(args[i])); - } else { - cr = new ClassReader(args[i]); - } - cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), flags); - } - - // ------------------------------------------------------------------------ - // Classes - // ------------------------------------------------------------------------ - - @Override - public void visit(final int version, final int access, final String name, - final String signature, final String superName, - final String[] interfaces) { - this.access = access; - int major = version & 0xFFFF; - int minor = version >>> 16; - buf.setLength(0); - buf.append("// class version ").append(major).append('.').append(minor) - .append(" (").append(version).append(")\n"); - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - buf.append("// DEPRECATED\n"); - } - buf.append("// access flags 0x") - .append(Integer.toHexString(access).toUpperCase()).append('\n'); - - appendDescriptor(CLASS_SIGNATURE, signature); - if (signature != null) { - TraceSignatureVisitor sv = new TraceSignatureVisitor(access); - SignatureReader r = new SignatureReader(signature); - r.accept(sv); - buf.append("// declaration: ").append(name) - .append(sv.getDeclaration()).append('\n'); - } - - appendAccess(access & ~Opcodes.ACC_SUPER); - if ((access & Opcodes.ACC_ANNOTATION) != 0) { - buf.append("@interface "); - } else if ((access & Opcodes.ACC_INTERFACE) != 0) { - buf.append("interface "); - } else if ((access & Opcodes.ACC_ENUM) == 0) { - buf.append("class "); - } - appendDescriptor(INTERNAL_NAME, name); - - if (superName != null && !"java/lang/Object".equals(superName)) { - buf.append(" extends "); - appendDescriptor(INTERNAL_NAME, superName); - buf.append(' '); - } - if (interfaces != null && interfaces.length > 0) { - buf.append(" implements "); - for (int i = 0; i < interfaces.length; ++i) { - appendDescriptor(INTERNAL_NAME, interfaces[i]); - buf.append(' '); - } - } - buf.append(" {\n\n"); - - text.add(buf.toString()); - } - - @Override - public void visitSource(final String file, final String debug) { - buf.setLength(0); - if (file != null) { - buf.append(tab).append("// compiled from: ").append(file) - .append('\n'); - } - if (debug != null) { - buf.append(tab).append("// debug info: ").append(debug) - .append('\n'); - } - if (buf.length() > 0) { - text.add(buf.toString()); - } - } - - @Override - public void visitOuterClass(final String owner, final String name, - final String desc) { - buf.setLength(0); - buf.append(tab).append("OUTERCLASS "); - appendDescriptor(INTERNAL_NAME, owner); - buf.append(' '); - if (name != null) { - buf.append(name).append(' '); - } - appendDescriptor(METHOD_DESCRIPTOR, desc); - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public Textifier visitClassAnnotation(final String desc, - final boolean visible) { - text.add("\n"); - return visitAnnotation(desc, visible); - } - - @Override - public Printer visitClassTypeAnnotation(int typeRef, TypePath typePath, - String desc, boolean visible) { - text.add("\n"); - return visitTypeAnnotation(typeRef, typePath, desc, visible); - } - - @Override - public void visitClassAttribute(final Attribute attr) { - text.add("\n"); - visitAttribute(attr); - } - - @Override - public void visitInnerClass(final String name, final String outerName, - final String innerName, final int access) { - buf.setLength(0); - buf.append(tab).append("// access flags 0x"); - buf.append( - Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase()) - .append('\n'); - buf.append(tab); - appendAccess(access); - buf.append("INNERCLASS "); - appendDescriptor(INTERNAL_NAME, name); - buf.append(' '); - appendDescriptor(INTERNAL_NAME, outerName); - buf.append(' '); - appendDescriptor(INTERNAL_NAME, innerName); - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public Textifier visitField(final int access, final String name, - final String desc, final String signature, final Object value) { - buf.setLength(0); - buf.append('\n'); - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - buf.append(tab).append("// DEPRECATED\n"); - } - buf.append(tab).append("// access flags 0x") - .append(Integer.toHexString(access).toUpperCase()).append('\n'); - if (signature != null) { - buf.append(tab); - appendDescriptor(FIELD_SIGNATURE, signature); - - TraceSignatureVisitor sv = new TraceSignatureVisitor(0); - SignatureReader r = new SignatureReader(signature); - r.acceptType(sv); - buf.append(tab).append("// declaration: ") - .append(sv.getDeclaration()).append('\n'); - } - - buf.append(tab); - appendAccess(access); - - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append(' ').append(name); - if (value != null) { - buf.append(" = "); - if (value instanceof String) { - buf.append('\"').append(value).append('\"'); - } else { - buf.append(value); - } - } - - buf.append('\n'); - text.add(buf.toString()); - - Textifier t = createTextifier(); - text.add(t.getText()); - return t; - } - - @Override - public Textifier visitMethod(final int access, final String name, - final String desc, final String signature, final String[] exceptions) { - buf.setLength(0); - buf.append('\n'); - if ((access & Opcodes.ACC_DEPRECATED) != 0) { - buf.append(tab).append("// DEPRECATED\n"); - } - buf.append(tab).append("// access flags 0x") - .append(Integer.toHexString(access).toUpperCase()).append('\n'); - - if (signature != null) { - buf.append(tab); - appendDescriptor(METHOD_SIGNATURE, signature); - - TraceSignatureVisitor v = new TraceSignatureVisitor(0); - SignatureReader r = new SignatureReader(signature); - r.accept(v); - String genericDecl = v.getDeclaration(); - String genericReturn = v.getReturnType(); - String genericExceptions = v.getExceptions(); - - buf.append(tab).append("// declaration: ").append(genericReturn) - .append(' ').append(name).append(genericDecl); - if (genericExceptions != null) { - buf.append(" throws ").append(genericExceptions); - } - buf.append('\n'); - } - - buf.append(tab); - appendAccess(access & ~Opcodes.ACC_VOLATILE); - if ((access & Opcodes.ACC_NATIVE) != 0) { - buf.append("native "); - } - if ((access & Opcodes.ACC_VARARGS) != 0) { - buf.append("varargs "); - } - if ((access & Opcodes.ACC_BRIDGE) != 0) { - buf.append("bridge "); - } - if ((this.access & Opcodes.ACC_INTERFACE) != 0 - && (access & Opcodes.ACC_ABSTRACT) == 0 - && (access & Opcodes.ACC_STATIC) == 0) { - buf.append("default "); - } - - buf.append(name); - appendDescriptor(METHOD_DESCRIPTOR, desc); - if (exceptions != null && exceptions.length > 0) { - buf.append(" throws "); - for (int i = 0; i < exceptions.length; ++i) { - appendDescriptor(INTERNAL_NAME, exceptions[i]); - buf.append(' '); - } - } - - buf.append('\n'); - text.add(buf.toString()); - - Textifier t = createTextifier(); - text.add(t.getText()); - return t; - } - - @Override - public void visitClassEnd() { - text.add("}\n"); - } - - // ------------------------------------------------------------------------ - // Annotations - // ------------------------------------------------------------------------ - - @Override - public void visit(final String name, final Object value) { - buf.setLength(0); - appendComa(valueNumber++); - - if (name != null) { - buf.append(name).append('='); - } - - if (value instanceof String) { - visitString((String) value); - } else if (value instanceof Type) { - visitType((Type) value); - } else if (value instanceof Byte) { - visitByte(((Byte) value).byteValue()); - } else if (value instanceof Boolean) { - visitBoolean(((Boolean) value).booleanValue()); - } else if (value instanceof Short) { - visitShort(((Short) value).shortValue()); - } else if (value instanceof Character) { - visitChar(((Character) value).charValue()); - } else if (value instanceof Integer) { - visitInt(((Integer) value).intValue()); - } else if (value instanceof Float) { - visitFloat(((Float) value).floatValue()); - } else if (value instanceof Long) { - visitLong(((Long) value).longValue()); - } else if (value instanceof Double) { - visitDouble(((Double) value).doubleValue()); - } else if (value.getClass().isArray()) { - buf.append('{'); - if (value instanceof byte[]) { - byte[] v = (byte[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitByte(v[i]); - } - } else if (value instanceof boolean[]) { - boolean[] v = (boolean[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitBoolean(v[i]); - } - } else if (value instanceof short[]) { - short[] v = (short[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitShort(v[i]); - } - } else if (value instanceof char[]) { - char[] v = (char[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitChar(v[i]); - } - } else if (value instanceof int[]) { - int[] v = (int[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitInt(v[i]); - } - } else if (value instanceof long[]) { - long[] v = (long[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitLong(v[i]); - } - } else if (value instanceof float[]) { - float[] v = (float[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitFloat(v[i]); - } - } else if (value instanceof double[]) { - double[] v = (double[]) value; - for (int i = 0; i < v.length; i++) { - appendComa(i); - visitDouble(v[i]); - } - } - buf.append('}'); - } - - text.add(buf.toString()); - } - - private void visitInt(final int value) { - buf.append(value); - } - - private void visitLong(final long value) { - buf.append(value).append('L'); - } - - private void visitFloat(final float value) { - buf.append(value).append('F'); - } - - private void visitDouble(final double value) { - buf.append(value).append('D'); - } - - private void visitChar(final char value) { - buf.append("(char)").append((int) value); - } - - private void visitShort(final short value) { - buf.append("(short)").append(value); - } - - private void visitByte(final byte value) { - buf.append("(byte)").append(value); - } - - private void visitBoolean(final boolean value) { - buf.append(value); - } - - private void visitString(final String value) { - appendString(buf, value); - } - - private void visitType(final Type value) { - buf.append(value.getClassName()).append(".class"); - } - - @Override - public void visitEnum(final String name, final String desc, - final String value) { - buf.setLength(0); - appendComa(valueNumber++); - if (name != null) { - buf.append(name).append('='); - } - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('.').append(value); - text.add(buf.toString()); - } - - @Override - public Textifier visitAnnotation(final String name, final String desc) { - buf.setLength(0); - appendComa(valueNumber++); - if (name != null) { - buf.append(name).append('='); - } - buf.append('@'); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('('); - text.add(buf.toString()); - Textifier t = createTextifier(); - text.add(t.getText()); - text.add(")"); - return t; - } - - @Override - public Textifier visitArray(final String name) { - buf.setLength(0); - appendComa(valueNumber++); - if (name != null) { - buf.append(name).append('='); - } - buf.append('{'); - text.add(buf.toString()); - Textifier t = createTextifier(); - text.add(t.getText()); - text.add("}"); - return t; - } - - @Override - public void visitAnnotationEnd() { - } - - // ------------------------------------------------------------------------ - // Fields - // ------------------------------------------------------------------------ - - @Override - public Textifier visitFieldAnnotation(final String desc, - final boolean visible) { - return visitAnnotation(desc, visible); - } - - @Override - public Printer visitFieldTypeAnnotation(int typeRef, TypePath typePath, - String desc, boolean visible) { - return visitTypeAnnotation(typeRef, typePath, desc, visible); - } - - @Override - public void visitFieldAttribute(final Attribute attr) { - visitAttribute(attr); - } - - @Override - public void visitFieldEnd() { - } - - // ------------------------------------------------------------------------ - // Methods - // ------------------------------------------------------------------------ - - @Override - public void visitParameter(final String name, final int access) { - buf.setLength(0); - buf.append(tab2).append("// parameter "); - appendAccess(access); - buf.append(' ').append((name == null) ? "<no name>" : name) - .append('\n'); - text.add(buf.toString()); - } - - @Override - public Textifier visitAnnotationDefault() { - text.add(tab2 + "default="); - Textifier t = createTextifier(); - text.add(t.getText()); - text.add("\n"); - return t; - } - - @Override - public Textifier visitMethodAnnotation(final String desc, - final boolean visible) { - return visitAnnotation(desc, visible); - } - - @Override - public Printer visitMethodTypeAnnotation(int typeRef, TypePath typePath, - String desc, boolean visible) { - return visitTypeAnnotation(typeRef, typePath, desc, visible); - } - - @Override - public Textifier visitParameterAnnotation(final int parameter, - final String desc, final boolean visible) { - buf.setLength(0); - buf.append(tab2).append('@'); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('('); - text.add(buf.toString()); - Textifier t = createTextifier(); - text.add(t.getText()); - text.add(visible ? ") // parameter " : ") // invisible, parameter "); - text.add(new Integer(parameter)); - text.add("\n"); - return t; - } - - @Override - public void visitMethodAttribute(final Attribute attr) { - buf.setLength(0); - buf.append(tab).append("ATTRIBUTE "); - appendDescriptor(-1, attr.type); - - if (attr instanceof Textifiable) { - ((Textifiable) attr).textify(buf, labelNames); - } else { - buf.append(" : unknown\n"); - } - - text.add(buf.toString()); - } - - @Override - public void visitCode() { - } - - @Override - public void visitFrame(final int type, final int nLocal, - final Object[] local, final int nStack, final Object[] stack) { - buf.setLength(0); - buf.append(ltab); - buf.append("FRAME "); - switch (type) { - case Opcodes.F_NEW: - case Opcodes.F_FULL: - buf.append("FULL ["); - appendFrameTypes(nLocal, local); - buf.append("] ["); - appendFrameTypes(nStack, stack); - buf.append(']'); - break; - case Opcodes.F_APPEND: - buf.append("APPEND ["); - appendFrameTypes(nLocal, local); - buf.append(']'); - break; - case Opcodes.F_CHOP: - buf.append("CHOP ").append(nLocal); - break; - case Opcodes.F_SAME: - buf.append("SAME"); - break; - case Opcodes.F_SAME1: - buf.append("SAME1 "); - appendFrameTypes(1, stack); - break; - } - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitInsn(final int opcode) { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitIntInsn(final int opcode, final int operand) { - buf.setLength(0); - buf.append(tab2) - .append(OPCODES[opcode]) - .append(' ') - .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer - .toString(operand)).append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitVarInsn(final int opcode, final int var) { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append(' ').append(var) - .append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitTypeInsn(final int opcode, final String type) { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append(' '); - appendDescriptor(INTERNAL_NAME, type); - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitFieldInsn(final int opcode, final String owner, - final String name, final String desc) { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append(' '); - appendDescriptor(INTERNAL_NAME, owner); - buf.append('.').append(name).append(" : "); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('\n'); - text.add(buf.toString()); - } - - @Deprecated - @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc) { - if (api >= Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc); - return; - } - doVisitMethodInsn(opcode, owner, name, desc, - opcode == Opcodes.INVOKEINTERFACE); - } - - @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc, final boolean itf) { - if (api < Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - doVisitMethodInsn(opcode, owner, name, desc, itf); - } - - private void doVisitMethodInsn(final int opcode, final String owner, - final String name, final String desc, final boolean itf) { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append(' '); - appendDescriptor(INTERNAL_NAME, owner); - buf.append('.').append(name).append(' '); - appendDescriptor(METHOD_DESCRIPTOR, desc); - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, - Object... bsmArgs) { - buf.setLength(0); - buf.append(tab2).append("INVOKEDYNAMIC").append(' '); - buf.append(name); - appendDescriptor(METHOD_DESCRIPTOR, desc); - buf.append(" ["); - buf.append('\n'); - buf.append(tab3); - appendHandle(bsm); - buf.append('\n'); - buf.append(tab3).append("// arguments:"); - if (bsmArgs.length == 0) { - buf.append(" none"); - } else { - buf.append('\n'); - for (int i = 0; i < bsmArgs.length; i++) { - buf.append(tab3); - Object cst = bsmArgs[i]; - if (cst instanceof String) { - Printer.appendString(buf, (String) cst); - } else if (cst instanceof Type) { - Type type = (Type) cst; - if(type.getSort() == Type.METHOD){ - appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor()); - } else { - buf.append(type.getDescriptor()).append(".class"); - } - } else if (cst instanceof Handle) { - appendHandle((Handle) cst); - } else { - buf.append(cst); - } - buf.append(", \n"); - } - buf.setLength(buf.length() - 3); - } - buf.append('\n'); - buf.append(tab2).append("]\n"); - text.add(buf.toString()); - } - - @Override - public void visitJumpInsn(final int opcode, final Label label) { - buf.setLength(0); - buf.append(tab2).append(OPCODES[opcode]).append(' '); - appendLabel(label); - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitLabel(final Label label) { - buf.setLength(0); - buf.append(ltab); - appendLabel(label); - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitLdcInsn(final Object cst) { - buf.setLength(0); - buf.append(tab2).append("LDC "); - if (cst instanceof String) { - Printer.appendString(buf, (String) cst); - } else if (cst instanceof Type) { - buf.append(((Type) cst).getDescriptor()).append(".class"); - } else { - buf.append(cst); - } - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitIincInsn(final int var, final int increment) { - buf.setLength(0); - buf.append(tab2).append("IINC ").append(var).append(' ') - .append(increment).append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitTableSwitchInsn(final int min, final int max, - final Label dflt, final Label... labels) { - buf.setLength(0); - buf.append(tab2).append("TABLESWITCH\n"); - for (int i = 0; i < labels.length; ++i) { - buf.append(tab3).append(min + i).append(": "); - appendLabel(labels[i]); - buf.append('\n'); - } - buf.append(tab3).append("default: "); - appendLabel(dflt); - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitLookupSwitchInsn(final Label dflt, final int[] keys, - final Label[] labels) { - buf.setLength(0); - buf.append(tab2).append("LOOKUPSWITCH\n"); - for (int i = 0; i < labels.length; ++i) { - buf.append(tab3).append(keys[i]).append(": "); - appendLabel(labels[i]); - buf.append('\n'); - } - buf.append(tab3).append("default: "); - appendLabel(dflt); - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitMultiANewArrayInsn(final String desc, final int dims) { - buf.setLength(0); - buf.append(tab2).append("MULTIANEWARRAY "); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append(' ').append(dims).append('\n'); - text.add(buf.toString()); - } - - @Override - public Printer visitInsnAnnotation(int typeRef, TypePath typePath, - String desc, boolean visible) { - return visitTypeAnnotation(typeRef, typePath, desc, visible); - } - - @Override - public void visitTryCatchBlock(final Label start, final Label end, - final Label handler, final String type) { - buf.setLength(0); - buf.append(tab2).append("TRYCATCHBLOCK "); - appendLabel(start); - buf.append(' '); - appendLabel(end); - buf.append(' '); - appendLabel(handler); - buf.append(' '); - appendDescriptor(INTERNAL_NAME, type); - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public Printer visitTryCatchAnnotation(int typeRef, TypePath typePath, - String desc, boolean visible) { - buf.setLength(0); - buf.append(tab2).append("TRYCATCHBLOCK @"); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('('); - text.add(buf.toString()); - Textifier t = createTextifier(); - text.add(t.getText()); - buf.setLength(0); - buf.append(") : "); - appendTypeReference(typeRef); - buf.append(", ").append(typePath); - buf.append(visible ? "\n" : " // invisible\n"); - text.add(buf.toString()); - return t; - } - - @Override - public void visitLocalVariable(final String name, final String desc, - final String signature, final Label start, final Label end, - final int index) { - buf.setLength(0); - buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' '); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append(' '); - appendLabel(start); - buf.append(' '); - appendLabel(end); - buf.append(' ').append(index).append('\n'); - - if (signature != null) { - buf.append(tab2); - appendDescriptor(FIELD_SIGNATURE, signature); - - TraceSignatureVisitor sv = new TraceSignatureVisitor(0); - SignatureReader r = new SignatureReader(signature); - r.acceptType(sv); - buf.append(tab2).append("// declaration: ") - .append(sv.getDeclaration()).append('\n'); - } - text.add(buf.toString()); - } - - @Override - public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath, - Label[] start, Label[] end, int[] index, String desc, - boolean visible) { - buf.setLength(0); - buf.append(tab2).append("LOCALVARIABLE @"); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('('); - text.add(buf.toString()); - Textifier t = createTextifier(); - text.add(t.getText()); - buf.setLength(0); - buf.append(") : "); - appendTypeReference(typeRef); - buf.append(", ").append(typePath); - for (int i = 0; i < start.length; ++i) { - buf.append(" [ "); - appendLabel(start[i]); - buf.append(" - "); - appendLabel(end[i]); - buf.append(" - ").append(index[i]).append(" ]"); - } - buf.append(visible ? "\n" : " // invisible\n"); - text.add(buf.toString()); - return t; - } - - @Override - public void visitLineNumber(final int line, final Label start) { - buf.setLength(0); - buf.append(tab2).append("LINENUMBER ").append(line).append(' '); - appendLabel(start); - buf.append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitMaxs(final int maxStack, final int maxLocals) { - buf.setLength(0); - buf.append(tab2).append("MAXSTACK = ").append(maxStack).append('\n'); - text.add(buf.toString()); - - buf.setLength(0); - buf.append(tab2).append("MAXLOCALS = ").append(maxLocals).append('\n'); - text.add(buf.toString()); - } - - @Override - public void visitMethodEnd() { - } - - // ------------------------------------------------------------------------ - // Common methods - // ------------------------------------------------------------------------ - - /** - * Prints a disassembled view of the given annotation. - * - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values. - */ - public Textifier visitAnnotation(final String desc, final boolean visible) { - buf.setLength(0); - buf.append(tab).append('@'); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('('); - text.add(buf.toString()); - Textifier t = createTextifier(); - text.add(t.getText()); - text.add(visible ? ")\n" : ") // invisible\n"); - return t; - } - - /** - * Prints a disassembled view of the given type annotation. - * - * @param typeRef - * a reference to the annotated type. See {@link TypeReference}. - * @param typePath - * the path to the annotated type argument, wildcard bound, array - * element type, or static inner type within 'typeRef'. May be - * <tt>null</tt> if the annotation targets 'typeRef' as a whole. - * @param desc - * the class descriptor of the annotation class. - * @param visible - * <tt>true</tt> if the annotation is visible at runtime. - * @return a visitor to visit the annotation values. - */ - public Textifier visitTypeAnnotation(final int typeRef, - final TypePath typePath, final String desc, final boolean visible) { - buf.setLength(0); - buf.append(tab).append('@'); - appendDescriptor(FIELD_DESCRIPTOR, desc); - buf.append('('); - text.add(buf.toString()); - Textifier t = createTextifier(); - text.add(t.getText()); - buf.setLength(0); - buf.append(") : "); - appendTypeReference(typeRef); - buf.append(", ").append(typePath); - buf.append(visible ? "\n" : " // invisible\n"); - text.add(buf.toString()); - return t; - } - - /** - * Prints a disassembled view of the given attribute. - * - * @param attr - * an attribute. - */ - public void visitAttribute(final Attribute attr) { - buf.setLength(0); - buf.append(tab).append("ATTRIBUTE "); - appendDescriptor(-1, attr.type); - - if (attr instanceof Textifiable) { - ((Textifiable) attr).textify(buf, null); - } else { - buf.append(" : unknown\n"); - } - - text.add(buf.toString()); - } - - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ - - /** - * Creates a new TraceVisitor instance. - * - * @return a new TraceVisitor. - */ - protected Textifier createTextifier() { - return new Textifier(); - } - - /** - * Appends an internal name, a type descriptor or a type signature to - * {@link #buf buf}. - * - * @param type - * indicates if desc is an internal name, a field descriptor, a - * method descriptor, a class signature, ... - * @param desc - * an internal name, type descriptor, or type signature. May be - * <tt>null</tt>. - */ - protected void appendDescriptor(final int type, final String desc) { - if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE - || type == METHOD_SIGNATURE) { - if (desc != null) { - buf.append("// signature ").append(desc).append('\n'); - } - } else { - buf.append(desc); - } - } - - /** - * Appends the name of the given label to {@link #buf buf}. Creates a new - * label name if the given label does not yet have one. - * - * @param l - * a label. - */ - protected void appendLabel(final Label l) { - if (labelNames == null) { - labelNames = new HashMap<Label, String>(); - } - String name = labelNames.get(l); - if (name == null) { - name = "L" + labelNames.size(); - labelNames.put(l, name); - } - buf.append(name); - } - - /** - * Appends the information about the given handle to {@link #buf buf}. - * - * @param h - * a handle, non null. - */ - protected void appendHandle(final Handle h) { - int tag = h.getTag(); - buf.append("// handle kind 0x").append(Integer.toHexString(tag)) - .append(" : "); - boolean isMethodHandle = false; - switch (tag) { - case Opcodes.H_GETFIELD: - buf.append("GETFIELD"); - break; - case Opcodes.H_GETSTATIC: - buf.append("GETSTATIC"); - break; - case Opcodes.H_PUTFIELD: - buf.append("PUTFIELD"); - break; - case Opcodes.H_PUTSTATIC: - buf.append("PUTSTATIC"); - break; - case Opcodes.H_INVOKEINTERFACE: - buf.append("INVOKEINTERFACE"); - isMethodHandle = true; - break; - case Opcodes.H_INVOKESPECIAL: - buf.append("INVOKESPECIAL"); - isMethodHandle = true; - break; - case Opcodes.H_INVOKESTATIC: - buf.append("INVOKESTATIC"); - isMethodHandle = true; - break; - case Opcodes.H_INVOKEVIRTUAL: - buf.append("INVOKEVIRTUAL"); - isMethodHandle = true; - break; - case Opcodes.H_NEWINVOKESPECIAL: - buf.append("NEWINVOKESPECIAL"); - isMethodHandle = true; - break; - } - buf.append('\n'); - buf.append(tab3); - appendDescriptor(INTERNAL_NAME, h.getOwner()); - buf.append('.'); - buf.append(h.getName()); - if(!isMethodHandle){ - buf.append('('); - } - appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc()); - if(!isMethodHandle){ - buf.append(')'); - } - } - - /** - * Appends a string representation of the given access modifiers to - * {@link #buf buf}. - * - * @param access - * some access modifiers. - */ - private void appendAccess(final int access) { - if ((access & Opcodes.ACC_PUBLIC) != 0) { - buf.append("public "); - } - if ((access & Opcodes.ACC_PRIVATE) != 0) { - buf.append("private "); - } - if ((access & Opcodes.ACC_PROTECTED) != 0) { - buf.append("protected "); - } - if ((access & Opcodes.ACC_FINAL) != 0) { - buf.append("final "); - } - if ((access & Opcodes.ACC_STATIC) != 0) { - buf.append("static "); - } - if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { - buf.append("synchronized "); - } - if ((access & Opcodes.ACC_VOLATILE) != 0) { - buf.append("volatile "); - } - if ((access & Opcodes.ACC_TRANSIENT) != 0) { - buf.append("transient "); - } - if ((access & Opcodes.ACC_ABSTRACT) != 0) { - buf.append("abstract "); - } - if ((access & Opcodes.ACC_STRICT) != 0) { - buf.append("strictfp "); - } - if ((access & Opcodes.ACC_SYNTHETIC) != 0) { - buf.append("synthetic "); - } - if ((access & Opcodes.ACC_MANDATED) != 0) { - buf.append("mandated "); - } - if ((access & Opcodes.ACC_ENUM) != 0) { - buf.append("enum "); - } - } - - private void appendComa(final int i) { - if (i != 0) { - buf.append(", "); - } - } - - private void appendTypeReference(final int typeRef) { - TypeReference ref = new TypeReference(typeRef); - switch (ref.getSort()) { - case TypeReference.CLASS_TYPE_PARAMETER: - buf.append("CLASS_TYPE_PARAMETER ").append( - ref.getTypeParameterIndex()); - break; - case TypeReference.METHOD_TYPE_PARAMETER: - buf.append("METHOD_TYPE_PARAMETER ").append( - ref.getTypeParameterIndex()); - break; - case TypeReference.CLASS_EXTENDS: - buf.append("CLASS_EXTENDS ").append(ref.getSuperTypeIndex()); - break; - case TypeReference.CLASS_TYPE_PARAMETER_BOUND: - buf.append("CLASS_TYPE_PARAMETER_BOUND ") - .append(ref.getTypeParameterIndex()).append(", ") - .append(ref.getTypeParameterBoundIndex()); - break; - case TypeReference.METHOD_TYPE_PARAMETER_BOUND: - buf.append("METHOD_TYPE_PARAMETER_BOUND ") - .append(ref.getTypeParameterIndex()).append(", ") - .append(ref.getTypeParameterBoundIndex()); - break; - case TypeReference.FIELD: - buf.append("FIELD"); - break; - case TypeReference.METHOD_RETURN: - buf.append("METHOD_RETURN"); - break; - case TypeReference.METHOD_RECEIVER: - buf.append("METHOD_RECEIVER"); - break; - case TypeReference.METHOD_FORMAL_PARAMETER: - buf.append("METHOD_FORMAL_PARAMETER ").append( - ref.getFormalParameterIndex()); - break; - case TypeReference.THROWS: - buf.append("THROWS ").append(ref.getExceptionIndex()); - break; - case TypeReference.LOCAL_VARIABLE: - buf.append("LOCAL_VARIABLE"); - break; - case TypeReference.RESOURCE_VARIABLE: - buf.append("RESOURCE_VARIABLE"); - break; - case TypeReference.EXCEPTION_PARAMETER: - buf.append("EXCEPTION_PARAMETER ").append( - ref.getTryCatchBlockIndex()); - break; - case TypeReference.INSTANCEOF: - buf.append("INSTANCEOF"); - break; - case TypeReference.NEW: - buf.append("NEW"); - break; - case TypeReference.CONSTRUCTOR_REFERENCE: - buf.append("CONSTRUCTOR_REFERENCE"); - break; - case TypeReference.METHOD_REFERENCE: - buf.append("METHOD_REFERENCE"); - break; - case TypeReference.CAST: - buf.append("CAST ").append(ref.getTypeArgumentIndex()); - break; - case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: - buf.append("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT ").append( - ref.getTypeArgumentIndex()); - break; - case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT: - buf.append("METHOD_INVOCATION_TYPE_ARGUMENT ").append( - ref.getTypeArgumentIndex()); - break; - case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: - buf.append("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT ").append( - ref.getTypeArgumentIndex()); - break; - case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT: - buf.append("METHOD_REFERENCE_TYPE_ARGUMENT ").append( - ref.getTypeArgumentIndex()); - break; - } - } - - private void appendFrameTypes(final int n, final Object[] o) { - for (int i = 0; i < n; ++i) { - if (i > 0) { - buf.append(' '); - } - if (o[i] instanceof String) { - String desc = (String) o[i]; - if (desc.startsWith("[")) { - appendDescriptor(FIELD_DESCRIPTOR, desc); - } else { - appendDescriptor(INTERNAL_NAME, desc); - } - } else if (o[i] instanceof Integer) { - switch (((Integer) o[i]).intValue()) { - case 0: - appendDescriptor(FIELD_DESCRIPTOR, "T"); - break; - case 1: - appendDescriptor(FIELD_DESCRIPTOR, "I"); - break; - case 2: - appendDescriptor(FIELD_DESCRIPTOR, "F"); - break; - case 3: - appendDescriptor(FIELD_DESCRIPTOR, "D"); - break; - case 4: - appendDescriptor(FIELD_DESCRIPTOR, "J"); - break; - case 5: - appendDescriptor(FIELD_DESCRIPTOR, "N"); - break; - case 6: - appendDescriptor(FIELD_DESCRIPTOR, "U"); - break; - } - } else { - appendLabel((Label) o[i]); - } - } - } -} diff --git a/src/asm/scala/tools/asm/util/TraceAnnotationVisitor.java b/src/asm/scala/tools/asm/util/TraceAnnotationVisitor.java deleted file mode 100644 index 7a9dbfef06..0000000000 --- a/src/asm/scala/tools/asm/util/TraceAnnotationVisitor.java +++ /dev/null @@ -1,89 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Opcodes; - -/** - * An {@link AnnotationVisitor} that prints the annotations it visits with a - * {@link Printer}. - * - * @author Eric Bruneton - */ -public final class TraceAnnotationVisitor extends AnnotationVisitor { - - private final Printer p; - - public TraceAnnotationVisitor(final Printer p) { - this(null, p); - } - - public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) { - super(Opcodes.ASM5, av); - this.p = p; - } - - @Override - public void visit(final String name, final Object value) { - p.visit(name, value); - super.visit(name, value); - } - - @Override - public void visitEnum(final String name, final String desc, - final String value) { - p.visitEnum(name, desc, value); - super.visitEnum(name, desc, value); - } - - @Override - public AnnotationVisitor visitAnnotation(final String name, - final String desc) { - Printer p = this.p.visitAnnotation(name, desc); - AnnotationVisitor av = this.av == null ? null : this.av - .visitAnnotation(name, desc); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public AnnotationVisitor visitArray(final String name) { - Printer p = this.p.visitArray(name); - AnnotationVisitor av = this.av == null ? null : this.av - .visitArray(name); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public void visitEnd() { - p.visitAnnotationEnd(); - super.visitEnd(); - } -} diff --git a/src/asm/scala/tools/asm/util/TraceClassVisitor.java b/src/asm/scala/tools/asm/util/TraceClassVisitor.java deleted file mode 100644 index 842d286672..0000000000 --- a/src/asm/scala/tools/asm/util/TraceClassVisitor.java +++ /dev/null @@ -1,220 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import java.io.PrintWriter; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Attribute; -import scala.tools.asm.ClassVisitor; -import scala.tools.asm.FieldVisitor; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.TypePath; - -/** - * A {@link ClassVisitor} that prints the classes it visits with a - * {@link Printer}. This class visitor can be used in the middle of a class - * visitor chain to trace the class that is visited at a given point in this - * chain. This may be useful for debugging purposes. - * <p> - * The trace printed when visiting the <tt>Hello</tt> class is the following: - * <p> - * <blockquote> - * - * <pre> - * // class version 49.0 (49) // access flags 0x21 public class Hello { - * - * // compiled from: Hello.java - * - * // access flags 0x1 public <init> ()V ALOAD 0 INVOKESPECIAL - * java/lang/Object <init> ()V RETURN MAXSTACK = 1 MAXLOCALS = 1 - * - * // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC - * java/lang/System out Ljava/io/PrintStream; LDC "hello" - * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN - * MAXSTACK = 2 MAXLOCALS = 1 } - * </pre> - * - * </blockquote> where <tt>Hello</tt> is defined by: - * <p> - * <blockquote> - * - * <pre> - * public class Hello { - * - * public static void main(String[] args) { - * System.out.println("hello"); - * } - * } - * </pre> - * - * </blockquote> - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -public final class TraceClassVisitor extends ClassVisitor { - - /** - * The print writer to be used to print the class. May be null. - */ - private final PrintWriter pw; - - /** - * The object that actually converts visit events into text. - */ - public final Printer p; - - /** - * Constructs a new {@link TraceClassVisitor}. - * - * @param pw - * the print writer to be used to print the class. - */ - public TraceClassVisitor(final PrintWriter pw) { - this(null, pw); - } - - /** - * Constructs a new {@link TraceClassVisitor}. - * - * @param cv - * the {@link ClassVisitor} to which this visitor delegates - * calls. May be <tt>null</tt>. - * @param pw - * the print writer to be used to print the class. - */ - public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) { - this(cv, new Textifier(), pw); - } - - /** - * Constructs a new {@link TraceClassVisitor}. - * - * @param cv - * the {@link ClassVisitor} to which this visitor delegates - * calls. May be <tt>null</tt>. - * @param p - * the object that actually converts visit events into text. - * @param pw - * the print writer to be used to print the class. May be null if - * you simply want to use the result via - * {@link Printer#getText()}, instead of printing it. - */ - public TraceClassVisitor(final ClassVisitor cv, final Printer p, - final PrintWriter pw) { - super(Opcodes.ASM5, cv); - this.pw = pw; - this.p = p; - } - - @Override - public void visit(final int version, final int access, final String name, - final String signature, final String superName, - final String[] interfaces) { - p.visit(version, access, name, signature, superName, interfaces); - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public void visitSource(final String file, final String debug) { - p.visitSource(file, debug); - super.visitSource(file, debug); - } - - @Override - public void visitOuterClass(final String owner, final String name, - final String desc) { - p.visitOuterClass(owner, name, desc); - super.visitOuterClass(owner, name, desc); - } - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - Printer p = this.p.visitClassAnnotation(desc, visible); - AnnotationVisitor av = cv == null ? null : cv.visitAnnotation(desc, - visible); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - Printer p = this.p.visitClassTypeAnnotation(typeRef, typePath, desc, - visible); - AnnotationVisitor av = cv == null ? null : cv.visitTypeAnnotation( - typeRef, typePath, desc, visible); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public void visitAttribute(final Attribute attr) { - p.visitClassAttribute(attr); - super.visitAttribute(attr); - } - - @Override - public void visitInnerClass(final String name, final String outerName, - final String innerName, final int access) { - p.visitInnerClass(name, outerName, innerName, access); - super.visitInnerClass(name, outerName, innerName, access); - } - - @Override - public FieldVisitor visitField(final int access, final String name, - final String desc, final String signature, final Object value) { - Printer p = this.p.visitField(access, name, desc, signature, value); - FieldVisitor fv = cv == null ? null : cv.visitField(access, name, desc, - signature, value); - return new TraceFieldVisitor(fv, p); - } - - @Override - public MethodVisitor visitMethod(final int access, final String name, - final String desc, final String signature, final String[] exceptions) { - Printer p = this.p.visitMethod(access, name, desc, signature, - exceptions); - MethodVisitor mv = cv == null ? null : cv.visitMethod(access, name, - desc, signature, exceptions); - return new TraceMethodVisitor(mv, p); - } - - @Override - public void visitEnd() { - p.visitClassEnd(); - if (pw != null) { - p.print(pw); - pw.flush(); - } - super.visitEnd(); - } -} diff --git a/src/asm/scala/tools/asm/util/TraceFieldVisitor.java b/src/asm/scala/tools/asm/util/TraceFieldVisitor.java deleted file mode 100644 index 1d0743a424..0000000000 --- a/src/asm/scala/tools/asm/util/TraceFieldVisitor.java +++ /dev/null @@ -1,87 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Attribute; -import scala.tools.asm.FieldVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.TypePath; - -/** - * A {@link FieldVisitor} that prints the fields it visits with a - * {@link Printer}. - * - * @author Eric Bruneton - */ -public final class TraceFieldVisitor extends FieldVisitor { - - public final Printer p; - - public TraceFieldVisitor(final Printer p) { - this(null, p); - } - - public TraceFieldVisitor(final FieldVisitor fv, final Printer p) { - super(Opcodes.ASM5, fv); - this.p = p; - } - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - Printer p = this.p.visitFieldAnnotation(desc, visible); - AnnotationVisitor av = fv == null ? null : fv.visitAnnotation(desc, - visible); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - Printer p = this.p.visitFieldTypeAnnotation(typeRef, typePath, desc, - visible); - AnnotationVisitor av = fv == null ? null : fv.visitTypeAnnotation( - typeRef, typePath, desc, visible); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public void visitAttribute(final Attribute attr) { - p.visitFieldAttribute(attr); - super.visitAttribute(attr); - } - - @Override - public void visitEnd() { - p.visitFieldEnd(); - super.visitEnd(); - } -} diff --git a/src/asm/scala/tools/asm/util/TraceMethodVisitor.java b/src/asm/scala/tools/asm/util/TraceMethodVisitor.java deleted file mode 100644 index db5f051003..0000000000 --- a/src/asm/scala/tools/asm/util/TraceMethodVisitor.java +++ /dev/null @@ -1,292 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import scala.tools.asm.AnnotationVisitor; -import scala.tools.asm.Attribute; -import scala.tools.asm.Handle; -import scala.tools.asm.Label; -import scala.tools.asm.MethodVisitor; -import scala.tools.asm.Opcodes; -import scala.tools.asm.TypePath; - -/** - * A {@link MethodVisitor} that prints the methods it visits with a - * {@link Printer}. - * - * @author Eric Bruneton - */ -public final class TraceMethodVisitor extends MethodVisitor { - - public final Printer p; - - public TraceMethodVisitor(final Printer p) { - this(null, p); - } - - public TraceMethodVisitor(final MethodVisitor mv, final Printer p) { - super(Opcodes.ASM5, mv); - this.p = p; - } - - @Override - public void visitParameter(String name, int access) { - p.visitParameter(name, access); - super.visitParameter(name, access); - } - - @Override - public AnnotationVisitor visitAnnotation(final String desc, - final boolean visible) { - Printer p = this.p.visitMethodAnnotation(desc, visible); - AnnotationVisitor av = mv == null ? null : mv.visitAnnotation(desc, - visible); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - Printer p = this.p.visitMethodTypeAnnotation(typeRef, typePath, desc, - visible); - AnnotationVisitor av = mv == null ? null : mv.visitTypeAnnotation( - typeRef, typePath, desc, visible); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public void visitAttribute(final Attribute attr) { - p.visitMethodAttribute(attr); - super.visitAttribute(attr); - } - - @Override - public AnnotationVisitor visitAnnotationDefault() { - Printer p = this.p.visitAnnotationDefault(); - AnnotationVisitor av = mv == null ? null : mv.visitAnnotationDefault(); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public AnnotationVisitor visitParameterAnnotation(final int parameter, - final String desc, final boolean visible) { - Printer p = this.p.visitParameterAnnotation(parameter, desc, visible); - AnnotationVisitor av = mv == null ? null : mv.visitParameterAnnotation( - parameter, desc, visible); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public void visitCode() { - p.visitCode(); - super.visitCode(); - } - - @Override - public void visitFrame(final int type, final int nLocal, - final Object[] local, final int nStack, final Object[] stack) { - p.visitFrame(type, nLocal, local, nStack, stack); - super.visitFrame(type, nLocal, local, nStack, stack); - } - - @Override - public void visitInsn(final int opcode) { - p.visitInsn(opcode); - super.visitInsn(opcode); - } - - @Override - public void visitIntInsn(final int opcode, final int operand) { - p.visitIntInsn(opcode, operand); - super.visitIntInsn(opcode, operand); - } - - @Override - public void visitVarInsn(final int opcode, final int var) { - p.visitVarInsn(opcode, var); - super.visitVarInsn(opcode, var); - } - - @Override - public void visitTypeInsn(final int opcode, final String type) { - p.visitTypeInsn(opcode, type); - super.visitTypeInsn(opcode, type); - } - - @Override - public void visitFieldInsn(final int opcode, final String owner, - final String name, final String desc) { - p.visitFieldInsn(opcode, owner, name, desc); - super.visitFieldInsn(opcode, owner, name, desc); - } - - @Deprecated - @Override - public void visitMethodInsn(int opcode, String owner, String name, - String desc) { - if (api >= Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc); - return; - } - p.visitMethodInsn(opcode, owner, name, desc); - if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc); - } - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, - String desc, boolean itf) { - if (api < Opcodes.ASM5) { - super.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - p.visitMethodInsn(opcode, owner, name, desc, itf); - if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc, itf); - } - } - - @Override - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, - Object... bsmArgs) { - p.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); - super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); - } - - @Override - public void visitJumpInsn(final int opcode, final Label label) { - p.visitJumpInsn(opcode, label); - super.visitJumpInsn(opcode, label); - } - - @Override - public void visitLabel(final Label label) { - p.visitLabel(label); - super.visitLabel(label); - } - - @Override - public void visitLdcInsn(final Object cst) { - p.visitLdcInsn(cst); - super.visitLdcInsn(cst); - } - - @Override - public void visitIincInsn(final int var, final int increment) { - p.visitIincInsn(var, increment); - super.visitIincInsn(var, increment); - } - - @Override - public void visitTableSwitchInsn(final int min, final int max, - final Label dflt, final Label... labels) { - p.visitTableSwitchInsn(min, max, dflt, labels); - super.visitTableSwitchInsn(min, max, dflt, labels); - } - - @Override - public void visitLookupSwitchInsn(final Label dflt, final int[] keys, - final Label[] labels) { - p.visitLookupSwitchInsn(dflt, keys, labels); - super.visitLookupSwitchInsn(dflt, keys, labels); - } - - @Override - public void visitMultiANewArrayInsn(final String desc, final int dims) { - p.visitMultiANewArrayInsn(desc, dims); - super.visitMultiANewArrayInsn(desc, dims); - } - - @Override - public AnnotationVisitor visitInsnAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - Printer p = this.p - .visitInsnAnnotation(typeRef, typePath, desc, visible); - AnnotationVisitor av = mv == null ? null : mv.visitInsnAnnotation( - typeRef, typePath, desc, visible); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public void visitTryCatchBlock(final Label start, final Label end, - final Label handler, final String type) { - p.visitTryCatchBlock(start, end, handler, type); - super.visitTryCatchBlock(start, end, handler, type); - } - - @Override - public AnnotationVisitor visitTryCatchAnnotation(int typeRef, - TypePath typePath, String desc, boolean visible) { - Printer p = this.p.visitTryCatchAnnotation(typeRef, typePath, desc, - visible); - AnnotationVisitor av = mv == null ? null : mv.visitTryCatchAnnotation( - typeRef, typePath, desc, visible); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public void visitLocalVariable(final String name, final String desc, - final String signature, final Label start, final Label end, - final int index) { - p.visitLocalVariable(name, desc, signature, start, end, index); - super.visitLocalVariable(name, desc, signature, start, end, index); - } - - @Override - public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, - TypePath typePath, Label[] start, Label[] end, int[] index, - String desc, boolean visible) { - Printer p = this.p.visitLocalVariableAnnotation(typeRef, typePath, - start, end, index, desc, visible); - AnnotationVisitor av = mv == null ? null : mv - .visitLocalVariableAnnotation(typeRef, typePath, start, end, - index, desc, visible); - return new TraceAnnotationVisitor(av, p); - } - - @Override - public void visitLineNumber(final int line, final Label start) { - p.visitLineNumber(line, start); - super.visitLineNumber(line, start); - } - - @Override - public void visitMaxs(final int maxStack, final int maxLocals) { - p.visitMaxs(maxStack, maxLocals); - super.visitMaxs(maxStack, maxLocals); - } - - @Override - public void visitEnd() { - p.visitMethodEnd(); - super.visitEnd(); - } -} diff --git a/src/asm/scala/tools/asm/util/TraceSignatureVisitor.java b/src/asm/scala/tools/asm/util/TraceSignatureVisitor.java deleted file mode 100644 index f99ec2b0c2..0000000000 --- a/src/asm/scala/tools/asm/util/TraceSignatureVisitor.java +++ /dev/null @@ -1,317 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package scala.tools.asm.util; - -import scala.tools.asm.Opcodes; -import scala.tools.asm.signature.SignatureVisitor; - -/** - * A {@link SignatureVisitor} that prints a disassembled view of the signature - * it visits. - * - * @author Eugene Kuleshov - * @author Eric Bruneton - */ -public final class TraceSignatureVisitor extends SignatureVisitor { - - private final StringBuffer declaration; - - private boolean isInterface; - - private boolean seenFormalParameter; - - private boolean seenInterfaceBound; - - private boolean seenParameter; - - private boolean seenInterface; - - private StringBuffer returnType; - - private StringBuffer exceptions; - - /** - * Stack used to keep track of class types that have arguments. Each element - * of this stack is a boolean encoded in one bit. The top of the stack is - * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping = - * /2. - */ - private int argumentStack; - - /** - * Stack used to keep track of array class types. Each element of this stack - * is a boolean encoded in one bit. The top of the stack is the lowest order - * bit. Pushing false = *2, pushing true = *2+1, popping = /2. - */ - private int arrayStack; - - private String separator = ""; - - public TraceSignatureVisitor(final int access) { - super(Opcodes.ASM5); - isInterface = (access & Opcodes.ACC_INTERFACE) != 0; - this.declaration = new StringBuffer(); - } - - private TraceSignatureVisitor(final StringBuffer buf) { - super(Opcodes.ASM5); - this.declaration = buf; - } - - @Override - public void visitFormalTypeParameter(final String name) { - declaration.append(seenFormalParameter ? ", " : "<").append(name); - seenFormalParameter = true; - seenInterfaceBound = false; - } - - @Override - public SignatureVisitor visitClassBound() { - separator = " extends "; - startType(); - return this; - } - - @Override - public SignatureVisitor visitInterfaceBound() { - separator = seenInterfaceBound ? ", " : " extends "; - seenInterfaceBound = true; - startType(); - return this; - } - - @Override - public SignatureVisitor visitSuperclass() { - endFormals(); - separator = " extends "; - startType(); - return this; - } - - @Override - public SignatureVisitor visitInterface() { - separator = seenInterface ? ", " : isInterface ? " extends " - : " implements "; - seenInterface = true; - startType(); - return this; - } - - @Override - public SignatureVisitor visitParameterType() { - endFormals(); - if (seenParameter) { - declaration.append(", "); - } else { - seenParameter = true; - declaration.append('('); - } - startType(); - return this; - } - - @Override - public SignatureVisitor visitReturnType() { - endFormals(); - if (seenParameter) { - seenParameter = false; - } else { - declaration.append('('); - } - declaration.append(')'); - returnType = new StringBuffer(); - return new TraceSignatureVisitor(returnType); - } - - @Override - public SignatureVisitor visitExceptionType() { - if (exceptions == null) { - exceptions = new StringBuffer(); - } else { - exceptions.append(", "); - } - // startType(); - return new TraceSignatureVisitor(exceptions); - } - - @Override - public void visitBaseType(final char descriptor) { - switch (descriptor) { - case 'V': - declaration.append("void"); - break; - case 'B': - declaration.append("byte"); - break; - case 'J': - declaration.append("long"); - break; - case 'Z': - declaration.append("boolean"); - break; - case 'I': - declaration.append("int"); - break; - case 'S': - declaration.append("short"); - break; - case 'C': - declaration.append("char"); - break; - case 'F': - declaration.append("float"); - break; - // case 'D': - default: - declaration.append("double"); - break; - } - endType(); - } - - @Override - public void visitTypeVariable(final String name) { - declaration.append(name); - endType(); - } - - @Override - public SignatureVisitor visitArrayType() { - startType(); - arrayStack |= 1; - return this; - } - - @Override - public void visitClassType(final String name) { - if ("java/lang/Object".equals(name)) { - // Map<java.lang.Object,java.util.List> - // or - // abstract public V get(Object key); (seen in Dictionary.class) - // should have Object - // but java.lang.String extends java.lang.Object is unnecessary - boolean needObjectClass = argumentStack % 2 != 0 || seenParameter; - if (needObjectClass) { - declaration.append(separator).append(name.replace('/', '.')); - } - } else { - declaration.append(separator).append(name.replace('/', '.')); - } - separator = ""; - argumentStack *= 2; - } - - @Override - public void visitInnerClassType(final String name) { - if (argumentStack % 2 != 0) { - declaration.append('>'); - } - argumentStack /= 2; - declaration.append('.'); - declaration.append(separator).append(name.replace('/', '.')); - separator = ""; - argumentStack *= 2; - } - - @Override - public void visitTypeArgument() { - if (argumentStack % 2 == 0) { - ++argumentStack; - declaration.append('<'); - } else { - declaration.append(", "); - } - declaration.append('?'); - } - - @Override - public SignatureVisitor visitTypeArgument(final char tag) { - if (argumentStack % 2 == 0) { - ++argumentStack; - declaration.append('<'); - } else { - declaration.append(", "); - } - - if (tag == EXTENDS) { - declaration.append("? extends "); - } else if (tag == SUPER) { - declaration.append("? super "); - } - - startType(); - return this; - } - - @Override - public void visitEnd() { - if (argumentStack % 2 != 0) { - declaration.append('>'); - } - argumentStack /= 2; - endType(); - } - - public String getDeclaration() { - return declaration.toString(); - } - - public String getReturnType() { - return returnType == null ? null : returnType.toString(); - } - - public String getExceptions() { - return exceptions == null ? null : exceptions.toString(); - } - - // ----------------------------------------------- - - private void endFormals() { - if (seenFormalParameter) { - declaration.append('>'); - seenFormalParameter = false; - } - } - - private void startType() { - arrayStack *= 2; - } - - private void endType() { - if (arrayStack % 2 == 0) { - arrayStack /= 2; - } else { - while (arrayStack % 2 != 0) { - arrayStack /= 2; - declaration.append("[]"); - } - } - } -} diff --git a/src/compiler/scala/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/reflect/quasiquotes/Reifiers.scala index 7c0e7dfbb8..e753c9787a 100644 --- a/src/compiler/scala/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/reflect/quasiquotes/Reifiers.scala @@ -317,7 +317,7 @@ trait Reifiers { self: Quasiquotes => * Reification of non-trivial list is done in two steps: * * 1. split the list into groups where every placeholder is always - * put in a group of it's own and all subsquent non-holeMap are + * put in a group of its own and all subsquent non-holeMap are * grouped together; element is considered to be a placeholder if it's * in the domain of the fill function; * diff --git a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl index 9862ea7987..6e91a2a202 100755 --- a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl +++ b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl @@ -137,8 +137,8 @@ while [[ $# -gt 0 ]]; do -D*) # pass to scala as well: otherwise we lose it sometimes when we # need it, e.g. communicating with a server compiler. - java_args=("${java_args[@@]}" "$1") - scala_args=("${scala_args[@@]}" "$1") + java_args+=("$1") + scala_args+=("$1") # respect user-supplied -Dscala.usejavacp case "$1" in -Dscala.usejavacp*) OVERRIDE_USEJAVACP="";; esac shift @@ -146,8 +146,8 @@ while [[ $# -gt 0 ]]; do -J*) # as with -D, pass to scala even though it will almost # never be used. - java_args=("${java_args[@@]}" "${1:2}") - scala_args=("${scala_args[@@]}" "$1") + java_args+=("${1:2}") + scala_args+=("$1") shift ;; -toolcp) @@ -167,7 +167,7 @@ while [[ $# -gt 0 ]]; do shift ;; *) - scala_args=("${scala_args[@@]}" "$1") + scala_args+=("$1") shift ;; esac diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index b233acf271..4430a84f06 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -10,7 +10,6 @@ package nsc import java.io.{ File, FileOutputStream, PrintWriter, IOException, FileNotFoundException } import java.net.URL import java.nio.charset.{ Charset, CharsetDecoder, IllegalCharsetNameException, UnsupportedCharsetException } -import scala.compat.Platform.currentTime import scala.collection.{ mutable, immutable } import io.{ SourceReader, AbstractFile, Path } import reporters.{ Reporter, ConsoleReporter } @@ -1487,6 +1486,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) compileUnitsInternal(units, fromPhase) private def compileUnitsInternal(units: List[CompilationUnit], fromPhase: Phase) { + def currentTime = java.util.concurrent.TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) + units foreach addUnit val startTime = currentTime diff --git a/src/compiler/scala/tools/nsc/PhaseAssembly.scala b/src/compiler/scala/tools/nsc/PhaseAssembly.scala index e1cfa63960..4b32aab5ee 100644 --- a/src/compiler/scala/tools/nsc/PhaseAssembly.scala +++ b/src/compiler/scala/tools/nsc/PhaseAssembly.scala @@ -127,7 +127,7 @@ trait PhaseAssembly { } /* Find all edges in the given graph that are hard links. For each hard link we - * need to check that its the only dependency. If not, then we will promote the + * need to check that it's the only dependency. If not, then we will promote the * other dependencies down */ def validateAndEnforceHardlinks() { diff --git a/src/compiler/scala/tools/nsc/Reporting.scala b/src/compiler/scala/tools/nsc/Reporting.scala index 72a4b69536..4e7a527a5a 100644 --- a/src/compiler/scala/tools/nsc/Reporting.scala +++ b/src/compiler/scala/tools/nsc/Reporting.scala @@ -46,7 +46,7 @@ trait Reporting extends scala.reflect.internal.Reporting { self: ast.Positions w private val _deprecationWarnings = new ConditionalWarning("deprecation", settings.deprecation)() private val _uncheckedWarnings = new ConditionalWarning("unchecked", settings.unchecked)() private val _featureWarnings = new ConditionalWarning("feature", settings.feature)() - private val _inlinerWarnings = new ConditionalWarning("inliner", settings.YinlinerWarnings)(if (settings.isBCodeAskedFor) settings.YoptWarnings.name else settings.YinlinerWarnings.name) + private val _inlinerWarnings = new ConditionalWarning("inliner", settings.YinlinerWarnings)(if (settings.isBCodeActive) settings.YoptWarnings.name else settings.YinlinerWarnings.name) private val _allConditionalWarnings = List(_deprecationWarnings, _uncheckedWarnings, _featureWarnings, _inlinerWarnings) // TODO: remove in favor of the overload that takes a Symbol, give that argument a default (NoSymbol) diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala index 02a199f7ac..6442ef2d54 100755 --- a/src/compiler/scala/tools/nsc/ast/DocComments.scala +++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala @@ -76,9 +76,9 @@ trait DocComments { self: Global => superComment(sym) match { case None => - if (ownComment.indexOf("@inheritdoc") != -1) - reporter.warning(sym.pos, "The comment for " + sym + - " contains @inheritdoc, but no parent comment is available to inherit from.") + // SI-8210 - The warning would be false negative when this symbol is a setter + if (ownComment.indexOf("@inheritdoc") != -1 && ! sym.isSetter) + reporter.warning(sym.pos, s"The comment for ${sym} contains @inheritdoc, but no parent comment is available to inherit from.") ownComment.replaceAllLiterally("@inheritdoc", "<invalid inheritdoc annotation>") case Some(sc) => if (ownComment == "") sc diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala index 96939e616c..52b8a51a79 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala @@ -6,6 +6,7 @@ package scala.tools.nsc package ast.parser +import scala.annotation.tailrec import scala.collection.mutable import mutable.{ Buffer, ArrayBuffer, ListBuffer } import scala.util.control.ControlThrowable @@ -172,20 +173,19 @@ trait MarkupParsers { } def appendText(pos: Position, ts: Buffer[Tree], txt: String): Unit = { - def append(t: String) = ts append handle.text(pos, t) - - if (preserveWS) append(txt) - else { + def append(text: String): Unit = { + val tree = handle.text(pos, text) + ts append tree + } + val clean = if (preserveWS) txt else { val sb = new StringBuilder() - txt foreach { c => if (!isSpace(c)) sb append c else if (sb.isEmpty || !isSpace(sb.last)) sb append ' ' } - - val trimmed = sb.toString.trim - if (!trimmed.isEmpty) append(trimmed) + sb.toString.trim } + if (!clean.isEmpty) append(clean) } /** adds entity/character to ts as side-effect @@ -216,44 +216,75 @@ trait MarkupParsers { if (xCheckEmbeddedBlock) ts append xEmbeddedExpr else appendText(p, ts, xText) - /** Returns true if it encounters an end tag (without consuming it), - * appends trees to ts as side-effect. + /** At an open angle-bracket, detects an end tag + * or consumes CDATA, comment, PI or element. + * Trees are appended to `ts` as a side-effect. + * @return true if an end tag (without consuming it) */ - private def content_LT(ts: ArrayBuffer[Tree]): Boolean = { - if (ch == '/') - return true // end tag - - val toAppend = ch match { - case '!' => nextch() ; if (ch =='[') xCharData else xComment // CDATA or Comment - case '?' => nextch() ; xProcInstr // PI - case _ => element // child node + private def content_LT(ts: ArrayBuffer[Tree]): Boolean = + (ch == '/') || { + val toAppend = ch match { + case '!' => nextch() ; if (ch =='[') xCharData else xComment // CDATA or Comment + case '?' => nextch() ; xProcInstr // PI + case _ => element // child node + } + ts append toAppend + false } - ts append toAppend - false - } - def content: Buffer[Tree] = { val ts = new ArrayBuffer[Tree] - while (true) { - if (xEmbeddedBlock) + val coalescing = settings.XxmlSettings.isCoalescing + @tailrec def loopContent(): Unit = + if (xEmbeddedBlock) { ts append xEmbeddedExpr - else { + loopContent() + } else { tmppos = o2p(curOffset) ch match { - // end tag, cdata, comment, pi or child node - case '<' => nextch() ; if (content_LT(ts)) return ts - // either the character '{' or an embedded scala block } - case '{' => content_BRACE(tmppos, ts) // } - // EntityRef or CharRef - case '&' => content_AMP(ts) - case SU => return ts - // text content - here xEmbeddedBlock might be true - case _ => appendText(tmppos, ts, xText) + case '<' => // end tag, cdata, comment, pi or child node + nextch() + if (!content_LT(ts)) loopContent() + case '{' => // } literal brace or embedded Scala block + content_BRACE(tmppos, ts) + loopContent() + case '&' => // EntityRef or CharRef + content_AMP(ts) + loopContent() + case SU => () + case _ => // text content - here xEmbeddedBlock might be true + appendText(tmppos, ts, xText) + loopContent() } } + // merge text sections and strip attachments + def coalesce(): ArrayBuffer[Tree] = { + def copy() = { + val buf = new ArrayBuffer[Tree] + var acc = new StringBuilder + var pos: Position = NoPosition + def emit() = if (acc.nonEmpty) { + appendText(pos, buf, acc.toString) + acc.clear() + } + for (t <- ts) + t.attachments.get[handle.TextAttache] match { + case Some(ta) => + if (acc.isEmpty) pos = ta.pos + acc append ta.text + case _ => + emit() + buf += t + } + emit() + buf + } + val res = if (ts.count(_.hasAttachment[handle.TextAttache]) > 1) copy() else ts + for (t <- res) t.removeAttachment[handle.TextAttache] + res } - unreachable + loopContent() + if (coalescing) coalesce() else ts } /** '<' element ::= xmlTag1 '>' { xmlExpr | '{' simpleExpr '}' } ETag @@ -289,20 +320,16 @@ trait MarkupParsers { private def xText: String = { assert(!xEmbeddedBlock, "internal error: encountered embedded block") val buf = new StringBuilder - def done = buf.toString - - while (ch != SU) { - if (ch == '}') { - if (charComingAfter(nextch()) == '}') nextch() - else errorBraces() - } - - buf append ch - nextch() - if (xCheckEmbeddedBlock || ch == '<' || ch == '&') - return done - } - done + if (ch != SU) + do { + if (ch == '}') { + if (charComingAfter(nextch()) == '}') nextch() + else errorBraces() + } + buf append ch + nextch() + } while (!(ch == SU || xCheckEmbeddedBlock || ch == '<' || ch == '&')) + buf.toString } /** Some try/catch/finally logic used by xLiteral and xLiteralPattern. */ @@ -344,12 +371,12 @@ trait MarkupParsers { tmppos = o2p(curOffset) // Iuli: added this line, as it seems content_LT uses tmppos when creating trees content_LT(ts) - // parse more XML ? + // parse more XML? if (charComingAfter(xSpaceOpt()) == '<') { do { xSpaceOpt() nextch() - ts append element + content_LT(ts) } while (charComingAfter(xSpaceOpt()) == '<') handle.makeXMLseq(r2p(start, start, curOffset), ts) } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 67e91ae857..4f195c2985 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1259,7 +1259,7 @@ self => atPos(start) { Apply(t3, exprsBuf.toList) } } if (inPattern) stringCheese - else withPlaceholders(stringCheese, isAny = true) // strinterpolator params are Any* by definition + else withPlaceholders(stringCheese, isAny = true) // string interpolator params are Any* by definition } /* ------------- NEW LINES ------------------------------------------------- */ diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala index d2a999cdec..67241ef639 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala @@ -36,6 +36,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { val _MetaData: NameType = "MetaData" val _NamespaceBinding: NameType = "NamespaceBinding" val _NodeBuffer: NameType = "NodeBuffer" + val _PCData: NameType = "PCData" val _PrefixedAttribute: NameType = "PrefixedAttribute" val _ProcInstr: NameType = "ProcInstr" val _Text: NameType = "Text" @@ -46,6 +47,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { private object xmlterms extends TermNames { val _Null: NameType = "Null" val __Elem: NameType = "Elem" + val _PCData: NameType = "PCData" val __Text: NameType = "Text" val _buf: NameType = "$buf" val _md: NameType = "$md" @@ -55,10 +57,15 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { val _xml: NameType = "xml" } - import xmltypes.{_Comment, _Elem, _EntityRef, _Group, _MetaData, _NamespaceBinding, _NodeBuffer, - _PrefixedAttribute, _ProcInstr, _Text, _Unparsed, _UnprefixedAttribute} + import xmltypes.{ + _Comment, _Elem, _EntityRef, _Group, _MetaData, _NamespaceBinding, _NodeBuffer, + _PCData, _PrefixedAttribute, _ProcInstr, _Text, _Unparsed, _UnprefixedAttribute + } + + import xmlterms.{ _Null, __Elem, __Text, _buf, _md, _plus, _scope, _tmpscope, _xml } - import xmlterms.{_Null, __Elem, __Text, _buf, _md, _plus, _scope, _tmpscope, _xml} + /** Attachment for trees deriving from text nodes (Text, CData, entities). Used for coalescing. */ + case class TextAttache(pos: Position, text: String) // convenience methods private def LL[A](x: A*): List[List[A]] = List(List(x:_*)) @@ -108,16 +115,21 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { final def entityRef(pos: Position, n: String) = atPos(pos)( New(_scala_xml_EntityRef, LL(const(n))) ) + private def coalescing = settings.XxmlSettings.isCoalescing + // create scala.xml.Text here <: scala.xml.Node final def text(pos: Position, txt: String): Tree = atPos(pos) { - if (isPattern) makeTextPat(const(txt)) - else makeText1(const(txt)) + val t = if (isPattern) makeTextPat(const(txt)) else makeText1(const(txt)) + if (coalescing) t updateAttachment TextAttache(pos, txt) else t } def makeTextPat(txt: Tree) = Apply(_scala_xml__Text, List(txt)) def makeText1(txt: Tree) = New(_scala_xml_Text, LL(txt)) def comment(pos: Position, text: String) = atPos(pos)( Comment(const(text)) ) - def charData(pos: Position, txt: String) = atPos(pos)( makeText1(const(txt)) ) + def charData(pos: Position, txt: String) = if (coalescing) text(pos, txt) else atPos(pos) { + if (isPattern) Apply(_scala_xml(xmlterms._PCData), List(const(txt))) + else New(_scala_xml(_PCData), LL(const(txt))) + } def procInstr(pos: Position, target: String, txt: String) = atPos(pos)( ProcInstr(const(target), const(txt)) ) diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 185fd93501..137954b52d 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -883,7 +883,12 @@ abstract class GenICode extends SubComponent { case None => val saved = settings.uniqid settings.uniqid.value = true - try abort(s"symbol $sym does not exist in ${ctx.method}, which contains locals ${ctx.method.locals.mkString(",")}") + try { + val methodCode = unit.body.collect { case dd: DefDef + if dd.symbol == ctx.method.symbol => showCode(dd); + }.headOption.getOrElse("<unknown>") + abort(s"symbol $sym does not exist in ${ctx.method}, which contains locals ${ctx.method.locals.mkString(",")}. \nMethod code: $methodCode") + } finally settings.uniqid.value = saved } } diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala index 0cdf629ce1..843648282b 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala @@ -109,7 +109,7 @@ abstract class ICodeCheckers { /** Only called when m1 < m2, so already known that (m1 ne m2). */ - private def isConfict(m1: IMember, m2: IMember, canOverload: Boolean) = ( + private def isConflict(m1: IMember, m2: IMember, canOverload: Boolean) = ( (m1.symbol.name == m2.symbol.name) && (!canOverload || (m1.symbol.tpe =:= m2.symbol.tpe)) ) @@ -119,11 +119,11 @@ abstract class ICodeCheckers { clasz = cls for (f1 <- cls.fields ; f2 <- cls.fields ; if f1 < f2) - if (isConfict(f1, f2, canOverload = false)) + if (isConflict(f1, f2, canOverload = false)) icodeError("Repetitive field name: " + f1.symbol.fullName) for (m1 <- cls.methods ; m2 <- cls.methods ; if m1 < m2) - if (isConfict(m1, m2, canOverload = true)) + if (isConflict(m1, m2, canOverload = true)) icodeError("Repetitive method: " + m1.symbol.fullName) clasz.methods foreach check @@ -471,7 +471,7 @@ abstract class ICodeCheckers { pushStack(local.kind) case LOAD_FIELD(field, isStatic) => - // the symbol's owner should contain it's field, but + // the symbol's owner should contain its field, but // this is already checked by the type checker, no need // to redo that here if (isStatic) () diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala index b0ad5bdaf9..058b6a161d 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala @@ -572,7 +572,7 @@ abstract class TypeFlowAnalysis { - `inlined` : These blocks were spliced into the method's CFG as part of inlining. Being new blocks, they haven't been visited yet by the typeflow analysis. - - `staleIn` : These blocks are what `doInline()` calls `afterBlock`s, ie the new home for instructions that previously appearead + - `staleIn` : These blocks are what `doInline()` calls `afterBlock`s, ie the new home for instructions that previously appeared after a callsite in a `staleOut` block. Based on the above information, we have to bring up-to-date the caches that `forwardAnalysis` and `blockTransfer` use to skip blocks and instructions. diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala index 162da4236a..eadc404bee 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala @@ -329,10 +329,12 @@ final class BCodeAsmCommon[G <: Global](val global: G) { * Build the [[InlineInfo]] for a class symbol. */ def buildInlineInfoFromClassSymbol(classSym: Symbol, classSymToInternalName: Symbol => InternalName, methodSymToDescriptor: Symbol => String): InlineInfo = { - val selfType = { + val traitSelfType = if (classSym.isTrait && !classSym.isImplClass) { // The mixin phase uses typeOfThis for the self parameter in implementation class methods. val selfSym = classSym.typeOfThis.typeSymbol if (selfSym != classSym) Some(classSymToInternalName(selfSym)) else None + } else { + None } val isEffectivelyFinal = classSym.isEffectivelyFinal @@ -394,6 +396,6 @@ final class BCodeAsmCommon[G <: Global](val global: G) { } }).toMap - InlineInfo(selfType, isEffectivelyFinal, methodInlineInfos, warning) + InlineInfo(traitSelfType, isEffectivelyFinal, methodInlineInfos, warning) } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 15b014bdd3..40ba0c010b 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -10,6 +10,7 @@ package backend package jvm import scala.annotation.switch +import scala.reflect.internal.Flags import scala.tools.asm import GenBCode._ @@ -32,7 +33,6 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { * Functionality to build the body of ASM MethodNode, except for `synchronized` and `try` expressions. */ abstract class PlainBodyBuilder(cunit: CompilationUnit) extends PlainSkelBuilder(cunit) { - import icodes.TestOp import icodes.opcodes.InvokeStyle @@ -632,6 +632,10 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { case _ => abort(s"Cannot instantiate $tpt of kind: $generatedType") } + case Apply(_, args) if app.hasAttachment[delambdafy.LambdaMetaFactoryCapable] => + val attachment = app.attachments.get[delambdafy.LambdaMetaFactoryCapable].get + genLoadArguments(args, paramTKs(app)) + genInvokeDynamicLambda(attachment.target, attachment.arity, attachment.functionalInterface) case Apply(fun @ _, List(expr)) if currentRun.runDefinitions.isBox(fun.symbol) => val nativeKind = tpeTK(expr) @@ -1280,6 +1284,44 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { def genSynchronized(tree: Apply, expectedType: BType): BType def genLoadTry(tree: Try): BType + def genInvokeDynamicLambda(lambdaTarget: Symbol, arity: Int, functionalInterface: Symbol) { + val isStaticMethod = lambdaTarget.hasFlag(Flags.STATIC) + def asmType(sym: Symbol) = classBTypeFromSymbol(sym).toASMType + + val implMethodHandle = + new asm.Handle(if (lambdaTarget.hasFlag(Flags.STATIC)) asm.Opcodes.H_INVOKESTATIC else asm.Opcodes.H_INVOKEVIRTUAL, + classBTypeFromSymbol(lambdaTarget.owner).internalName, + lambdaTarget.name.toString, + asmMethodType(lambdaTarget).descriptor) + val receiver = if (isStaticMethod) Nil else lambdaTarget.owner :: Nil + val (capturedParams, lambdaParams) = lambdaTarget.paramss.head.splitAt(lambdaTarget.paramss.head.length - arity) + // Requires https://github.com/scala/scala-java8-compat on the runtime classpath + val invokedType = asm.Type.getMethodDescriptor(asmType(functionalInterface), (receiver ::: capturedParams).map(sym => toTypeKind(sym.info).toASMType): _*) + + val constrainedType = new MethodBType(lambdaParams.map(p => toTypeKind(p.tpe)), toTypeKind(lambdaTarget.tpe.resultType)).toASMType + val sam = functionalInterface.info.decls.find(_.isDeferred).getOrElse(functionalInterface.info.member(nme.apply)) + val samName = sam.name.toString + val samMethodType = asmMethodType(sam).toASMType + + val flags = 3 // TODO 2.12.x Replace with LambdaMetafactory.FLAG_SERIALIZABLE | LambdaMetafactory.FLAG_MARKERS + + val ScalaSerializable = classBTypeFromSymbol(definitions.SerializableClass).toASMType + bc.jmethod.visitInvokeDynamicInsn(samName, invokedType, lambdaMetaFactoryBootstrapHandle, + /* samMethodType = */ samMethodType, + /* implMethod = */ implMethodHandle, + /* instantiatedMethodType = */ constrainedType, + /* flags = */ flags.asInstanceOf[AnyRef], + /* markerInterfaceCount = */ 1.asInstanceOf[AnyRef], + /* markerInterfaces[0] = */ ScalaSerializable, + /* bridgeCount = */ 0.asInstanceOf[AnyRef] + ) + indyLambdaHosts += this.claszSymbol + } } + lazy val lambdaMetaFactoryBootstrapHandle = + new asm.Handle(asm.Opcodes.H_INVOKESTATIC, + definitions.LambdaMetaFactory.fullName('/'), sn.AltMetafactory.toString, + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;") + } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index 18468f5ae3..6aa3a62295 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -682,6 +682,59 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { new java.lang.Long(id) ).visitEnd() } + + /** + * Add: + * private static java.util.Map $deserializeLambdaCache$ = null + * private static Object $deserializeLambda$(SerializedLambda l) { + * var cache = $deserializeLambdaCache$ + * if (cache eq null) { + * cache = new java.util.HashMap() + * $deserializeLambdaCache$ = cache + * } + * return scala.compat.java8.runtime.LambdaDeserializer.deserializeLambda(MethodHandles.lookup(), cache, l); + * } + */ + def addLambdaDeserialize(clazz: Symbol, jclass: asm.ClassVisitor): Unit = { + val cw = jclass + import scala.tools.asm.Opcodes._ + + // Need to force creation of BTypes for these as `getCommonSuperClass` is called on + // automatically computing the max stack size (`visitMaxs`) during method writing. + javaUtilHashMapReference + javaUtilMapReference + + cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", ACC_PUBLIC + ACC_FINAL + ACC_STATIC) + + { + val fv = cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$deserializeLambdaCache$", "Ljava/util/Map;", null, null) + fv.visitEnd() + } + + { + val mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$deserializeLambda$", "(Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;", null, null) + mv.visitCode() + mv.visitFieldInsn(GETSTATIC, clazz.javaBinaryName.encoded, "$deserializeLambdaCache$", "Ljava/util/Map;") + mv.visitVarInsn(ASTORE, 1) + mv.visitVarInsn(ALOAD, 1) + val l0 = new asm.Label() + mv.visitJumpInsn(IFNONNULL, l0) + mv.visitTypeInsn(NEW, "java/util/HashMap") + mv.visitInsn(DUP) + mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V", false) + mv.visitVarInsn(ASTORE, 1) + mv.visitVarInsn(ALOAD, 1) + mv.visitFieldInsn(PUTSTATIC, clazz.javaBinaryName.encoded, "$deserializeLambdaCache$", "Ljava/util/Map;") + mv.visitLabel(l0) + mv.visitFrame(asm.Opcodes.F_APPEND,1, Array("java/util/Map"), 0, null) + mv.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;", false) + mv.visitVarInsn(ALOAD, 1) + mv.visitVarInsn(ALOAD, 0) + mv.visitMethodInsn(INVOKESTATIC, "scala/compat/java8/runtime/LambdaDeserializer", "deserializeLambda", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/util/Map;Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;", false) + mv.visitInsn(ARETURN) + mv.visitEnd() + } + } } // end of trait BCClassGen /* functionality for building plain and mirror classes */ diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala index 9993357eee..8f2a17a2bf 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala @@ -412,6 +412,9 @@ abstract class BCodeIdiomatic extends SubComponent { jmethod.instructions.add(node) if (settings.YoptInlinerEnabled) callsitePositions(node) = pos } + final def invokedynamic(owner: String, name: String, desc: String) { + jmethod.visitMethodInsn(Opcodes.INVOKEDYNAMIC, owner, name, desc) + } // can-multi-thread final def goTo(label: asm.Label) { jmethod.visitJumpInsn(Opcodes.GOTO, label) } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala index 2a06c62e37..a2fd22d24c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala @@ -68,6 +68,8 @@ abstract class BCodeSkelBuilder extends BCodeHelpers { var isCZStaticModule = false var isCZRemote = false + protected val indyLambdaHosts = collection.mutable.Set[Symbol]() + /* ---------------- idiomatic way to ask questions to typer ---------------- */ def paramTKs(app: Apply): List[BType] = { @@ -121,6 +123,16 @@ abstract class BCodeSkelBuilder extends BCodeHelpers { innerClassBufferASM ++= classBType.info.get.nestedClasses gen(cd.impl) + + + val shouldAddLambdaDeserialize = ( + settings.target.value == "jvm-1.8" + && settings.Ydelambdafy.value == "method" + && indyLambdaHosts.contains(claszSymbol)) + + if (shouldAddLambdaDeserialize) + addLambdaDeserialize(claszSymbol, cnode) + addInnerClassesASM(cnode, innerClassBufferASM.toList) cnode.visitAttribute(classBType.inlineInfoAttribute.get) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala index d8a17e975e..e61190bf3a 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala @@ -11,11 +11,12 @@ import scala.collection.concurrent.TrieMap import scala.reflect.internal.util.Position import scala.tools.asm import asm.Opcodes -import scala.tools.asm.tree.{MethodInsnNode, InnerClassNode, ClassNode} +import scala.tools.asm.tree.{MethodNode, MethodInsnNode, InnerClassNode, ClassNode} import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, MethodInlineInfo} import scala.tools.nsc.backend.jvm.BackendReporting._ import scala.tools.nsc.backend.jvm.opt._ import scala.collection.convert.decorateAsScala._ +import scala.tools.nsc.settings.ScalaSettings /** * The BTypes component defines The BType class hierarchy. A BType stores all type information @@ -39,6 +40,8 @@ abstract class BTypes { */ val byteCodeRepository: ByteCodeRepository + val localOpt: LocalOpt[this.type] + val inliner: Inliner[this.type] val callGraph: CallGraph[this.type] @@ -48,14 +51,9 @@ abstract class BTypes { // Allows to define per-run caches here and in the CallGraph component, which don't have a global def recordPerRunCache[T <: collection.generic.Clearable](cache: T): T - // When building the call graph, we need to know if global inlining is allowed (the component doesn't have a global) - def inlineGlobalEnabled: Boolean - - // When the inliner is not enabled, there's no point in adding InlineInfos to all ClassBTypes - def inlinerEnabled: Boolean + // Allows access to the compiler settings for backend components that don't have a global in scope + def compilerSettings: ScalaSettings - // Settings that define what kind of optimizer warnings are emitted. - def warnSettings: WarnSettings /** * A map from internal names to ClassBTypes. Every ClassBType is added to this map on its @@ -83,6 +81,18 @@ abstract class BTypes { val javaDefinedClasses: collection.mutable.Set[InternalName] = recordPerRunCache(collection.mutable.Set.empty) /** + * Cache, contains methods whose unreachable instructions are eliminated. + * + * The ASM Analyzer class does not compute any frame information for unreachable instructions. + * Transformations that use an analyzer (including inlining) therefore require unreachable code + * to be eliminated. + * + * This cache allows running dead code elimination whenever an analyzer is used. If the method + * is already optimized, DCE can return early. + */ + val unreachableCodeEliminated: collection.mutable.Set[MethodNode] = recordPerRunCache(collection.mutable.Set.empty) + + /** * Obtain the BType for a type descriptor or internal name. For class descriptors, the ClassBType * is constructed by parsing the corresponding classfile. * @@ -229,7 +239,7 @@ abstract class BTypes { // The InlineInfo is built from the classfile (not from the symbol) for all classes that are NOT // being compiled. For those classes, the info is only needed if the inliner is enabled, othewise // we can save the memory. - if (!inlinerEnabled) BTypes.EmptyInlineInfo + if (!compilerSettings.YoptInlinerEnabled) BTypes.EmptyInlineInfo else fromClassfileAttribute getOrElse fromClassfileWithoutAttribute } @@ -305,7 +315,7 @@ abstract class BTypes { case ArrayBType(component) => if (other == ObjectReference || other == jlCloneableReference || other == jioSerializableReference) true else other match { - case ArrayBType(otherComponoent) => component.conformsTo(otherComponoent).orThrow + case ArrayBType(otherComponent) => component.conformsTo(otherComponent).orThrow case _ => false } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index eeb6ed24a2..1b9fd5e298 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -7,9 +7,10 @@ package scala.tools.nsc package backend.jvm import scala.tools.asm -import scala.tools.nsc.backend.jvm.opt.{CallGraph, Inliner, ByteCodeRepository} +import scala.tools.nsc.backend.jvm.opt.{LocalOpt, CallGraph, Inliner, ByteCodeRepository} import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, MethodInlineInfo, InternalName} import BackendReporting._ +import scala.tools.nsc.settings.ScalaSettings /** * This class mainly contains the method classBTypeFromSymbol, which extracts the necessary @@ -37,6 +38,8 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { val byteCodeRepository = new ByteCodeRepository(global.classPath, javaDefinedClasses, recordPerRunCache(collection.concurrent.TrieMap.empty)) + val localOpt: LocalOpt[this.type] = new LocalOpt(this) + val inliner: Inliner[this.type] = new Inliner(this) val callGraph: CallGraph[this.type] = new CallGraph(this) @@ -49,19 +52,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { def recordPerRunCache[T <: collection.generic.Clearable](cache: T): T = perRunCaches.recordCache(cache) - def inlineGlobalEnabled: Boolean = settings.YoptInlineGlobal - - def inlinerEnabled: Boolean = settings.YoptInlinerEnabled - - def warnSettings: WarnSettings = { - val c = settings.YoptWarningsChoices - // cannot extract settings.YoptWarnings into a local val due to some dependent typing issue. - WarnSettings( - !settings.YoptWarnings.isSetByUser || settings.YoptWarnings.contains(c.atInlineFailedSummary.name) || settings.YoptWarnings.contains(c.atInlineFailed.name), - settings.YoptWarnings.contains(c.noInlineMixed.name), - settings.YoptWarnings.contains(c.noInlineMissingBytecode.name), - settings.YoptWarnings.contains(c.noInlineMissingScalaInlineInfoAttr.name)) - } + def compilerSettings: ScalaSettings = settings // helpers that need access to global. // TODO @lry create a separate component, they don't belong to BTypesFromSymbols @@ -418,8 +409,8 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { // phase travel required, see implementation of `compiles`. for nested classes, it checks if the // enclosingTopLevelClass is being compiled. after flatten, all classes are considered top-level, // so `compiles` would return `false`. - if (exitingPickler(currentRun.compiles(classSym))) buildFromSymbol // InlineInfo required for classes being compiled, we have to create the classfile attribute - else if (!inlinerEnabled) BTypes.EmptyInlineInfo // For other classes, we need the InlineInfo only inf the inliner is enabled. + if (exitingPickler(currentRun.compiles(classSym))) buildFromSymbol // InlineInfo required for classes being compiled, we have to create the classfile attribute + else if (!compilerSettings.YoptInlinerEnabled) BTypes.EmptyInlineInfo // For other classes, we need the InlineInfo only inf the inliner is enabled. else { // For classes not being compiled, the InlineInfo is read from the classfile attribute. This // fixes an issue with mixed-in methods: the mixin phase enters mixin methods only to class diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala b/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala index a06fb4bab8..d641f708d2 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala @@ -4,6 +4,8 @@ package backend.jvm import scala.tools.asm.tree.{AbstractInsnNode, MethodNode} import scala.tools.nsc.backend.jvm.BTypes.InternalName import scala.reflect.internal.util.Position +import scala.tools.nsc.settings.ScalaSettings +import scala.util.control.ControlThrowable /** * Interface for emitting inline warnings. The interface is required because the implementation @@ -73,24 +75,22 @@ object BackendReporting { } } - case class Invalid[A](e: A) extends Exception + case class Invalid[A](e: A) extends ControlThrowable /** * See documentation of orThrow above. */ def tryEither[A, B](op: => Either[A, B]): Either[A, B] = try { op } catch { case Invalid(e) => Left(e.asInstanceOf[A]) } - final case class WarnSettings(atInlineFailed: Boolean, noInlineMixed: Boolean, noInlineMissingBytecode: Boolean, noInlineMissingScalaInlineInfoAttr: Boolean) - sealed trait OptimizerWarning { - def emitWarning(settings: WarnSettings): Boolean + def emitWarning(settings: ScalaSettings): Boolean } // Method filter in RightBiasedEither requires an implicit empty value. Taking the value here // in scope allows for-comprehensions that desugar into filter calls (for example when using a // tuple de-constructor). implicit object emptyOptimizerWarning extends OptimizerWarning { - def emitWarning(settings: WarnSettings): Boolean = false + def emitWarning(settings: ScalaSettings): Boolean = false } sealed trait MissingBytecodeWarning extends OptimizerWarning { @@ -112,17 +112,17 @@ object BackendReporting { missingClass.map(c => s" Reason:\n$c").getOrElse("") } - def emitWarning(settings: WarnSettings): Boolean = this match { + def emitWarning(settings: ScalaSettings): Boolean = this match { case ClassNotFound(_, javaDefined) => - if (javaDefined) settings.noInlineMixed - else settings.noInlineMissingBytecode + if (javaDefined) settings.YoptWarningNoInlineMixed + else settings.YoptWarningNoInlineMissingBytecode case m @ MethodNotFound(_, _, _, missing) => if (m.isArrayMethod) false - else settings.noInlineMissingBytecode || missing.exists(_.emitWarning(settings)) + else settings.YoptWarningNoInlineMissingBytecode || missing.exists(_.emitWarning(settings)) case FieldNotFound(_, _, _, missing) => - settings.noInlineMissingBytecode || missing.exists(_.emitWarning(settings)) + settings.YoptWarningNoInlineMissingBytecode || missing.exists(_.emitWarning(settings)) } } @@ -141,9 +141,9 @@ object BackendReporting { s"Failed to get the type of class symbol $classFullName due to SI-9111." } - def emitWarning(settings: WarnSettings): Boolean = this match { + def emitWarning(settings: ScalaSettings): Boolean = this match { case NoClassBTypeInfoMissingBytecode(cause) => cause.emitWarning(settings) - case NoClassBTypeInfoClassSymbolInfoFailedSI9111(_) => settings.noInlineMissingBytecode + case NoClassBTypeInfoClassSymbolInfoFailedSI9111(_) => settings.YoptWarningNoInlineMissingBytecode } } @@ -175,11 +175,11 @@ object BackendReporting { cause.toString } - def emitWarning(settings: WarnSettings): Boolean = this match { + def emitWarning(settings: ScalaSettings): Boolean = this match { case MethodInlineInfoIncomplete(_, _, _, cause) => cause.emitWarning(settings) case MethodInlineInfoMissing(_, _, _, Some(cause)) => cause.emitWarning(settings) - case MethodInlineInfoMissing(_, _, _, None) => settings.noInlineMissingBytecode + case MethodInlineInfoMissing(_, _, _, None) => settings.YoptWarningNoInlineMissingBytecode case MethodInlineInfoError(_, _, _, cause) => cause.emitWarning(settings) @@ -214,11 +214,21 @@ object BackendReporting { case SynchronizedMethod(_, _, _) => s"Method $calleeMethodSig cannot be inlined because it is synchronized." + + case StrictfpMismatch(_, _, _, callsiteClass, callsiteName, callsiteDesc) => + s"""The callsite method ${BackendReporting.methodSignature(callsiteClass, callsiteName, callsiteDesc)} + |does not have the same strictfp mode as the callee $calleeMethodSig. + """.stripMargin + + case ResultingMethodTooLarge(_, _, _, callsiteClass, callsiteName, callsiteDesc) => + s"""The size of the callsite method ${BackendReporting.methodSignature(callsiteClass, callsiteName, callsiteDesc)} + |would exceed the JVM method size limit after inlining $calleeMethodSig. + """.stripMargin } - def emitWarning(settings: WarnSettings): Boolean = this match { - case _: IllegalAccessInstruction | _: MethodWithHandlerCalledOnNonEmptyStack | _: SynchronizedMethod => - settings.atInlineFailed + def emitWarning(settings: ScalaSettings): Boolean = this match { + case _: IllegalAccessInstruction | _: MethodWithHandlerCalledOnNonEmptyStack | _: SynchronizedMethod | _: StrictfpMismatch | _: ResultingMethodTooLarge => + settings.YoptWarningEmitAtInlineFailed case IllegalAccessCheckFailed(_, _, _, _, _, cause) => cause.emitWarning(settings) @@ -231,6 +241,10 @@ object BackendReporting { case class MethodWithHandlerCalledOnNonEmptyStack(calleeDeclarationClass: InternalName, name: String, descriptor: String, callsiteClass: InternalName, callsiteName: String, callsiteDesc: String) extends CannotInlineWarning case class SynchronizedMethod(calleeDeclarationClass: InternalName, name: String, descriptor: String) extends CannotInlineWarning + case class StrictfpMismatch(calleeDeclarationClass: InternalName, name: String, descriptor: String, + callsiteClass: InternalName, callsiteName: String, callsiteDesc: String) extends CannotInlineWarning + case class ResultingMethodTooLarge(calleeDeclarationClass: InternalName, name: String, descriptor: String, + callsiteClass: InternalName, callsiteName: String, callsiteDesc: String) extends CannotInlineWarning /** * Used in the InlineInfo of a ClassBType, when some issue occurred obtaining the inline information. @@ -250,11 +264,11 @@ object BackendReporting { s"Cannot read ScalaInlineInfo version $version in classfile $internalName. Use a more recent compiler." } - def emitWarning(settings: WarnSettings): Boolean = this match { - case NoInlineInfoAttribute(_) => settings.noInlineMissingScalaInlineInfoAttr + def emitWarning(settings: ScalaSettings): Boolean = this match { + case NoInlineInfoAttribute(_) => settings.YoptWarningNoInlineMissingScalaInlineInfoAttr case ClassNotFoundWhenBuildingInlineInfoFromSymbol(cause) => cause.emitWarning(settings) - case ClassSymbolInfoFailureSI9111(_) => settings.noInlineMissingBytecode - case UnknownScalaInlineInfoVersion(_, _) => settings.noInlineMissingScalaInlineInfoAttr + case ClassSymbolInfoFailureSI9111(_) => settings.YoptWarningNoInlineMissingBytecode + case UnknownScalaInlineInfoVersion(_, _) => settings.YoptWarningNoInlineMissingScalaInlineInfoAttr } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala index 492fe3ae79..00ca096e59 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala @@ -114,6 +114,8 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { lazy val jioSerializableReference : ClassBType = classBTypeFromSymbol(JavaSerializableClass) // java/io/Serializable lazy val scalaSerializableReference : ClassBType = classBTypeFromSymbol(SerializableClass) // scala/Serializable lazy val classCastExceptionReference : ClassBType = classBTypeFromSymbol(ClassCastExceptionClass) // java/lang/ClassCastException + lazy val javaUtilMapReference : ClassBType = classBTypeFromSymbol(JavaUtilMap) // java/util/Map + lazy val javaUtilHashMapReference : ClassBType = classBTypeFromSymbol(JavaUtilHashMap) // java/util/HashMap lazy val srBooleanRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.BooleanRef]) lazy val srByteRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.ByteRef]) @@ -258,6 +260,8 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: def jioSerializableReference : ClassBType = _coreBTypes.jioSerializableReference def scalaSerializableReference : ClassBType = _coreBTypes.scalaSerializableReference def classCastExceptionReference : ClassBType = _coreBTypes.classCastExceptionReference + def javaUtilMapReference : ClassBType = _coreBTypes.javaUtilMapReference + def javaUtilHashMapReference : ClassBType = _coreBTypes.javaUtilHashMapReference def srBooleanRef : ClassBType = _coreBTypes.srBooleanRef def srByteRef : ClassBType = _coreBTypes.srByteRef diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala index be1595dc29..c6ee36d7b2 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala @@ -14,7 +14,6 @@ import scala.reflect.internal.util.Statistics import scala.tools.asm import scala.tools.asm.tree.ClassNode -import scala.tools.nsc.backend.jvm.opt.LocalOpt /* * Prepare in-memory representations of classfiles using the ASM Tree API, and serialize them to disk. @@ -215,17 +214,12 @@ abstract class GenBCode extends BCodeSyncAndTry { * - converting the plain ClassNode to byte array and placing it on queue-3 */ class Worker2 { - lazy val localOpt = new LocalOpt(settings) - def runGlobalOptimizations(): Unit = { import scala.collection.convert.decorateAsScala._ q2.asScala foreach { case Item2(_, _, plain, _, _) => // skip mirror / bean: wd don't inline into tem, and they are not used in the plain class - if (plain != null) { - localOpt.minimalRemoveUnreachableCode(plain) - callGraph.addClass(plain) - } + if (plain != null) callGraph.addClass(plain) } bTypes.inliner.runInliner() } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/AliasingFrame.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/AliasingFrame.scala new file mode 100644 index 0000000000..7bbe1e2a49 --- /dev/null +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/AliasingFrame.scala @@ -0,0 +1,251 @@ +package scala.tools.nsc +package backend.jvm +package analysis + +import scala.annotation.switch +import scala.collection.{mutable, immutable} +import scala.tools.asm.Opcodes +import scala.tools.asm.tree._ +import scala.tools.asm.tree.analysis.{Analyzer, Value, Frame, Interpreter} +import opt.BytecodeUtils._ + +object AliasingFrame { + private var _idCounter: Long = 0l + private def nextId = { _idCounter += 1; _idCounter } +} + +class AliasingFrame[V <: Value](nLocals: Int, nStack: Int) extends Frame[V](nLocals, nStack) { + import Opcodes._ + + // Auxiliary constructor required for implementing `AliasingAnalyzer.newFrame` + def this(src: Frame[_ <: V]) { + this(src.getLocals, src.getMaxStackSize) + init(src) + } + + /** + * For each slot (entry in the `values` array of the frame), an id that uniquely represents + * the object stored in it. If two values have the same id, they are aliases of the same + * object. + */ + private val aliasIds: Array[Long] = Array.fill(nLocals + nStack)(AliasingFrame.nextId) + + /** + * The object alias id of for a value index. + */ + def aliasId(entry: Int) = aliasIds(entry) + + /** + * Returns the indices of the values array which are aliases of the object `id`. + */ + def valuesWithAliasId(id: Long): Set[Int] = immutable.BitSet.empty ++ aliasIds.indices.iterator.filter(i => aliasId(i) == id) + + /** + * The set of aliased values for a given entry in the `values` array. + */ + def aliasesOf(entry: Int): Set[Int] = valuesWithAliasId(aliasIds(entry)) + + /** + * Define a new alias. For example, given + * var a = this // this, a have the same aliasId + * then an assignment + * b = a + * will set the same the aliasId for `b`. + */ + private def newAlias(assignee: Int, source: Int): Unit = { + aliasIds(assignee) = aliasIds(source) + } + + /** + * An assignment + * a = someUnknownValue() + * sets a fresh alias id for `a`. + * A stack value is also removed from its alias set when being consumed. + */ + private def removeAlias(assignee: Int): Unit = { + aliasIds(assignee) = AliasingFrame.nextId + } + + override def execute(insn: AbstractInsnNode, interpreter: Interpreter[V]): Unit = { + // Make the extendsion methods easier to use (otherwise we have to repeat `this`.stackTop) + def stackTop: Int = this.stackTop + def peekStack(n: Int): V = this.peekStack(n) + + // the val pattern `val (p, c) = f` still allocates a tuple (https://github.com/scala-opt/scala/issues/28) + val prodCons = InstructionStackEffect(insn, this) // needs to be called before super.execute, see its doc + val consumed = prodCons._1 + val produced = prodCons._2 + + super.execute(insn, interpreter) + + (insn.getOpcode: @switch) match { + case ALOAD => + newAlias(assignee = stackTop, source = insn.asInstanceOf[VarInsnNode].`var`) + + case DUP => + val top = stackTop + newAlias(assignee = top, source = top - 1) + + case DUP_X1 => + val top = stackTop + newAlias(assignee = top, source = top - 1) + newAlias(assignee = top - 1, source = top - 2) + newAlias(assignee = top - 2, source = top) + + case DUP_X2 => + // Check if the second element on the stack is size 2 + // https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.dup_x2 + val isSize2 = peekStack(1).getSize == 2 + val top = stackTop + newAlias(assignee = top, source = top - 1) + newAlias(assignee = top - 1, source = top - 2) + if (isSize2) { + // Size 2 values on the stack only take one slot in the `values` array + newAlias(assignee = top - 2, source = top) + } else { + newAlias(assignee = top - 2, source = top - 3) + newAlias(assignee = top - 3, source = top) + } + + case DUP2 => + val isSize2 = peekStack(0).getSize == 2 + val top = stackTop + if (isSize2) { + newAlias(assignee = top, source = top - 1) + } else { + newAlias(assignee = top - 1, source = top - 3) + newAlias(assignee = top, source = top - 2) + } + + case DUP2_X1 => + val isSize2 = peekStack(0).getSize == 2 + val top = stackTop + if (isSize2) { + newAlias(assignee = top, source = top - 1) + newAlias(assignee = top - 1, source = top - 2) + newAlias(assignee = top - 2, source = top) + } else { + newAlias(assignee = top, source = top - 2) + newAlias(assignee = top - 1, source = top - 3) + newAlias(assignee = top - 2, source = top - 4) + newAlias(assignee = top - 4, source = top) + newAlias(assignee = top - 5, source = top - 1) + } + + case DUP2_X2 => + val top = stackTop + // https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.dup2_x2 + val v1isSize2 = peekStack(0).getSize == 2 + if (v1isSize2) { + newAlias(assignee = top, source = top - 1) + newAlias(assignee = top - 1, source = top - 2) + val v2isSize2 = peekStack(1).getSize == 2 + if (v2isSize2) { + // Form 4 + newAlias(assignee = top - 2, source = top) + } else { + // Form 2 + newAlias(assignee = top - 2, source = top - 3) + newAlias(assignee = top - 3, source = top) + } + } else { + newAlias(assignee = top, source = top - 2) + newAlias(assignee = top - 1, source = top - 3) + newAlias(assignee = top - 2, source = top - 4) + val v3isSize2 = peekStack(2).getSize == 2 + if (v3isSize2) { + // Form 3 + newAlias(assignee = top - 3, source = top) + newAlias(assignee = top - 4, source = top - 1) + } else { + // Form 1 + newAlias(assignee = top - 3, source = top - 5) + newAlias(assignee = top - 4, source = top) + newAlias(assignee = top - 5, source = top - 1) + } + } + + case SWAP => + val top = stackTop + val idTop = aliasIds(top) + aliasIds(top) = aliasIds(top - 1) + aliasIds(top - 1) = idTop + + case opcode => + if (opcode == ASTORE) { + // Not a separate case because we need to remove the consumed stack value from alias sets after. + val stackTopBefore = stackTop - produced + consumed + val local = insn.asInstanceOf[VarInsnNode].`var` + newAlias(assignee = local, source = stackTopBefore) + // if the value written is size 2, it overwrites the subsequent slot, which is then no + // longer an alias of anything. see the corresponding case in `Frame.execute`. + if (getLocal(local).getSize == 2) + removeAlias(local + 1) + + // if the value at the preceding index is size 2, it is no longer valid, so we remove its + // aliasing. see corresponding case in `Frame.execute` + if (local > 0) { + val precedingValue = getLocal(local - 1) + if (precedingValue != null && precedingValue.getSize == 2) + removeAlias(local - 1) + } + } + + // Remove consumed stack values from aliasing sets. + // Example: iadd + // - before: local1, local2, stack1, consumed1, consumed2 + // - after: local1, local2, stack1, produced1 // stackTop = 3 + val firstConsumed = stackTop - produced + 1 // firstConsumed = 3 + for (i <- 0 until consumed) + removeAlias(firstConsumed + i) // remove aliases for 3 and 4 + + // We don't need to set the aliases ids for the produced values: the aliasIds array already + // contains fresh ids for non-used stack values (ensured by removeAlias). + } + } + + /** + * Merge the AliasingFrame `other` into this AliasingFrame. + * + * Aliases that are common in both frames are kept. Example: + * + * var x, y = null + * if (...) { + * x = a + * y = a // (x, y, a) are aliases + * } else { + * x = a + * y = b // (x, a) and (y, b) + * } + * [...] // (x, a) + */ + override def merge(other: Frame[_ <: V], interpreter: Interpreter[V]): Boolean = { + val valuesChanged = super.merge(other, interpreter) + var aliasesChanged = false + val aliasingOther = other.asInstanceOf[AliasingFrame[_]] + for (i <- aliasIds.indices) { + val thisAliases = aliasesOf(i) + val thisNotOther = thisAliases diff (thisAliases intersect aliasingOther.aliasesOf(i)) + if (thisNotOther.nonEmpty) { + aliasesChanged = true + thisNotOther foreach removeAlias + } + } + valuesChanged || aliasesChanged + } + + override def init(src: Frame[_ <: V]): Frame[V] = { + super.init(src) + compat.Platform.arraycopy(src.asInstanceOf[AliasingFrame[_]].aliasIds, 0, aliasIds, 0, aliasIds.length) + this + } +} + +/** + * An analyzer that uses AliasingFrames instead of bare Frames. This can be used when an analysis + * needs to track aliases, but doesn't require a more specific Frame subclass. + */ +class AliasingAnalyzer[V <: Value](interpreter: Interpreter[V]) extends Analyzer[V](interpreter) { + override def newFrame(nLocals: Int, nStack: Int): AliasingFrame[V] = new AliasingFrame(nLocals, nStack) + override def newFrame(src: Frame[_ <: V]): AliasingFrame[V] = new AliasingFrame(src) +} diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/InstructionStackEffect.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/InstructionStackEffect.scala new file mode 100644 index 0000000000..98e93c125b --- /dev/null +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/InstructionStackEffect.scala @@ -0,0 +1,265 @@ +package scala.tools.nsc +package backend.jvm +package analysis + +import scala.annotation.switch +import scala.tools.asm.Opcodes._ +import scala.tools.asm.Type +import scala.tools.asm.tree.{MultiANewArrayInsnNode, InvokeDynamicInsnNode, MethodInsnNode, AbstractInsnNode} +import scala.tools.asm.tree.analysis.{Frame, Value} +import opt.BytecodeUtils._ +import collection.immutable + +object InstructionStackEffect { + private var cache: immutable.IntMap[(Int, Int)] = immutable.IntMap.empty + private def t(x: Int, y: Int): (Int, Int) = { + // x can go up to 255 (number of parameters of a method, dimensions in multianewarray) we cache + // x up to 10, which covers most cases and limits the cache. y doesn't go above 6 (see cases). + if (x > 10 || y > 6) (x, y) + else { + val key = (x << 8) + y // this would work for any x < 256 + if (cache contains key) { + cache(key) + } else { + val r = (x, y) + cache += key -> r + r + } + } + } + + /** + * Returns a pair with the number of stack values consumed and produced by `insn`. + * This method requires the `frame` to be in the state **before** executing / interpreting + * the `insn`. + */ + def apply[V <: Value](insn: AbstractInsnNode, frame: Frame[V]): (Int, Int) = { + def peekStack(n: Int): V = frame.peekStack(n) + + (insn.getOpcode: @switch) match { + // The order of opcodes is the same as in Frame.execute. + case NOP => t(0, 0) + + case ACONST_NULL | + ICONST_M1 | + ICONST_0 | + ICONST_1 | + ICONST_2 | + ICONST_3 | + ICONST_4 | + ICONST_5 | + LCONST_0 | + LCONST_1 | + FCONST_0 | + FCONST_1 | + FCONST_2 | + DCONST_0 | + DCONST_1 | + BIPUSH | + SIPUSH | + LDC | + ILOAD | + LLOAD | + FLOAD | + DLOAD | + ALOAD => t(0, 1) + + case IALOAD | + LALOAD | + FALOAD | + DALOAD | + AALOAD | + BALOAD | + CALOAD | + SALOAD => t(2, 1) + + case ISTORE | + LSTORE | + FSTORE | + DSTORE | + ASTORE => t(1, 0) + + case IASTORE | + LASTORE | + FASTORE | + DASTORE | + AASTORE | + BASTORE | + CASTORE | + SASTORE => t(3, 0) + + case POP => t(1, 0) + + case POP2 => + val isSize2 = peekStack(0).getSize == 2 + if (isSize2) t(1, 0) else t(2, 0) + + case DUP => t(0, 1) + + case DUP_X1 => t(2, 3) + + case DUP_X2 => + val isSize2 = peekStack(1).getSize == 2 + if (isSize2) t(2, 3) else t(3, 4) + + case DUP2 => + val isSize2 = peekStack(0).getSize == 2 + if (isSize2) t(0, 1) else t(0, 2) + + case DUP2_X1 => + val isSize2 = peekStack(0).getSize == 2 + if (isSize2) t(2, 3) else t(3, 4) + + case DUP2_X2 => + val v1isSize2 = peekStack(0).getSize == 2 + if (v1isSize2) { + val v2isSize2 = peekStack(1).getSize == 2 + if (v2isSize2) t(2, 3) else t(3, 4) + } else { + val v3isSize2 = peekStack(2).getSize == 2 + if (v3isSize2) t(3, 5) else t(4, 6) + } + + case SWAP => t(2, 2) + + case IADD | + LADD | + FADD | + DADD | + ISUB | + LSUB | + FSUB | + DSUB | + IMUL | + LMUL | + FMUL | + DMUL | + IDIV | + LDIV | + FDIV | + DDIV | + IREM | + LREM | + FREM | + DREM => t(2, 1) + + case INEG | + LNEG | + FNEG | + DNEG => t(1, 1) + + case ISHL | + LSHL | + ISHR | + LSHR | + IUSHR | + LUSHR | + IAND | + LAND | + IOR | + LOR | + IXOR | + LXOR => t(2, 1) + + case IINC => t(0, 0) + + case I2L | + I2F | + I2D | + L2I | + L2F | + L2D | + F2I | + F2L | + F2D | + D2I | + D2L | + D2F | + I2B | + I2C | + I2S => t(1, 1) + + case LCMP | + FCMPL | + FCMPG | + DCMPL | + DCMPG => t(2, 1) + + case IFEQ | + IFNE | + IFLT | + IFGE | + IFGT | + IFLE => t(1, 0) + + case IF_ICMPEQ | + IF_ICMPNE | + IF_ICMPLT | + IF_ICMPGE | + IF_ICMPGT | + IF_ICMPLE | + IF_ACMPEQ | + IF_ACMPNE => t(2, 0) + + case GOTO => t(0, 0) + + case JSR => t(0, 1) + + case RET => t(0, 0) + + case TABLESWITCH | + LOOKUPSWITCH => t(1, 0) + + case IRETURN | + LRETURN | + FRETURN | + DRETURN | + ARETURN => t(1, 0) // Frame.execute consumes one stack value + + case RETURN => t(0, 0) // Frame.execute does not change the stack + + case GETSTATIC => t(0, 1) + + case PUTSTATIC => t(1, 0) + + case GETFIELD => t(1, 1) + + case PUTFIELD => t(2, 0) + + case INVOKEVIRTUAL | + INVOKESPECIAL | + INVOKESTATIC | + INVOKEINTERFACE => + val desc = insn.asInstanceOf[MethodInsnNode].desc + val cons = Type.getArgumentTypes(desc).length + (if (insn.getOpcode == INVOKESTATIC) 0 else 1) + val prod = if (Type.getReturnType(desc) == Type.VOID_TYPE) 0 else 1 + t(cons, prod) + + case INVOKEDYNAMIC => + val desc = insn.asInstanceOf[InvokeDynamicInsnNode].desc + val cons = Type.getArgumentTypes(desc).length + val prod = if (Type.getReturnType(desc) == Type.VOID_TYPE) 0 else 1 + t(cons, prod) + + case NEW => t(0, 1) + + case NEWARRAY | + ANEWARRAY | + ARRAYLENGTH => t(1, 1) + + case ATHROW => t(1, 0) // Frame.execute consumes one stack value + + case CHECKCAST | + INSTANCEOF => t(1, 1) // Frame.execute does push(pop()) for both of them + + case MONITORENTER | + MONITOREXIT => t(1, 0) + + case MULTIANEWARRAY => t(insn.asInstanceOf[MultiANewArrayInsnNode].dims, 1) + + case IFNULL | + IFNONNULL => t(1, 0) + } + } + +} diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzer.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzer.scala new file mode 100644 index 0000000000..31710dcbee --- /dev/null +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzer.scala @@ -0,0 +1,282 @@ +package scala.tools.nsc +package backend.jvm +package analysis + +import java.util + +import scala.annotation.switch +import scala.tools.asm.{Type, Opcodes} +import scala.tools.asm.tree.{MethodInsnNode, LdcInsnNode, AbstractInsnNode} +import scala.tools.asm.tree.analysis.{Frame, Analyzer, Interpreter, Value} +import scala.tools.nsc.backend.jvm.opt.BytecodeUtils +import BytecodeUtils._ + +/** + * Some notes on the ASM ananlyzer framework. + * + * Value + * - Abstract, needs to be implemented for each analysis. + * - Represents the desired information about local variables and stack values, for example: + * - Is this value known to be null / not null? + * - What are the instructions that could potentially have produced this value? + * + * Interpreter + * - Abstract, needs to be implemented for each analysis. Sometimes one can subclass an existing + * interpreter, e.g., SourceInterpreter or BasicInterpreter. + * - Multiple abstract methods that receive an instruction and the instruction's input values, and + * return a value representing the result of that instruction. + * - Note: due to control flow, the interpreter can be invoked multiple times for the same + * instruction, until reaching a fixed point. + * - Abstract `merge` function that computes the least upper bound of two values. Used by + * Frame.merge (see below). + * + * Frame + * - Can be used directly for many analyses, no subclass required. + * - Every frame has an array of values: one for each local variable and for each stack slot. + * - A `top` index stores the index of the current stack top + * - NOTE: for a size-2 local variable at index i, the local variable at i+1 is set to an empty + * value. However, for a size-2 value at index i on the stack, the value at i+1 holds the next + * stack value. + * - Defines the `execute(instruction)` method. + * - executing mutates the state of the frame according to the effect of the instruction + * - pop consumed values from the stack + * - pass them to the interpreter together with the instruction + * - if applicable, push the resulting value on the stack + * - Defines the `merge(otherFrame)` method + * - called by the analyzer when multiple control flow paths lead to an instruction + * - the frame at the branching instruction is merged into the current frame of the + * instruction (held by the analyzer) + * - mutates the values of the current frame, merges all values using interpreter.merge. + * + * Analyzer + * - Stores a frame for each instruction + * - `merge` function takes an instruction and a frame, merges the existing frame for that instr + * (from the frames array) with the new frame passed as argument. + * if the frame changed, puts the instruction on the work queue (fixpiont). + * - initial frame: initialized for first instr by calling interpreter.new[...]Value + * for each slot (locals and params), stored in frames[firstInstr] by calling `merge` + * - work queue of instructions (`queue` array, `top` index for next instruction to analyze) + * - analyze(method): simulate control flow. while work queue non-empty: + * - copy the state of `frames[instr]` into a local frame `current` + * - call `current.execute(instr, interpreter)`, mutating the `current` frame + * - if it's a branching instruction + * - for all potential destination instructions + * - merge the destination instruction frame with the `current` frame + * (this enqueues the destination instr if its frame changed) + * - invoke `newControlFlowEdge` (see below) + * - the analyzer also tracks active exception handlers at each instruction + * - the empty method `newControlFlowEdge` can be overridden to track control flow if required + * + * + * Some notes on nullness analysis. + * + * For an instance method, `this` is non-null at entry. So we have to return a NotNull value when + * the analyzer is initializing the first frame of a method (see above). This required a change of + * the analyzer: before it would simply call `interpreter.newValue`, where we don't have the + * required context. See https://github.com/scala/scala-asm/commit/8133d75032. + * + * After some operations we know that a certain value is not null (e.g. the receiver of an instance + * call). However, the receiver is an value on the stack and consumed while interpreting the + * instruction - so we can only gain some knowledge if we know that the receiver was an alias of + * some other local variable or stack slot. Therefore we use the AliasingFrame class. + * + * TODO: + * Finally, we'd also like to exploit the knowledge gained from `if (x == null)` tests: x is known + * to be null in one branch, not null in the other. This will make use of alias tracking as well. + * We still have to figure out how to do this exactly in the analyzer framework. + */ + +/** + * Type to represent nullness of values. + */ +sealed trait Nullness { + final def merge(other: Nullness) = if (this == other) this else Unknown +} +case object NotNull extends Nullness +case object Unknown extends Nullness +case object Null extends Nullness + +/** + * Represents the nullness state for a local variable or stack value. + * + * Note that nullness of primitive values is not tracked, it will be always [[Unknown]]. + */ +sealed trait NullnessValue extends Value { + /** + * The nullness of this value. + */ + def nullness: Nullness + + /** + * True if this value is a long or double. The Analyzer framework needs to know + * the size of each value when interpreting instructions, see `Frame.execute`. + */ + def isSize2: Boolean + /** + * The size of the slot described by this value. Cannot be 0 because no values are allocated + * for void-typed slots, see NullnessInterpreter.newValue. + **/ + def getSize: Int = if (isSize2) 2 else 1 + + def merge(other: NullnessValue) = NullnessValue(nullness merge other.nullness, isSize2) +} + +object NullValue extends NullnessValue { def nullness = Null; def isSize2 = false; override def toString = "Null" } +object UnknownValue1 extends NullnessValue { def nullness = Unknown; def isSize2 = false; override def toString = "Unknown1" } +object UnknownValue2 extends NullnessValue { def nullness = Unknown; def isSize2 = true; override def toString = "Unknown2" } +object NotNullValue extends NullnessValue { def nullness = NotNull; def isSize2 = false; override def toString = "NotNull" } + +object NullnessValue { + def apply(nullness: Nullness, isSize2: Boolean): NullnessValue = { + if (nullness == Null) NullValue + else if (nullness == NotNull) NotNullValue + else if (isSize2) UnknownValue2 + else UnknownValue1 + } + + def apply(nullness: Nullness, insn: AbstractInsnNode): NullnessValue = { + apply(nullness, isSize2 = BytecodeUtils.instructionResultSize(insn) == 2) + } +} + +final class NullnessInterpreter extends Interpreter[NullnessValue](Opcodes.ASM5) { + def newValue(tp: Type): NullnessValue = { + // ASM loves giving semantics to null. The behavior here is the same as in SourceInterpreter, + // which is provided by the framework. + // + // (1) For the void type, the ASM framework expects newValue to return `null`. + // Also, the Frame.returnValue field is `null` for methods with return type void. + // Example callsite passing VOID_TYPE: in Analyzer, `newValue(Type.getReturnType(m.desc))`. + // + // (2) `tp` may also be `null`. When creating the initial frame, the analyzer invokes + // `newValue(null)` for each local variable. We have to return a value of size 1. + if (tp == Type.VOID_TYPE) null // (1) + else NullnessValue(Unknown, isSize2 = tp != null /*(2)*/ && tp.getSize == 2 ) + } + + override def newParameterValue(isInstanceMethod: Boolean, local: Int, tp: Type): NullnessValue = { + // For instance methods, the `this` parameter is known to be not null. + if (isInstanceMethod && local == 0) NullnessValue(NotNull, isSize2 = false) + else super.newParameterValue(isInstanceMethod, local, tp) + } + + def newOperation(insn: AbstractInsnNode): NullnessValue = { + val nullness = (insn.getOpcode: @switch) match { + case Opcodes.ACONST_NULL => Null + + case Opcodes.LDC => insn.asInstanceOf[LdcInsnNode].cst match { + case _: String | _: Type => NotNull + case _ => Unknown + } + + case _ => Unknown + } + + // for Opcodes.NEW, we use Unknown. The value will become NotNull after the constructor call. + NullnessValue(nullness, insn) + } + + def copyOperation(insn: AbstractInsnNode, value: NullnessValue): NullnessValue = value + + def unaryOperation(insn: AbstractInsnNode, value: NullnessValue): NullnessValue = (insn.getOpcode: @switch) match { + case Opcodes.CHECKCAST => value + + case Opcodes.NEWARRAY | + Opcodes.ANEWARRAY => NullnessValue(NotNull, isSize2 = false) + + case _ => NullnessValue(Unknown, insn) + } + + def binaryOperation(insn: AbstractInsnNode, value1: NullnessValue, value2: NullnessValue): NullnessValue = { + NullnessValue(Unknown, insn) + } + + def ternaryOperation(insn: AbstractInsnNode, value1: NullnessValue, value2: NullnessValue, value3: NullnessValue): NullnessValue = { + NullnessValue(Unknown, isSize2 = false) + } + + def naryOperation(insn: AbstractInsnNode, values: util.List[_ <: NullnessValue]): NullnessValue = (insn.getOpcode: @switch) match { + case Opcodes.MULTIANEWARRAY => + NullnessValue(NotNull, isSize2 = false) + + case _ => + // TODO: use a list of methods that are known to return non-null values + NullnessValue(Unknown, insn) + } + + def returnOperation(insn: AbstractInsnNode, value: NullnessValue, expected: NullnessValue): Unit = () + + def merge(a: NullnessValue, b: NullnessValue): NullnessValue = a merge b +} + +class NullnessFrame(nLocals: Int, nStack: Int) extends AliasingFrame[NullnessValue](nLocals, nStack) { + // Auxiliary constructor required for implementing `NullnessAnalyzer.newFrame` + def this(src: Frame[_ <: NullnessValue]) { + this(src.getLocals, src.getMaxStackSize) + init(src) + } + + override def execute(insn: AbstractInsnNode, interpreter: Interpreter[NullnessValue]): Unit = { + import Opcodes._ + + // get the object id of the object that is known to be not-null after this operation + val nullCheckedAliasId: Long = (insn.getOpcode: @switch) match { + case IALOAD | + LALOAD | + FALOAD | + DALOAD | + AALOAD | + BALOAD | + CALOAD | + SALOAD => + aliasId(this.stackTop - 1) + + case IASTORE | + FASTORE | + AASTORE | + BASTORE | + CASTORE | + SASTORE | + LASTORE | + DASTORE => + aliasId(this.stackTop - 2) + + case GETFIELD => + aliasId(this.stackTop) + + case PUTFIELD => + aliasId(this.stackTop - 1) + + case INVOKEVIRTUAL | + INVOKESPECIAL | + INVOKEINTERFACE => + val desc = insn.asInstanceOf[MethodInsnNode].desc + val numArgs = Type.getArgumentTypes(desc).length + aliasId(this.stackTop - numArgs) + + case ARRAYLENGTH | + MONITORENTER | + MONITOREXIT => + aliasId(this.stackTop) + + case _ => + -1 + } + + super.execute(insn, interpreter) + + if (nullCheckedAliasId != -1) { + for (i <- valuesWithAliasId(nullCheckedAliasId)) + this.setValue(i, NotNullValue) + } + } +} + +/** + * This class is required to override the `newFrame` methods, which makes makes sure the analyzer + * uses NullnessFrames. + */ +class NullnessAnalyzer extends Analyzer[NullnessValue](new NullnessInterpreter) { + override def newFrame(nLocals: Int, nStack: Int): NullnessFrame = new NullnessFrame(nLocals, nStack) + override def newFrame(src: Frame[_ <: NullnessValue]): NullnessFrame = new NullnessFrame(src) +} 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 14e8cccc60..9bd016f964 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala @@ -10,6 +10,7 @@ package opt import scala.annotation.{tailrec, switch} import scala.collection.mutable import scala.reflect.internal.util.Collections._ +import scala.tools.asm.commons.CodeSizeEvaluator import scala.tools.asm.tree.analysis._ import scala.tools.asm.{MethodWriter, ClassWriter, Label, Opcodes} import scala.tools.asm.tree._ @@ -21,6 +22,12 @@ import scala.tools.nsc.backend.jvm.BTypes._ object BytecodeUtils { + // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.9.1 + final val maxJVMMethodSize = 65535 + + // 5% margin, more than enough for the instructions added by the inliner (store / load args, null check for instance methods) + final val maxMethodSizeAfterInline = maxJVMMethodSize - (maxJVMMethodSize / 20) + object Goto { def unapply(instruction: AbstractInsnNode): Option[JumpInsnNode] = { if (instruction.getOpcode == Opcodes.GOTO) Some(instruction.asInstanceOf[JumpInsnNode]) @@ -83,10 +90,14 @@ object BytecodeUtils { def isSynchronizedMethod(methodNode: MethodNode): Boolean = (methodNode.access & Opcodes.ACC_SYNCHRONIZED) != 0 + def isNativeMethod(methodNode: MethodNode): Boolean = (methodNode.access & Opcodes.ACC_NATIVE) != 0 + def isFinalClass(classNode: ClassNode): Boolean = (classNode.access & Opcodes.ACC_FINAL) != 0 def isFinalMethod(methodNode: MethodNode): Boolean = (methodNode.access & (Opcodes.ACC_FINAL | Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC)) != 0 + def isStrictfpMethod(methodNode: MethodNode): Boolean = (methodNode.access & Opcodes.ACC_STRICT) != 0 + def nextExecutableInstruction(instruction: AbstractInsnNode, alsoKeep: AbstractInsnNode => Boolean = Set()): Option[AbstractInsnNode] = { var result = instruction do { result = result.getNext } @@ -159,6 +170,8 @@ object BytecodeUtils { new InsnNode(op) } + def instructionResultSize(instruction: AbstractInsnNode) = InstructionResultSize(instruction) + def labelReferences(method: MethodNode): Map[LabelNode, Set[AnyRef]] = { val res = mutable.Map.empty[LabelNode, Set[AnyRef]] def add(l: LabelNode, ref: AnyRef) = if (res contains l) res(l) = res(l) + ref else res(l) = Set(ref) @@ -215,7 +228,7 @@ object BytecodeUtils { * to create a separate visitor for computing those values, duplicating the functionality from the * MethodWriter. */ - def computeMaxLocalsMaxStack(method: MethodNode) { + def computeMaxLocalsMaxStack(method: MethodNode): Unit = { val cw = new ClassWriter(ClassWriter.COMPUTE_MAXS) val excs = method.exceptions.asScala.toArray val mw = cw.visitMethod(method.access, method.name, method.desc, method.signature, excs).asInstanceOf[MethodWriter] @@ -224,6 +237,21 @@ object BytecodeUtils { method.maxStack = mw.getMaxStack } + def codeSizeOKForInlining(caller: MethodNode, callee: MethodNode): Boolean = { + // Looking at the implementation of CodeSizeEvaluator, all instructions except tableswitch and + // lookupswitch are <= 8 bytes. These should be rare enough for 8 to be an OK rough upper bound. + def roughUpperBound(methodNode: MethodNode): Int = methodNode.instructions.size * 8 + + def maxSize(methodNode: MethodNode): Int = { + val eval = new CodeSizeEvaluator(null) + methodNode.accept(eval) + eval.getMaxSize + } + + (roughUpperBound(caller) + roughUpperBound(callee) > maxMethodSizeAfterInline) && + (maxSize(caller) + maxSize(callee) > maxMethodSizeAfterInline) + } + def removeLineNumberNodes(classNode: ClassNode): Unit = { for (m <- classNode.methods.asScala) removeLineNumberNodes(m.instructions) } @@ -302,13 +330,38 @@ object BytecodeUtils { class AsmAnalyzer[V <: Value](methodNode: MethodNode, classInternalName: InternalName, interpreter: Interpreter[V] = new BasicInterpreter) { val analyzer = new Analyzer(interpreter) analyzer.analyze(classInternalName, methodNode) - def frameAt(instruction: AbstractInsnNode): Frame[V] = analyzer.getFrames()(methodNode.instructions.indexOf(instruction)) + def frameAt(instruction: AbstractInsnNode): Frame[V] = analyzer.frameAt(instruction, methodNode) } - implicit class `frame extensions`[V <: Value](val frame: Frame[V]) extends AnyVal { - def peekDown(n: Int): V = { - val topIndex = frame.getStackSize - 1 - frame.getStack(topIndex - n) + implicit class AnalyzerExtensions[V <: Value](val analyzer: Analyzer[V]) extends AnyVal { + def frameAt(instruction: AbstractInsnNode, methodNode: MethodNode): Frame[V] = analyzer.getFrames()(methodNode.instructions.indexOf(instruction)) + } + + implicit class FrameExtensions[V <: Value](val frame: Frame[V]) extends AnyVal { + /** + * The value `n` positions down the stack. + */ + def peekStack(n: Int): V = frame.getStack(frame.getStackSize - 1 - n) + + /** + * The index of the current stack top. + */ + def stackTop = frame.getLocals + frame.getStackSize - 1 + + /** + * Gets the value at slot i, where i may be a local or a stack index. + */ + def getValue(i: Int): V = { + if (i < frame.getLocals) frame.getLocal(i) + else frame.getStack(i - frame.getLocals) + } + + /** + * Sets the value at slot i, where i may be a local or a stack index. + */ + def setValue(i: Int, value: V): Unit = { + if (i < frame.getLocals) frame.setLocal(i, value) + else frame.setStack(i - frame.getLocals, value) } } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index 47d32c94cb..0932564b1f 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -8,12 +8,15 @@ package backend.jvm package opt import scala.reflect.internal.util.{NoPosition, Position} +import scala.tools.asm.tree.analysis.{Value, Analyzer, BasicInterpreter} +import scala.tools.asm.{Opcodes, Type} import scala.tools.asm.tree._ import scala.collection.convert.decorateAsScala._ -import scala.tools.nsc.backend.jvm.BTypes.{MethodInlineInfo, InternalName} +import scala.tools.nsc.backend.jvm.BTypes.InternalName import scala.tools.nsc.backend.jvm.BackendReporting._ -import scala.tools.nsc.backend.jvm.opt.BytecodeUtils.AsmAnalyzer +import scala.tools.nsc.backend.jvm.analysis.{NotNull, NullnessAnalyzer} import ByteCodeRepository.{Source, CompilationUnit} +import BytecodeUtils._ class CallGraph[BT <: BTypes](val btypes: BT) { import btypes._ @@ -43,14 +46,14 @@ class CallGraph[BT <: BTypes](val btypes: BT) { // callee, we only check there for the methodInlineInfo, we should find it there. calleeDeclarationClassBType.info.orThrow.inlineInfo.methodInfos.get(methodSignature) match { case Some(methodInlineInfo) => - val canInlineFromSource = inlineGlobalEnabled || calleeSource == CompilationUnit + val canInlineFromSource = compilerSettings.YoptInlineGlobal || calleeSource == CompilationUnit val isAbstract = BytecodeUtils.isAbstractMethod(calleeMethodNode) // (1) A non-final method can be safe to inline if the receiver type is a final subclass. Example: // class A { @inline def f = 1 }; object B extends A; B.f // can be inlined // - // TODO: type analysis can render more calls statically resolved. Example˜∫ + // TODO: type analysis can render more calls statically resolved. Example: // new A.f // can be inlined, the receiver type is known to be exactly A. val isStaticallyResolved: Boolean = { methodInlineInfo.effectivelyFinal || @@ -68,8 +71,13 @@ class CallGraph[BT <: BTypes](val btypes: BT) { // (2) Final trait methods can be rewritten from the interface to the static implementation // method to enable inlining. CallsiteInfo( - safeToInline = canInlineFromSource && isStaticallyResolved && !isAbstract, // (1) - safeToRewrite = canInlineFromSource && isRewritableTraitCall, // (2) + safeToInline = + canInlineFromSource && + isStaticallyResolved && // (1) + !isAbstract && + !BytecodeUtils.isConstructor(calleeMethodNode) && + !BytecodeUtils.isNativeMethod(calleeMethodNode), + safeToRewrite = canInlineFromSource && isRewritableTraitCall, // (2) annotatedInline = methodInlineInfo.annotatedInline, annotatedNoInline = methodInlineInfo.annotatedNoInline, warning = warning) @@ -88,11 +96,25 @@ class CallGraph[BT <: BTypes](val btypes: BT) { // TODO: run dataflow analyses to make the call graph more precise // - producers to get forwarded parameters (ForwardedParam) // - typeAnalysis for more precise argument types, more precise callee - // - nullAnalysis to skip emitting the receiver-null-check when inlining - // TODO: for now we run a basic analyzer to get the stack height at the call site. - // once we run a more elaborate analyzer (types, nullness), we can get the stack height out of there. - val analyzer = new AsmAnalyzer(methodNode, definingClass.internalName) + // For now we run a NullnessAnalyzer. It is used to determine if the receiver of an instance + // call is known to be not-null, in which case we don't have to emit a null check when inlining. + // It is also used to get the stack height at the call site. + localOpt.minimalRemoveUnreachableCode(methodNode, definingClass.internalName) + + val analyzer: Analyzer[_ <: Value] = { + if (compilerSettings.YoptNullnessTracking) new NullnessAnalyzer + else new Analyzer(new BasicInterpreter) + } + analyzer.analyze(definingClass.internalName, methodNode) + + def receiverNotNullByAnalysis(call: MethodInsnNode, numArgs: Int) = analyzer match { + case nullnessAnalyzer: NullnessAnalyzer => + val frame = nullnessAnalyzer.frameAt(call, methodNode) + frame.getStack(frame.getStackSize - 1 - numArgs).nullness == NotNull + + case _ => false + } methodNode.instructions.iterator.asScala.collect({ case call: MethodInsnNode => @@ -120,13 +142,19 @@ class CallGraph[BT <: BTypes](val btypes: BT) { Nil } + val receiverNotNull = call.getOpcode == Opcodes.INVOKESTATIC || { + val numArgs = Type.getArgumentTypes(call.desc).length + receiverNotNullByAnalysis(call, numArgs) + } + Callsite( callsiteInstruction = call, callsiteMethod = methodNode, callsiteClass = definingClass, callee = callee, argInfos = argInfos, - callsiteStackHeight = analyzer.frameAt(call).getStackSize, + callsiteStackHeight = analyzer.frameAt(call, methodNode).getStackSize, + receiverKnownNotNull = receiverNotNull, callsitePosition = callsitePositions.getOrElse(call, NoPosition) ) }).toList @@ -148,7 +176,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { */ final case class Callsite(callsiteInstruction: MethodInsnNode, callsiteMethod: MethodNode, callsiteClass: ClassBType, callee: Either[OptimizerWarning, Callee], argInfos: List[ArgInfo], - callsiteStackHeight: Int, callsitePosition: Position) { + callsiteStackHeight: Int, receiverKnownNotNull: Boolean, callsitePosition: Position) { override def toString = "Invocation of" + s" ${callee.map(_.calleeDeclarationClass.internalName).getOrElse("?")}.${callsiteInstruction.name + callsiteInstruction.desc}" + diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala index e14e57d3ab..814c78b69c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala @@ -16,7 +16,7 @@ import scala.collection.convert.decorateAsJava._ import AsmUtils._ import BytecodeUtils._ import collection.mutable -import scala.tools.asm.tree.analysis.{SourceInterpreter, Analyzer} +import scala.tools.asm.tree.analysis.SourceInterpreter import BackendReporting._ import scala.tools.nsc.backend.jvm.BTypes.InternalName @@ -24,21 +24,39 @@ class Inliner[BT <: BTypes](val btypes: BT) { import btypes._ import callGraph._ + def eliminateUnreachableCodeAndUpdateCallGraph(methodNode: MethodNode, definingClass: InternalName): Unit = { + localOpt.minimalRemoveUnreachableCode(methodNode, definingClass) foreach { + case invocation: MethodInsnNode => callGraph.callsites.remove(invocation) + case _ => + } + } + def runInliner(): Unit = { rewriteFinalTraitMethodInvocations() for (request <- collectAndOrderInlineRequests) { val Right(callee) = request.callee // collectAndOrderInlineRequests returns callsites with a known callee - val r = inline(request.callsiteInstruction, request.callsiteStackHeight, request.callsiteMethod, request.callsiteClass, - callee.callee, callee.calleeDeclarationClass, - receiverKnownNotNull = false, keepLineNumbers = false) - - for (warning <- r) { - if ((callee.annotatedInline && btypes.warnSettings.atInlineFailed) || warning.emitWarning(warnSettings)) { - val annotWarn = if (callee.annotatedInline) " is annotated @inline but" else "" - val msg = s"${BackendReporting.methodSignature(callee.calleeDeclarationClass.internalName, callee.callee)}$annotWarn could not be inlined:\n$warning" - backendReporting.inlinerWarning(request.callsitePosition, msg) + // Inlining a method can create unreachable code. Example: + // def f = throw e + // def g = f; println() // println is unreachable after inlining f + // If we have an inline request for a call to g, and f has been already inlined into g, we + // need to run DCE before inlining g. + eliminateUnreachableCodeAndUpdateCallGraph(callee.callee, callee.calleeDeclarationClass.internalName) + + // DCE above removes unreachable callsites from the call graph. If the inlining request denotes + // such an eliminated callsite, do nothing. + if (callGraph.callsites contains request.callsiteInstruction) { + val r = inline(request.callsiteInstruction, request.callsiteStackHeight, request.callsiteMethod, request.callsiteClass, + callee.callee, callee.calleeDeclarationClass, + request.receiverKnownNotNull, keepLineNumbers = false) + + for (warning <- r) { + if ((callee.annotatedInline && btypes.compilerSettings.YoptWarningEmitAtInlineFailed) || warning.emitWarning(compilerSettings)) { + val annotWarn = if (callee.annotatedInline) " is annotated @inline but" else "" + val msg = s"${BackendReporting.methodSignature(callee.calleeDeclarationClass.internalName, callee.callee)}$annotWarn could not be inlined:\n$warning" + backendReporting.inlinerWarning(request.callsitePosition, msg) + } } } } @@ -71,11 +89,11 @@ class Inliner[BT <: BTypes](val btypes: BT) { */ def selectCallsitesForInlining: List[Callsite] = { callsites.valuesIterator.filter({ - case callsite @ Callsite(_, _, _, Right(Callee(callee, calleeDeclClass, safeToInline, _, annotatedInline, _, warning)), _, _, pos) => + case callsite @ Callsite(_, _, _, Right(Callee(callee, calleeDeclClass, safeToInline, _, annotatedInline, _, warning)), _, _, _, pos) => val res = doInlineCallsite(callsite) if (!res) { - if (annotatedInline && btypes.warnSettings.atInlineFailed) { + if (annotatedInline && btypes.compilerSettings.YoptWarningEmitAtInlineFailed) { // if the callsite is annotated @inline, we report an inline warning even if the underlying // reason is, for example, mixed compilation (which has a separate -Yopt-warning flag). def initMsg = s"${BackendReporting.methodSignature(calleeDeclClass.internalName, callee)} is annotated @inline but cannot be inlined" @@ -86,7 +104,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { backendReporting.inlinerWarning(pos, s"$initMsg: the method is not final and may be overridden." + warnMsg) else backendReporting.inlinerWarning(pos, s"$initMsg." + warnMsg) - } else if (warning.isDefined && warning.get.emitWarning(warnSettings)) { + } else if (warning.isDefined && warning.get.emitWarning(compilerSettings)) { // when annotatedInline is false, and there is some warning, the callsite metadata is possibly incomplete. backendReporting.inlinerWarning(pos, s"there was a problem determining if method ${callee.name} can be inlined: \n"+ warning.get) } @@ -94,8 +112,8 @@ class Inliner[BT <: BTypes](val btypes: BT) { res - case Callsite(ins, _, _, Left(warning), _, _, pos) => - if (warning.emitWarning(warnSettings)) + case Callsite(ins, _, _, Left(warning), _, _, _, pos) => + if (warning.emitWarning(compilerSettings)) backendReporting.inlinerWarning(pos, s"failed to determine if ${ins.name} should be inlined:\n$warning") false }).toList @@ -105,8 +123,9 @@ class Inliner[BT <: BTypes](val btypes: BT) { * The current inlining heuristics are simple: inline calls to methods annotated @inline. */ def doInlineCallsite(callsite: Callsite): Boolean = callsite match { - case Callsite(_, _, _, Right(Callee(callee, calleeDeclClass, safeToInline, _, annotatedInline, _, warning)), _, _, pos) => - annotatedInline && safeToInline + case Callsite(_, _, _, Right(Callee(callee, calleeDeclClass, safeToInline, _, annotatedInline, _, warning)), _, _, _, pos) => + if (compilerSettings.YoptInlineHeuristics.value == "everything") safeToInline + else annotatedInline && safeToInline case _ => false } @@ -167,8 +186,10 @@ class Inliner[BT <: BTypes](val btypes: BT) { // VerifyError. We run a `SourceInterpreter` to find all producer instructions of the // receiver value and add a cast to the self type after each. if (!selfTypeOk) { + // there's no need to run eliminateUnreachableCode here. building the call graph does that + // already, no code can become unreachable in the meantime. val analyzer = new AsmAnalyzer(callsite.callsiteMethod, callsite.callsiteClass.internalName, new SourceInterpreter) - val receiverValue = analyzer.frameAt(callsite.callsiteInstruction).peekDown(traitMethodArgumentTypes.length) + val receiverValue = analyzer.frameAt(callsite.callsiteInstruction).peekStack(traitMethodArgumentTypes.length) for (i <- receiverValue.insns.asScala) { val cast = new TypeInsnNode(CHECKCAST, selfParamType.internalName) callsite.callsiteMethod.instructions.insert(i, cast) @@ -194,6 +215,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { calleeInfoWarning = infoWarning)), argInfos = Nil, callsiteStackHeight = callsite.callsiteStackHeight, + receiverKnownNotNull = callsite.receiverKnownNotNull, callsitePosition = callsite.callsitePosition ) callGraph.callsites(newCallsiteInstruction) = staticCallsite @@ -311,6 +333,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { val localVarShift = callsiteMethod.maxLocals clonedInstructions.iterator.asScala foreach { case varInstruction: VarInsnNode => varInstruction.`var` += localVarShift + case iinc: IincInsnNode => iinc.`var` += localVarShift case _ => () } @@ -378,7 +401,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { val inlinedReturn = instructionMap(originalReturn) val returnReplacement = new InsnList - def drop(slot: Int) = returnReplacement add getPop(frame.peekDown(slot).getSize) + def drop(slot: Int) = returnReplacement add getPop(frame.peekStack(slot).getSize) // for non-void methods, store the stack top into the return local variable if (hasReturnValue) { @@ -422,6 +445,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { callee = originalCallsite.callee, argInfos = Nil, // TODO: re-compute argInfos for new destination (once we actually compute them) callsiteStackHeight = callsiteStackHeight + originalCallsite.callsiteStackHeight, + receiverKnownNotNull = originalCallsite.receiverKnownNotNull, callsitePosition = originalCallsite.callsitePosition ) @@ -433,6 +457,9 @@ class Inliner[BT <: BTypes](val btypes: BT) { // Remove the elided invocation from the call graph callGraph.callsites.remove(callsiteInstruction) + // Inlining a method body can render some code unreachable, see example above (in runInliner). + unreachableCodeEliminated -= callsiteMethod + callsiteMethod.maxLocals += returnType.getSize + callee.maxLocals callsiteMethod.maxStack = math.max(callsiteMethod.maxStack, callee.maxStack + callsiteStackHeight) @@ -472,10 +499,18 @@ class Inliner[BT <: BTypes](val btypes: BT) { callsiteStackHeight > expectedArgs } - if (isSynchronizedMethod(callee)) { + if (codeSizeOKForInlining(callsiteMethod, callee)) { + Some(ResultingMethodTooLarge( + calleeDeclarationClass.internalName, callee.name, callee.desc, + callsiteClass.internalName, callsiteMethod.name, callsiteMethod.desc)) + } else if (isSynchronizedMethod(callee)) { // Could be done by locking on the receiver, wrapping the inlined code in a try and unlocking // in finally. But it's probably not worth the effort, scala never emits synchronized methods. Some(SynchronizedMethod(calleeDeclarationClass.internalName, callee.name, callee.desc)) + } else if (isStrictfpMethod(callsiteMethod) != isStrictfpMethod(callee)) { + Some(StrictfpMismatch( + calleeDeclarationClass.internalName, callee.name, callee.desc, + callsiteClass.internalName, callsiteMethod.name, callsiteMethod.desc)) } else if (!callee.tryCatchBlocks.isEmpty && stackHasNonParameters) { Some(MethodWithHandlerCalledOnNonEmptyStack( calleeDeclarationClass.internalName, callee.name, callee.desc, diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/InstructionResultSize.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/InstructionResultSize.scala new file mode 100644 index 0000000000..8d744f6d13 --- /dev/null +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/InstructionResultSize.scala @@ -0,0 +1,240 @@ +package scala.tools.nsc.backend.jvm.opt + +import scala.annotation.switch +import scala.tools.asm.{Handle, Type, Opcodes} +import scala.tools.asm.tree._ + +object InstructionResultSize { + import Opcodes._ + def apply(instruction: AbstractInsnNode): Int = (instruction.getOpcode: @switch) match { + // The order of opcodes is (almost) the same as in Opcodes.java + case ACONST_NULL => 1 + + case ICONST_M1 | + ICONST_0 | + ICONST_1 | + ICONST_2 | + ICONST_3 | + ICONST_4 | + ICONST_5 => 1 + + case LCONST_0 | + LCONST_1 => 2 + + case FCONST_0 | + FCONST_1 | + FCONST_2 => 1 + + case DCONST_0 | + DCONST_1 => 2 + + case BIPUSH | + SIPUSH => 1 + + case LDC => + instruction.asInstanceOf[LdcInsnNode].cst match { + case _: java.lang.Integer | + _: java.lang.Float | + _: String | + _: Type | + _: Handle => 1 + + case _: java.lang.Long | + _: java.lang.Double => 2 + } + + case ILOAD | + FLOAD | + ALOAD => 1 + + case LLOAD | + DLOAD => 2 + + case IALOAD | + FALOAD | + AALOAD | + BALOAD | + CALOAD | + SALOAD => 1 + + case LALOAD | + DALOAD => 2 + + case ISTORE | + LSTORE | + FSTORE | + DSTORE | + ASTORE => 0 + + case IASTORE | + LASTORE | + FASTORE | + DASTORE | + AASTORE | + BASTORE | + CASTORE | + SASTORE => 0 + + case POP | + POP2 => 0 + + case DUP | + DUP_X1 | + DUP_X2 | + DUP2 | + DUP2_X1 | + DUP2_X2 | + SWAP => throw new IllegalArgumentException("Can't compute the size of DUP/SWAP without knowing what's on stack top") + + case IADD | + FADD => 1 + + case LADD | + DADD => 2 + + case ISUB | + FSUB => 1 + + case LSUB | + DSUB => 2 + + case IMUL | + FMUL => 1 + + case LMUL | + DMUL => 2 + + case IDIV | + FDIV => 1 + + case LDIV | + DDIV => 2 + + case IREM | + FREM => 1 + + case LREM | + DREM => 2 + + case INEG | + FNEG => 1 + + case LNEG | + DNEG => 2 + + case ISHL | + ISHR => 1 + + case LSHL | + LSHR => 2 + + case IUSHR => 1 + + case LUSHR => 2 + + case IAND | + IOR | + IXOR => 1 + + case LAND | + LOR | + LXOR => 2 + + case IINC => 1 + + case I2F | + L2I | + L2F | + F2I | + D2I | + D2F | + I2B | + I2C | + I2S => 1 + + case I2L | + I2D | + L2D | + F2L | + F2D | + D2L => 2 + + case LCMP | + FCMPL | + FCMPG | + DCMPL | + DCMPG => 1 + + case IFEQ | + IFNE | + IFLT | + IFGE | + IFGT | + IFLE => 0 + + case IF_ICMPEQ | + IF_ICMPNE | + IF_ICMPLT | + IF_ICMPGE | + IF_ICMPGT | + IF_ICMPLE | + IF_ACMPEQ | + IF_ACMPNE => 0 + + case GOTO => 0 + + case JSR => throw new IllegalArgumentException("Subroutines are not supported.") + + case RET => 0 + + case TABLESWITCH | + LOOKUPSWITCH => 0 + + case IRETURN | + FRETURN | + ARETURN => 1 + + case LRETURN | + DRETURN => 2 + + case RETURN => 0 + + case GETSTATIC => Type.getType(instruction.asInstanceOf[FieldInsnNode].desc).getSize + + case PUTSTATIC => 0 + + case GETFIELD => Type.getType(instruction.asInstanceOf[FieldInsnNode].desc).getSize + + case PUTFIELD => 0 + + case INVOKEVIRTUAL | + INVOKESPECIAL | + INVOKESTATIC | + INVOKEINTERFACE => + val desc = instruction.asInstanceOf[MethodInsnNode].desc + Type.getReturnType(desc).getSize + + case INVOKEDYNAMIC => + val desc = instruction.asInstanceOf[InvokeDynamicInsnNode].desc + Type.getReturnType(desc).getSize + + case NEW => 1 + + case NEWARRAY | + ANEWARRAY | + ARRAYLENGTH => 1 + + case ATHROW => 0 + + case CHECKCAST | + INSTANCEOF => 1 + + case MONITORENTER | + MONITOREXIT => 0 + + case MULTIANEWARRAY => 1 + + case IFNULL | + IFNONNULL => 0 + } +} 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 f6cfc5598b..5f51a94673 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala @@ -14,7 +14,6 @@ import scala.tools.asm.tree._ import scala.collection.convert.decorateAsScala._ import scala.tools.nsc.backend.jvm.BTypes.InternalName import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._ -import scala.tools.nsc.settings.ScalaSettings /** * Optimizations within a single method. @@ -47,18 +46,9 @@ import scala.tools.nsc.settings.ScalaSettings * stale labels * - eliminate labels that are not referenced, merge sequences of label definitions. */ -class LocalOpt(settings: ScalaSettings) { - /** - * Remove unreachable code from all methods of `classNode`. See of its overload. - * - * @param classNode The class to optimize - * @return `true` if unreachable code was removed from any method - */ - def minimalRemoveUnreachableCode(classNode: ClassNode): Boolean = { - classNode.methods.asScala.foldLeft(false) { - case (changed, method) => minimalRemoveUnreachableCode(method, classNode.name) || changed - } - } +class LocalOpt[BT <: BTypes](val btypes: BT) { + import LocalOptImpls._ + import btypes._ /** * Remove unreachable code from a method. @@ -66,25 +56,30 @@ class LocalOpt(settings: ScalaSettings) { * This implementation only removes instructions that are unreachable for an ASM analyzer / * interpreter. This ensures that future analyses will not produce `null` frames. The inliner * and call graph builder depend on this property. + * + * @return A set containing the eliminated instructions */ - def minimalRemoveUnreachableCode(method: MethodNode, ownerClassName: InternalName): Boolean = { - if (method.instructions.size == 0) return false // fast path for abstract methods + def minimalRemoveUnreachableCode(method: MethodNode, ownerClassName: InternalName): Set[AbstractInsnNode] = { + if (method.instructions.size == 0) return Set.empty // fast path for abstract methods + if (unreachableCodeEliminated(method)) return Set.empty // we know there is no unreachable code // For correctness, after removing unreachable code, we have to eliminate empty exception // handlers, see scaladoc of def methodOptimizations. Removing an live handler may render more // code unreachable and therefore requires running another round. - def removalRound(): Boolean = { - val (codeRemoved, liveLabels) = removeUnreachableCodeImpl(method, ownerClassName) - if (codeRemoved) { + def removalRound(): Set[AbstractInsnNode] = { + val (removedInstructions, liveLabels) = removeUnreachableCodeImpl(method, ownerClassName) + val removedRecursively = if (removedInstructions.nonEmpty) { val liveHandlerRemoved = removeEmptyExceptionHandlers(method).exists(h => liveLabels(h.start)) if (liveHandlerRemoved) removalRound() - } - codeRemoved + else Set.empty + } else Set.empty + removedInstructions ++ removedRecursively } - val codeRemoved = removalRound() - if (codeRemoved) removeUnusedLocalVariableNodes(method)() - codeRemoved + val removedInstructions = removalRound() + if (removedInstructions.nonEmpty) removeUnusedLocalVariableNodes(method)() + unreachableCodeEliminated += method + removedInstructions } /** @@ -95,7 +90,7 @@ class LocalOpt(settings: ScalaSettings) { * @return `true` if unreachable code was eliminated in some method, `false` otherwise. */ def methodOptimizations(clazz: ClassNode): Boolean = { - !settings.YoptNone && clazz.methods.asScala.foldLeft(false) { + !compilerSettings.YoptNone && clazz.methods.asScala.foldLeft(false) { case (changed, method) => methodOptimizations(method, clazz.name) || changed } } @@ -144,15 +139,15 @@ class LocalOpt(settings: ScalaSettings) { def removalRound(): Boolean = { // unreachable-code, empty-handlers and simplify-jumps run until reaching a fixpoint (see doc on class LocalOpt) - val (codeRemoved, handlersRemoved, liveHandlerRemoved) = if (settings.YoptUnreachableCode) { - val (codeRemoved, liveLabels) = removeUnreachableCodeImpl(method, ownerClassName) + val (codeRemoved, handlersRemoved, liveHandlerRemoved) = if (compilerSettings.YoptUnreachableCode) { + val (removedInstructions, liveLabels) = removeUnreachableCodeImpl(method, ownerClassName) val removedHandlers = removeEmptyExceptionHandlers(method) - (codeRemoved, removedHandlers.nonEmpty, removedHandlers.exists(h => liveLabels(h.start))) + (removedInstructions.nonEmpty, removedHandlers.nonEmpty, removedHandlers.exists(h => liveLabels(h.start))) } else { (false, false, false) } - val jumpsChanged = if (settings.YoptSimplifyJumps) simplifyJumps(method) else false + val jumpsChanged = if (compilerSettings.YoptSimplifyJumps) simplifyJumps(method) else false // Eliminating live handlers and simplifying jump instructions may render more code // unreachable, so we need to run another round. @@ -165,13 +160,13 @@ class LocalOpt(settings: ScalaSettings) { // (*) Removing stale local variable descriptors is required for correctness of unreachable-code val localsRemoved = - if (settings.YoptCompactLocals) compactLocalVariables(method) // also removes unused - else if (settings.YoptUnreachableCode) removeUnusedLocalVariableNodes(method)() // (*) + if (compilerSettings.YoptCompactLocals) compactLocalVariables(method) // also removes unused + else if (compilerSettings.YoptUnreachableCode) removeUnusedLocalVariableNodes(method)() // (*) else false - val lineNumbersRemoved = if (settings.YoptEmptyLineNumbers) removeEmptyLineNumbers(method) else false + val lineNumbersRemoved = if (compilerSettings.YoptEmptyLineNumbers) removeEmptyLineNumbers(method) else false - val labelsRemoved = if (settings.YoptEmptyLabels) removeEmptyLabelNodes(method) else false + val labelsRemoved = if (compilerSettings.YoptEmptyLabels) removeEmptyLabelNodes(method) else false // assert that local variable annotations are empty (we don't emit them) - otherwise we'd have // to eliminate those covering an empty range, similar to removeUnusedLocalVariableNodes. @@ -179,15 +174,22 @@ class LocalOpt(settings: ScalaSettings) { assert(nullOrEmpty(method.visibleLocalVariableAnnotations), method.visibleLocalVariableAnnotations) assert(nullOrEmpty(method.invisibleLocalVariableAnnotations), method.invisibleLocalVariableAnnotations) + unreachableCodeEliminated += method + codeHandlersOrJumpsChanged || localsRemoved || lineNumbersRemoved || labelsRemoved } +} + +object LocalOptImpls { /** * Removes unreachable basic blocks. * * TODO: rewrite, don't use computeMaxLocalsMaxStack (runs a ClassWriter) / Analyzer. Too slow. + * + * @return A set containing eliminated instructions, and a set containing all live label nodes. */ - def removeUnreachableCodeImpl(method: MethodNode, ownerClassName: InternalName): (Boolean, Set[LabelNode]) = { + def removeUnreachableCodeImpl(method: MethodNode, ownerClassName: InternalName): (Set[AbstractInsnNode], Set[LabelNode]) = { // The data flow analysis requires the maxLocals / maxStack fields of the method to be computed. computeMaxLocalsMaxStack(method) val a = new Analyzer(new BasicInterpreter) @@ -197,6 +199,7 @@ class LocalOpt(settings: ScalaSettings) { val initialSize = method.instructions.size var i = 0 var liveLabels = Set.empty[LabelNode] + var removedInstructions = Set.empty[AbstractInsnNode] val itr = method.instructions.iterator() while (itr.hasNext) { itr.next() match { @@ -209,11 +212,12 @@ class LocalOpt(settings: ScalaSettings) { // Instruction iterators allow removing during iteration. // Removing is O(1): instructions are doubly linked list elements. itr.remove() + removedInstructions += ins } } i += 1 } - (method.instructions.size != initialSize, liveLabels) + (removedInstructions, liveLabels) } /** diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala index 3704acb055..1b6631e7a4 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala @@ -173,7 +173,7 @@ abstract class DeadCodeElimination extends SubComponent { moveToWorkList() case LOAD_FIELD(sym, isStatic) if isStatic || !inliner.isClosureClass(sym.owner) => - // static load may trigger static initization. + // static load may trigger static initialization. // non-static load can throw NPE (but we know closure fields can't be accessed via a // null reference. moveToWorkList() @@ -191,7 +191,7 @@ abstract class DeadCodeElimination extends SubComponent { case LOAD_EXCEPTION(_) | DUP(_) | LOAD_MODULE(_) => true case _ => dropOf((bb1, idx1)) = (bb,idx) :: dropOf.getOrElse((bb1, idx1), Nil) - debuglog("DROP is innessential: " + i + " because of: " + bb1(idx1) + " at " + bb1 + ":" + idx1) + debuglog("DROP is inessential: " + i + " because of: " + bb1(idx1) + " at " + bb1 + ":" + idx1) false } } diff --git a/src/compiler/scala/tools/nsc/plugins/Plugin.scala b/src/compiler/scala/tools/nsc/plugins/Plugin.scala index 5a7a0df595..1a5529140c 100644 --- a/src/compiler/scala/tools/nsc/plugins/Plugin.scala +++ b/src/compiler/scala/tools/nsc/plugins/Plugin.scala @@ -60,13 +60,15 @@ abstract class Plugin { * @return true to continue, or false to opt out */ def init(options: List[String], error: String => Unit): Boolean = { - if (!options.isEmpty) error(s"Error: $name takes no options") + // call to deprecated method required here, we must continue to support + // code that subclasses that override `processOptions`. + processOptions(options, error) true } @deprecated("use Plugin#init instead", since="2.11") def processOptions(options: List[String], error: String => Unit): Unit = { - init(options, error) + if (!options.isEmpty) error(s"Error: $name takes no options") } /** A description of this plugin's options, suitable as a response diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index d273995e6e..953e43eaca 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -101,7 +101,8 @@ trait ScalaSettings extends AbsScalaSettings val Xhelp = BooleanSetting ("-X", "Print a synopsis of advanced options.") val checkInit = BooleanSetting ("-Xcheckinit", "Wrap field accessors to throw an exception on uninitialized access.") val developer = BooleanSetting ("-Xdev", "Indicates user is a developer - issue warnings about anything which seems amiss") - val noassertions = BooleanSetting ("-Xdisable-assertions", "Generate no assertions or assumptions.") + val noassertions = BooleanSetting ("-Xdisable-assertions", "Generate no assertions or assumptions.") andThen (flag => + if (flag) elidebelow.value = elidable.ASSERTION + 1) val elidebelow = IntSetting ("-Xelide-below", "Calls to @elidable methods are omitted if method priority is lower than argument", elidable.MINIMUM, None, elidable.byName get _) val noForwarders = BooleanSetting ("-Xno-forwarders", "Do not generate static forwarders in mirror classes.") @@ -139,6 +140,18 @@ trait ScalaSettings extends AbsScalaSettings val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.") val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.") + // XML parsing options + object XxmlSettings extends MultiChoiceEnumeration { + val coalescing = Choice("coalescing", "Convert PCData to Text and coalesce sibling nodes") + def isCoalescing = (Xxml contains coalescing) || (!isScala212 && !Xxml.isSetByUser) + } + val Xxml = MultiChoiceSetting( + name = "-Xxml", + helpArg = "property", + descr = "Configure XML parsing", + domain = XxmlSettings + ) + /** Compatibility stubs for options whose value name did * not previously match the option name. */ @@ -221,15 +234,16 @@ trait ScalaSettings extends AbsScalaSettings val emptyLineNumbers = Choice("empty-line-numbers", "Eliminate unnecessary line number information.") val emptyLabels = Choice("empty-labels", "Eliminate and collapse redundant labels in the bytecode.") val compactLocals = Choice("compact-locals", "Eliminate empty slots in the sequence of local variables.") - val inlineProject = Choice("inline-project", "Inline only methods defined in the files being compiled") - val inlineGlobal = Choice("inline-global", "Inline methods from any source, including classfiles on the compile classpath") + val nullnessTracking = Choice("nullness-tracking", "Track nullness / non-nullness of local variables and apply optimizations.") + val inlineProject = Choice("inline-project", "Inline only methods defined in the files being compiled.") + val inlineGlobal = Choice("inline-global", "Inline methods from any source, including classfiles on the compile classpath.") val lNone = Choice("l:none", "Don't enable any optimizations.") private val defaultChoices = List(unreachableCode) val lDefault = Choice("l:default", "Enable default optimizations: "+ defaultChoices.mkString(","), expandsTo = defaultChoices) - private val methodChoices = List(unreachableCode, simplifyJumps, emptyLineNumbers, emptyLabels, compactLocals) + private val methodChoices = List(unreachableCode, simplifyJumps, emptyLineNumbers, emptyLabels, compactLocals, nullnessTracking) val lMethod = Choice("l:method", "Enable intra-method optimizations: "+ methodChoices.mkString(","), expandsTo = methodChoices) private val projectChoices = List(lMethod, inlineProject) @@ -251,11 +265,19 @@ trait ScalaSettings extends AbsScalaSettings def YoptEmptyLineNumbers = Yopt.contains(YoptChoices.emptyLineNumbers) def YoptEmptyLabels = Yopt.contains(YoptChoices.emptyLabels) def YoptCompactLocals = Yopt.contains(YoptChoices.compactLocals) + def YoptNullnessTracking = Yopt.contains(YoptChoices.nullnessTracking) def YoptInlineProject = Yopt.contains(YoptChoices.inlineProject) def YoptInlineGlobal = Yopt.contains(YoptChoices.inlineGlobal) def YoptInlinerEnabled = YoptInlineProject || YoptInlineGlobal + val YoptInlineHeuristics = ChoiceSetting( + name = "-Yopt-inline-heuristics", + helpArg = "strategy", + descr = "Set the heuristics for inlining decisions.", + choices = List("at-inline-annotated", "everything"), + default = "at-inline-annotated") + object YoptWarningsChoices extends MultiChoiceEnumeration { val none = Choice("none" , "No optimizer warnings.") val atInlineFailedSummary = Choice("at-inline-failed-summary" , "One-line summary if there were @inline method calls that could not be inlined.") @@ -267,7 +289,7 @@ trait ScalaSettings extends AbsScalaSettings val YoptWarnings = MultiChoiceSetting( name = "-Yopt-warnings", - helpArg = "warnings", + helpArg = "warning", descr = "Enable optimizer warnings", domain = YoptWarningsChoices, default = Some(List(YoptWarningsChoices.atInlineFailed.name))) withPostSetHook (self => { @@ -275,6 +297,15 @@ trait ScalaSettings extends AbsScalaSettings else YinlinerWarnings.value = true }) + def YoptWarningEmitAtInlineFailed = + !YoptWarnings.isSetByUser || + YoptWarnings.contains(YoptWarningsChoices.atInlineFailedSummary) || + YoptWarnings.contains(YoptWarningsChoices.atInlineFailed) + + def YoptWarningNoInlineMixed = YoptWarnings.contains(YoptWarningsChoices.noInlineMixed) + def YoptWarningNoInlineMissingBytecode = YoptWarnings.contains(YoptWarningsChoices.noInlineMissingBytecode) + def YoptWarningNoInlineMissingScalaInlineInfoAttr = YoptWarnings.contains(YoptWarningsChoices.noInlineMissingScalaInlineInfoAttr) + 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." object YstatisticsPhases extends MultiChoiceEnumeration { val parser, typer, patmat, erasure, cleanup, jvm = Value } @@ -345,12 +376,7 @@ trait ScalaSettings extends AbsScalaSettings /** Test whether this is scaladoc we're looking at */ def isScaladoc = false - /** - * Helper utilities for use by checkConflictingSettings() - */ - def isBCodeActive = !isICodeAskedFor - def isBCodeAskedFor = (Ybackend.value != "GenASM") - def isICodeAskedFor = ((Ybackend.value == "GenASM") || optimiseSettings.exists(_.value) || writeICode.isSetByUser) + def isBCodeActive = Ybackend.value == "GenBCode" object MacroExpand { val None = "none" diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala index 41ce0837cb..59cc13c64e 100644 --- a/src/compiler/scala/tools/nsc/settings/Warnings.scala +++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala @@ -23,7 +23,7 @@ trait Warnings { val warnValueDiscard = BooleanSetting("-Ywarn-value-discard", "Warn when non-Unit expression results are unused.") val warnNumericWiden = BooleanSetting("-Ywarn-numeric-widen", "Warn when numerics are widened.") // SI-7712, SI-7707 warnUnused not quite ready for prime-time - val warnUnused = BooleanSetting("-Ywarn-unused", "Warn when local and private vals, vars, defs, and types are are unused.") + val warnUnused = BooleanSetting("-Ywarn-unused", "Warn when local and private vals, vars, defs, and types are unused.") // currently considered too noisy for general use val warnUnusedImport = BooleanSetting("-Ywarn-unused-import", "Warn when imports are unused.") diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 8fd2ea45e4..a22428075c 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -8,7 +8,6 @@ package symtab import classfile.ClassfileParser import java.io.IOException -import scala.compat.Platform.currentTime import scala.reflect.internal.MissingRequirementError import scala.reflect.internal.util.Statistics import scala.reflect.io.{ AbstractFile, NoAbstractFile } @@ -207,7 +206,7 @@ abstract class SymbolLoaders { override def complete(root: Symbol) { try { - val start = currentTime + val start = java.util.concurrent.TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) val currentphase = phase doComplete(root) phase = currentphase diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 1ffa064b78..518a402230 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -15,6 +15,7 @@ import scala.collection.mutable.{ ListBuffer, ArrayBuffer } import scala.annotation.switch import scala.reflect.internal.{ JavaAccFlags } import scala.reflect.internal.pickling.{PickleBuffer, ByteCodecs} +import scala.reflect.io.NoAbstractFile import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.util.ClassFileLookup @@ -52,6 +53,7 @@ abstract class ClassfileParser { protected type ThisConstantPool <: ConstantPool protected def newConstantPool: ThisConstantPool + protected var file: AbstractFile = _ // the class file protected var in: AbstractFileReader = _ // the class file reader protected var clazz: Symbol = _ // the class symbol containing dynamic members protected var staticModule: Symbol = _ // the module symbol containing static members @@ -96,14 +98,14 @@ abstract class ClassfileParser { private def handleMissing(e: MissingRequirementError) = { if (settings.debug) e.printStackTrace - throw new IOException(s"Missing dependency '${e.req}', required by ${in.file}") + throw new IOException(s"Missing dependency '${e.req}', required by $file") } private def handleError(e: Exception) = { if (settings.debug) e.printStackTrace() - throw new IOException(s"class file '${in.file}' is broken\n(${e.getClass}/${e.getMessage})") + throw new IOException(s"class file '$file' is broken\n(${e.getClass}/${e.getMessage})") } private def mismatchError(c: Symbol) = { - throw new IOException(s"class file '${in.file}' has location not matching its contents: contains $c") + throw new IOException(s"class file '$file' has location not matching its contents: contains $c") } private def parseErrorHandler[T]: PartialFunction[Throwable, T] = { @@ -130,6 +132,7 @@ abstract class ClassfileParser { def parse(file: AbstractFile, root: Symbol): Unit = { debuglog("[class] >> " + root.fullName) + this.file = file pushBusy(root) { this.in = new AbstractFileReader(file) this.clazz = if (root.isModule) root.companionClass else root @@ -922,6 +925,7 @@ abstract class ClassfileParser { Some(ScalaSigBytes(pool.getBytes(entries.toList))) } + // TODO SI-9296 duplicated code, refactor /* Parse and return a single annotation. If it is malformed, * return None. */ @@ -1022,11 +1026,18 @@ abstract class ClassfileParser { val sflags = jflags.toScalaFlags val owner = ownerForFlags(jflags) val scope = getScope(jflags) - val innerClass = owner.newClass(name.toTypeName, NoPosition, sflags) setInfo completer - val innerModule = owner.newModule(name.toTermName, NoPosition, sflags) setInfo completer + def newStub(name: Name) = + owner.newStubSymbol(name, s"Class file for ${entry.externalName} not found").setFlag(JAVA) - innerModule.moduleClass setInfo loaders.moduleClassLoader - List(innerClass, innerModule.moduleClass) foreach (_.associatedFile = file) + val (innerClass, innerModule) = if (file == NoAbstractFile) { + (newStub(name.toTypeName), newStub(name.toTermName)) + } else { + val cls = owner.newClass(name.toTypeName, NoPosition, sflags) setInfo completer + val mod = owner.newModule(name.toTermName, NoPosition, sflags) setInfo completer + mod.moduleClass setInfo loaders.moduleClassLoader + List(cls, mod.moduleClass) foreach (_.associatedFile = file) + (cls, mod) + } scope enter innerClass scope enter innerModule @@ -1046,10 +1057,8 @@ abstract class ClassfileParser { for (entry <- innerClasses.entries) { // create a new class member for immediate inner classes if (entry.outerName == currentClass) { - val file = classFileLookup.findClassFile(entry.externalName.toString) getOrElse { - throw new AssertionError(s"Class file for ${entry.externalName} not found") - } - enterClassAndModule(entry, file) + val file = classFileLookup.findClassFile(entry.externalName.toString) + enterClassAndModule(entry, file.getOrElse(NoAbstractFile)) } } } @@ -1135,16 +1144,12 @@ abstract class ClassfileParser { private def innerSymbol(entry: InnerClassEntry): Symbol = { val name = entry.originalName.toTypeName val enclosing = entry.enclosing - def getMember = ( + val member = ( if (enclosing == clazz) entry.scope lookup name else lookupMemberAtTyperPhaseIfPossible(enclosing, name) ) - getMember - /* There used to be an assertion that this result is not NoSymbol; changing it to an error - * revealed it had been going off all the time, but has been swallowed by a catch t: Throwable - * in Repository.scala. Since it has been accomplishing nothing except misleading anyone who - * thought it wasn't triggering, I removed it entirely. - */ + def newStub = enclosing.newStubSymbol(name, s"Unable to locate class corresponding to inner class entry for $name in owner ${entry.outerName}") + member.orElse(newStub) } } diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 3591372bbe..79776485de 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -207,7 +207,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => } def transformMixinInfo(tp: Type): Type = tp match { - case ClassInfoType(parents, decls, clazz) => + case ClassInfoType(parents, decls, clazz) if clazz.isPackageClass || !clazz.isJavaDefined => if (clazz.needsImplClass) implClass(clazz setFlag lateINTERFACE) // generate an impl class diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index d0fca12e6a..86685d46de 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -315,7 +315,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { } def rewriteDelayedInit() { - /* XXX This is not corect: remainingConstrStats.nonEmpty excludes too much, + /* XXX This is not correct: remainingConstrStats.nonEmpty excludes too much, * but excluding it includes too much. The constructor sequence being mimicked * needs to be reproduced with total fidelity. * diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 94e88589f5..55ab73028e 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -9,23 +9,29 @@ import scala.reflect.internal.Symbols import scala.collection.mutable.LinkedHashMap /** - * This transformer is responsible for turning lambdas into anonymous classes. + * This transformer is responsible for preparing lambdas for runtime, by either translating to anonymous classes + * or to a tree that will be convereted to invokedynamic by the JVM 1.8+ backend. + * * The main assumption it makes is that a lambda {args => body} has been turned into * {args => liftedBody()} where lifted body is a top level method that implements the body of the lambda. * Currently Uncurry is responsible for that transformation. * - * From a lambda, Delambdafy will create - * 1) a static forwarder at the top level of the class that contained the lambda - * 2) a new top level class that + * From a lambda, Delambdafy will create: + * + * Under -target:jvm-1.7 and below: + * + * 1) a new top level class that a) has fields and a constructor taking the captured environment (including possibly the "this" * reference) - * b) an apply method that calls the static forwarder + * b) an apply method that calls the target method * c) if needed a bridge method for the apply method - * 3) an instantiation of the newly created class which replaces the lambda + * 2) an instantiation of the newly created class which replaces the lambda * - * TODO the main work left to be done is to plug into specialization. Primarily that means choosing a - * specialized FunctionN trait instead of the generic FunctionN trait as a parent and creating the - * appropriately named applysp method + * Under -target:jvm-1.8 with GenBCode: + * + * 1) An application of the captured arguments to a fictional symbol representing the lambda factory. + * This will be translated by the backed into an invokedynamic using a bootstrap method in JDK8's `LambdaMetaFactory`. + * The captured arguments include `this` if `liftedBody` is unable to be made STATIC. */ abstract class Delambdafy extends Transform with TypingTransformers with ast.TreeDSL with TypeAdaptingTransformer { import global._ @@ -76,36 +82,37 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre referrers } - val accessorMethods = mutable.ArrayBuffer[Tree]() + // the result of the transformFunction method. + sealed abstract class TransformedFunction + // A class definition for the lambda, an expression instantiating the lambda class + case class DelambdafyAnonClass(lambdaClassDef: ClassDef, newExpr: Tree) extends TransformedFunction + case class InvokeDynamicLambda(tree: Apply) extends TransformedFunction - // the result of the transformFunction method. A class definition for the lambda, an expression - // insantiating the lambda class, and an accessor method for the lambda class to be able to - // call the implementation - case class TransformedFunction(lambdaClassDef: ClassDef, newExpr: Tree, accessorMethod: Tree) + private val boxingBridgeMethods = mutable.ArrayBuffer[Tree]() // here's the main entry point of the transform override def transform(tree: Tree): Tree = tree match { // the main thing we care about is lambdas case fun @ Function(_, _) => - // a lambda beccomes a new class, an instantiation expression, and an - // accessor method - val TransformedFunction(lambdaClassDef, newExpr, accessorMethod) = transformFunction(fun) - // we'll add accessor methods to the current template later - accessorMethods += accessorMethod - val pkg = lambdaClassDef.symbol.owner - - // we'll add the lambda class to the package later - lambdaClassDefs(pkg) = lambdaClassDef :: lambdaClassDefs(pkg) - - super.transform(newExpr) - // when we encounter a template (basically the thing that holds body of a class/trait) - // we need to updated it to include newly created accessor methods after transforming it + transformFunction(fun) match { + case DelambdafyAnonClass(lambdaClassDef, newExpr) => + // a lambda becomes a new class, an instantiation expression + val pkg = lambdaClassDef.symbol.owner + + // we'll add the lambda class to the package later + lambdaClassDefs(pkg) = lambdaClassDef :: lambdaClassDefs(pkg) + + super.transform(newExpr) + case InvokeDynamicLambda(apply) => + // ... or an invokedynamic call + super.transform(apply) + } case Template(_, _, _) => try { - // during this call accessorMethods will be populated from the Function case + // during this call boxingBridgeMethods will be populated from the Function case val Template(parents, self, body) = super.transform(tree) - Template(parents, self, body ++ accessorMethods) - } finally accessorMethods.clear() + Template(parents, self, body ++ boxingBridgeMethods) + } finally boxingBridgeMethods.clear() case _ => super.transform(tree) } @@ -120,8 +127,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre private def optionSymbol(sym: Symbol): Option[Symbol] = if (sym.exists) Some(sym) else None - // turns a lambda into a new class def, a New expression instantiating that class, and an - // accessor method fo the body of the lambda + // turns a lambda into a new class def, a New expression instantiating that class private def transformFunction(originalFunction: Function): TransformedFunction = { val functionTpe = originalFunction.tpe val targs = functionTpe.typeArgs @@ -132,46 +138,75 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // passed into the constructor of the anonymous function class val captures = FreeVarTraverser.freeVarsOf(originalFunction) - /** - * Creates the apply method for the anonymous subclass of FunctionN - */ - def createAccessorMethod(thisProxy: Symbol, fun: Function): DefDef = { - val target = targetMethod(fun) - if (!thisProxy.exists) { - target setFlag STATIC + val target = targetMethod(originalFunction) + target.makeNotPrivate(target.owner) + if (!thisReferringMethods.contains(target)) + target setFlag STATIC + + val isStatic = target.hasFlag(STATIC) + + def createBoxingBridgeMethod(functionParamTypes: List[Type], functionResultType: Type): Tree = { + // Note: we bail out of this method and return EmptyTree if we find there is no adaptation required. + // If we need to improve performance, we could check the types first before creating the + // method and parameter symbols. + val methSym = oldClass.newMethod(target.name.append("$adapted").toTermName, target.pos, target.flags | FINAL | ARTIFACT) + var neededAdaptation = false + def boxedType(tpe: Type): Type = { + if (isPrimitiveValueClass(tpe.typeSymbol)) {neededAdaptation = true; ObjectTpe} + else if (enteringErasure(tpe.typeSymbol.isDerivedValueClass)) {neededAdaptation = true; ObjectTpe} + else tpe } - val params = ((optionSymbol(thisProxy) map {proxy:Symbol => ValDef(proxy)}) ++ (target.paramss.flatten map ValDef.apply)).toList - - val methSym = oldClass.newMethod(unit.freshTermName(nme.accessor.toString() + "$"), target.pos, FINAL | BRIDGE | SYNTHETIC | PROTECTED | STATIC) - - val paramSyms = params map {param => methSym.newSyntheticValueParam(param.symbol.tpe, param.name) } - - params zip paramSyms foreach { case (valdef, sym) => valdef.symbol = sym } - params foreach (_.symbol.owner = methSym) - - val methodType = MethodType(paramSyms, restpe) + val targetParams: List[Symbol] = target.paramss.head + val numCaptures = targetParams.length - functionParamTypes.length + val (targetCaptureParams, targetFunctionParams) = targetParams.splitAt(numCaptures) + val bridgeParams: List[Symbol] = + targetCaptureParams.map(param => methSym.newSyntheticValueParam(param.tpe, param.name.toTermName)) ::: + map2(targetFunctionParams, functionParamTypes)((param, tp) => methSym.newSyntheticValueParam(boxedType(tp), param.name.toTermName)) + + val bridgeResultType: Type = { + if (target.info.resultType == UnitTpe && functionResultType != UnitTpe) { + neededAdaptation = true + ObjectTpe + } else + boxedType(functionResultType) + } + val methodType = MethodType(bridgeParams, bridgeResultType) methSym setInfo methodType - - oldClass.info.decls enter methSym - - val body = localTyper.typed { - val newTarget = Select(if (thisProxy.exists) gen.mkAttributedRef(paramSyms(0)) else gen.mkAttributedThis(oldClass), target) - val newParams = paramSyms drop (if (thisProxy.exists) 1 else 0) map Ident - Apply(newTarget, newParams) - } setPos fun.pos - val methDef = DefDef(methSym, List(params), body) - - // Have to repack the type to avoid mismatches when existentials - // appear in the result - see SI-4869. - // TODO probably don't need packedType - methDef.tpt setType localTyper.packedType(body, methSym) - methDef + if (!neededAdaptation) + EmptyTree + else { + val bridgeParamTrees = bridgeParams.map(ValDef(_)) + + oldClass.info.decls enter methSym + + val body = localTyper.typedPos(originalFunction.pos) { + val newTarget = Select(gen.mkAttributedThis(oldClass), target) + val args: List[Tree] = mapWithIndex(bridgeParams) { (param, i) => + if (i < numCaptures) { + gen.mkAttributedRef(param) + } else { + val functionParam = functionParamTypes(i - numCaptures) + val targetParam = targetParams(i) + if (enteringErasure(functionParam.typeSymbol.isDerivedValueClass)) { + val casted = cast(gen.mkAttributedRef(param), functionParam) + val unboxed = unbox(casted, ErasedValueType(functionParam.typeSymbol, targetParam.tpe)).modifyType(postErasure.elimErasedValueType) + unboxed + } else adaptToType(gen.mkAttributedRef(param), targetParam.tpe) + } + } + gen.mkMethodCall(newTarget, args) + } + val body1 = if (enteringErasure(functionResultType.typeSymbol.isDerivedValueClass)) + adaptToType(box(body.setType(ErasedValueType(functionResultType.typeSymbol, body.tpe)), "boxing lambda target"), bridgeResultType) + else adaptToType(body, bridgeResultType) + val methDef0 = DefDef(methSym, List(bridgeParamTrees), body1) + postErasure.newTransformer(unit).transform(methDef0).asInstanceOf[DefDef] + } } - /** * Creates the apply method for the anonymous subclass of FunctionN */ - def createApplyMethod(newClass: Symbol, fun: Function, accessor: DefDef, thisProxy: Symbol): DefDef = { + def createApplyMethod(newClass: Symbol, fun: Function, thisProxy: Symbol): DefDef = { val methSym = newClass.newMethod(nme.apply, fun.pos, FINAL | SYNTHETIC) val params = fun.vparams map (_.duplicate) @@ -187,8 +222,12 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre newClass.info.decls enter methSym val Apply(_, oldParams) = fun.body + val qual = if (thisProxy.exists) + Select(gen.mkAttributedThis(newClass), thisProxy) + else + gen.mkAttributedThis(oldClass) // sort of a lie, EmptyTree.<static method> would be more honest, but the backend chokes on that. - val body = localTyper typed Apply(Select(gen.mkAttributedThis(oldClass), accessor.symbol), (optionSymbol(thisProxy) map {tp => Select(gen.mkAttributedThis(newClass), tp)}).toList ++ oldParams) + val body = localTyper typed Apply(Select(qual, target), oldParams) body.substituteSymbols(fun.vparams map (_.symbol), params map (_.symbol)) body changeOwner (fun.symbol -> methSym) @@ -238,7 +277,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val abstractFunctionErasedType = AbstractFunctionClass(formals.length).tpe // anonymous subclass of FunctionN with an apply method - def makeAnonymousClass = { + def makeAnonymousClass: ClassDef = { val parents = addSerializable(abstractFunctionErasedType) val funOwner = originalFunction.symbol.owner @@ -271,18 +310,16 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // the Optional proxy that will hold a reference to the 'this' // object used by the lambda, if any. NoSymbol if there is no this proxy val thisProxy = { - val target = targetMethod(originalFunction) - if (thisReferringMethods contains target) { + if (isStatic) + NoSymbol + else { val sym = lambdaClass.newVariable(nme.FAKE_LOCAL_THIS, originalFunction.pos, SYNTHETIC) - sym.info = oldClass.tpe - sym - } else NoSymbol + sym.setInfo(oldClass.tpe) + } } val decapturify = new DeCapturifyTransformer(captureProxies2, unit, oldClass, lambdaClass, originalFunction.symbol.pos, thisProxy) - val accessorMethod = createAccessorMethod(thisProxy, originalFunction) - val decapturedFunction = decapturify.transform(originalFunction).asInstanceOf[Function] val members = (optionSymbol(thisProxy).toList ++ (captureProxies2 map (_._2))) map {member => @@ -294,7 +331,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val constr = createConstructor(lambdaClass, members) // apply method with same arguments and return type as original lambda. - val applyMethodDef = createApplyMethod(lambdaClass, decapturedFunction, accessorMethod, thisProxy) + val applyMethodDef = createApplyMethod(lambdaClass, decapturedFunction, thisProxy) val bridgeMethod = createBridgeMethod(lambdaClass, originalFunction, applyMethodDef) @@ -312,22 +349,73 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val body = members ++ List(constr, applyMethodDef) ++ bridgeMethod // TODO if member fields are private this complains that they're not accessible - (localTyper.typedPos(decapturedFunction.pos)(ClassDef(lambdaClass, body)).asInstanceOf[ClassDef], thisProxy, accessorMethod) + localTyper.typedPos(decapturedFunction.pos)(ClassDef(lambdaClass, body)).asInstanceOf[ClassDef] } - val (anonymousClassDef, thisProxy, accessorMethod) = makeAnonymousClass - - pkg.info.decls enter anonymousClassDef.symbol - - val thisArg = optionSymbol(thisProxy) map (_ => gen.mkAttributedThis(oldClass) setPos originalFunction.pos) - val captureArgs = captures map (capture => Ident(capture) setPos originalFunction.pos) - - val newStat = - Typed(New(anonymousClassDef.symbol, (thisArg.toList ++ captureArgs): _*), TypeTree(abstractFunctionErasedType)) + val allCaptureArgs: List[Tree] = { + val thisArg = if (isStatic) Nil else (gen.mkAttributedThis(oldClass) setPos originalFunction.pos) :: Nil + val captureArgs = captures.iterator.map(capture => gen.mkAttributedRef(capture) setPos originalFunction.pos).toList + thisArg ::: captureArgs + } - val typedNewStat = localTyper.typedPos(originalFunction.pos)(newStat) + val arity = originalFunction.vparams.length + + // Reconstruct the type of the function entering erasure. + // We do this by taking the type after erasure, and re-boxing `ErasedValueType`. + // + // Unfortunately, the more obvious `enteringErasure(target.info)` doesn't work + // as we would like, value classes in parameter position show up as the unboxed types. + val (functionParamTypes, functionResultType) = exitingErasure { + def boxed(tp: Type) = tp match { + case ErasedValueType(valueClazz, _) => TypeRef(NoPrefix, valueClazz, Nil) + case _ => tp + } + // We don't need to deeply map `boxedValueClassType` over the infos as `ErasedValueType` + // will only appear directly as a parameter type in a method signature, as shown + // https://gist.github.com/retronym/ba81dbd462282c504ff8 + val info = target.info + val boxedParamTypes = info.paramTypes.takeRight(arity).map(boxed) + (boxedParamTypes, boxed(info.resultType)) + } + val functionType = definitions.functionType(functionParamTypes, functionResultType) + + val (functionalInterface, isSpecialized) = java8CompatFunctionalInterface(target, functionType) + if (functionalInterface.exists) { + // Create a symbol representing a fictional lambda factory method that accepts the captured + // arguments and returns a Function. + val msym = currentOwner.newMethod(nme.ANON_FUN_NAME, originalFunction.pos, ARTIFACT) + val argTypes: List[Type] = allCaptureArgs.map(_.tpe) + val params = msym.newSyntheticValueParams(argTypes) + msym.setInfo(MethodType(params, functionType)) + val arity = originalFunction.vparams.length + + val lambdaTarget = + if (isSpecialized) + target + else { + createBoxingBridgeMethod(functionParamTypes, functionResultType) match { + case EmptyTree => + target + case bridge => + boxingBridgeMethods += bridge + bridge.symbol + } + } - TransformedFunction(anonymousClassDef, typedNewStat, accessorMethod) + // We then apply this symbol to the captures. + val apply = localTyper.typedPos(originalFunction.pos)(Apply(Ident(msym), allCaptureArgs)).asInstanceOf[Apply] + + // The backend needs to know the target of the lambda and the functional interface in order + // to emit the invokedynamic instruction. We pass this information as tree attachment. + apply.updateAttachment(LambdaMetaFactoryCapable(lambdaTarget, arity, functionalInterface)) + InvokeDynamicLambda(apply) + } else { + val anonymousClassDef = makeAnonymousClass + pkg.info.decls enter anonymousClassDef.symbol + val newStat = Typed(New(anonymousClassDef.symbol, allCaptureArgs: _*), TypeTree(abstractFunctionErasedType)) + val typedNewStat = localTyper.typedPos(originalFunction.pos)(newStat) + DelambdafyAnonClass(anonymousClassDef, typedNewStat) + } } /** @@ -477,4 +565,28 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre super.traverse(tree) } } + + final case class LambdaMetaFactoryCapable(target: Symbol, arity: Int, functionalInterface: Symbol) + + // The functional interface that can be used to adapt the lambda target method `target` to the + // given function type. Returns `NoSymbol` if the compiler settings are unsuitable. + private def java8CompatFunctionalInterface(target: Symbol, functionType: Type): (Symbol, Boolean) = { + val canUseLambdaMetafactory: Boolean = { + val isTarget18 = settings.target.value.contains("jvm-1.8") + settings.isBCodeActive && isTarget18 + } + + val sym = functionType.typeSymbol + val pack = currentRun.runDefinitions.Scala_Java8_CompatPackage + val name1 = specializeTypes.specializedFunctionName(sym, functionType.typeArgs) + val paramTps :+ restpe = functionType.typeArgs + val arity = paramTps.length + val isSpecialized = name1.toTypeName != sym.name + val functionalInterface = if (!isSpecialized) { + currentRun.runDefinitions.Scala_Java8_CompatPackage_JFunction(arity) + } else { + pack.info.decl(name1.toTypeName.prepend("J")) + } + (if (canUseLambdaMetafactory) functionalInterface else NoSymbol, isSpecialized) + } } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index facce9062b..a04625c9c5 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -188,14 +188,16 @@ abstract class Erasure extends AddInterfaces /* Drop redundant types (ones which are implemented by some other parent) from the immediate parents. * This is important on Android because there is otherwise an interface explosion. */ - def minimizeParents(parents: List[Type]): List[Type] = { - var rest = parents - var leaves = collection.mutable.ListBuffer.empty[Type] + def minimizeParents(parents: List[Type]): List[Type] = if (parents.isEmpty) parents else { + def isInterfaceOrTrait(sym: Symbol) = sym.isInterface || sym.isTrait + + var rest = parents.tail + var leaves = collection.mutable.ListBuffer.empty[Type] += parents.head while(rest.nonEmpty) { val candidate = rest.head val nonLeaf = leaves exists { t => t.typeSymbol isSubClass candidate.typeSymbol } if(!nonLeaf) { - leaves = leaves filterNot { t => candidate.typeSymbol isSubClass t.typeSymbol } + leaves = leaves filterNot { t => isInterfaceOrTrait(t.typeSymbol) && (candidate.typeSymbol isSubClass t.typeSymbol) } leaves += candidate } rest = rest.tail @@ -812,11 +814,10 @@ abstract class Erasure extends AddInterfaces // specialized members have no type history before 'specialize', causing double def errors for curried defs override def exclude(sym: Symbol): Boolean = ( sym.isType - || sym.isPrivate || super.exclude(sym) || !sym.hasTypeAt(currentRun.refchecksPhase.id) ) - override def matches(lo: Symbol, high: Symbol) = true + override def matches(lo: Symbol, high: Symbol) = !high.isPrivate } def isErasureDoubleDef(pair: SymbolPair) = { import pair._ diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index 5e2fe21eec..d1be1558b9 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -376,7 +376,7 @@ abstract class LambdaLift extends InfoTransform { private def addFreeArgs(pos: Position, sym: Symbol, args: List[Tree]) = { free get sym match { - case Some(fvs) => args ++ (fvs.toList map (fv => atPos(pos)(proxyRef(fv)))) + case Some(fvs) => addFree(sym, free = fvs.toList map (fv => atPos(pos)(proxyRef(fv))), original = args) case _ => args } } @@ -388,9 +388,9 @@ abstract class LambdaLift extends InfoTransform { case DefDef(_, _, _, vparams :: _, _, _) => val addParams = cloneSymbols(ps).map(_.setFlag(PARAM)) sym.updateInfo( - lifted(MethodType(sym.info.params ::: addParams, sym.info.resultType))) + lifted(MethodType(addFree(sym, free = addParams, original = sym.info.params), sym.info.resultType))) - copyDefDef(tree)(vparamss = List(vparams ++ freeParams)) + copyDefDef(tree)(vparamss = List(addFree(sym, free = freeParams, original = vparams))) case ClassDef(_, _, _, _) => // SI-6231 // Disabled attempt to to add getters to freeParams @@ -571,4 +571,12 @@ abstract class LambdaLift extends InfoTransform { } } // class LambdaLifter + private def addFree[A](sym: Symbol, free: List[A], original: List[A]): List[A] = { + val prependFree = ( + !sym.isConstructor // this condition is redundant for now. It will be needed if we remove the second condition in 2.12.x + && (settings.Ydelambdafy.value == "method" && sym.isDelambdafyTarget) // SI-8359 Makes the lambda body a viable as the target MethodHandle for a call to LambdaMetafactory + ) + if (prependFree) free ::: original + else original ::: free + } } diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala index 38671ebaae..df622d4d1d 100644 --- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala +++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala @@ -219,7 +219,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD * l$ * } or * <rhs> when the lazy value has type Unit (for which there is no field - * to cache it's value. + * to cache its value. * * Similarly as for normal lazy val members (see Mixin), the result will be a tree of the form * { if ((bitmap&n & MASK) == 0) this.l$compute() diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 408f4466e1..11f9483f77 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -26,7 +26,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { */ private val treatedClassInfos = perRunCaches.newMap[Symbol, Type]() withDefaultValue NoType - /** Map a lazy, mixedin field accessor to it's trait member accessor */ + /** Map a lazy, mixedin field accessor to its trait member accessor */ private val initializer = perRunCaches.newMap[Symbol, Symbol]() // --------- helper functions ----------------------------------------------- @@ -886,7 +886,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { } /* Complete lazy field accessors. Applies only to classes, - * for it's own (non inherited) lazy fields. If 'checkinit' + * for its own (non inherited) lazy fields. If 'checkinit' * is enabled, getters that check for the initialized bit are * generated, and the class constructor is changed to set the * initialized bits. diff --git a/src/compiler/scala/tools/nsc/transform/SampleTransform.scala b/src/compiler/scala/tools/nsc/transform/SampleTransform.scala index cffb483072..ba303f7c2b 100644 --- a/src/compiler/scala/tools/nsc/transform/SampleTransform.scala +++ b/src/compiler/scala/tools/nsc/transform/SampleTransform.scala @@ -27,7 +27,7 @@ abstract class SampleTransform extends Transform { tree1 match { case Block(List(), expr) => // a simple optimization expr - case Block(defs, sup @ Super(qual, mix)) => // A hypthothetic transformation, which replaces + case Block(defs, sup @ Super(qual, mix)) => // A hypothetical transformation, which replaces // {super} by {super.sample} treeCopy.Block( // `copy` is the usual lazy tree copier tree1, defs, diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 086512677e..53a1347a48 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -303,6 +303,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } + def specializedFunctionName(sym: Symbol, args: List[Type]) = exitingSpecialize { + require(isFunctionSymbol(sym), sym) + val env: TypeEnv = TypeEnv.fromSpecialization(sym, args) + specializedClass.get((sym, env)) match { + case Some(x) => + x.name + case None => + sym.name + } + } + /** Return the specialized name of 'sym' in the given environment. It * guarantees the same result regardless of the map order by sorting * type variables alphabetically. @@ -315,10 +326,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (sym.isClass) env.keySet else specializedTypeVars(sym).intersect(env.keySet) ) + specializedName(sym.name, tvars, env) + } + + private def specializedName(name: Name, tvars: immutable.Set[Symbol], env: TypeEnv): TermName = { val (methparams, others) = tvars.toList sortBy ("" + _.name) partition (_.owner.isMethod) // debuglog("specName(" + sym + ") env: " + env + " tvars: " + tvars) - specializedName(sym.name, methparams map env, others map env) + specializedName(name, methparams map env, others map env) } /** Specialize name for the two list of types. The first one denotes @@ -610,7 +625,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { exitingSpecialize(sClass setInfo specializedInfoType) val fullEnv = outerEnv ++ env - /* Enter 'sym' in the scope of the current specialized class. It's type is + /* Enter 'sym' in the scope of the current specialized class. Its type is * mapped through the active environment, binding type variables to concrete * types. The existing typeEnv for `sym` is composed with the current active * environment @@ -1368,7 +1383,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { ) def specializeCalls(unit: CompilationUnit) = new TypingTransformer(unit) { - /** Map a specializable method to it's rhs, when not deferred. */ + /** Map a specializable method to its rhs, when not deferred. */ val body = perRunCaches.newMap[Symbol, Tree]() /** Map a specializable method to its value parameter symbols. */ diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 3330fbcae2..b310e6c3a1 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -71,6 +71,14 @@ abstract class UnCurry extends InfoTransform private val noApply = mutable.HashSet[Tree]() private val newMembers = mutable.Map[Symbol, mutable.Buffer[Tree]]() + private lazy val forceSpecializationInfoTransformOfFunctionN: Unit = { + if (currentRun.specializePhase != NoPhase) { // be robust in case of -Ystop-after:uncurry + exitingSpecialize { + FunctionClass.seq.foreach(cls => cls.info) + } + } + } + /** Add a new synthetic member for `currentOwner` */ private def addNewMember(t: Tree): Unit = newMembers.getOrElseUpdate(currentOwner, mutable.Buffer()) += t @@ -221,8 +229,16 @@ abstract class UnCurry extends InfoTransform def mkMethod(owner: Symbol, name: TermName, additionalFlags: FlagSet = NoFlags): DefDef = gen.mkMethodFromFunction(localTyper)(fun, owner, name, additionalFlags) - val canUseDelamdafyMethod = (inConstructorFlag == 0) // Avoiding synthesizing code prone to SI-6666, SI-8363 by using old-style lambda translation + def isSpecialized = { + forceSpecializationInfoTransformOfFunctionN + val specialized = specializeTypes.specializedType(fun.tpe) + !(specialized =:= fun.tpe) + } + def canUseDelamdafyMethod = ( + (inConstructorFlag == 0) // Avoiding synthesizing code prone to SI-6666, SI-8363 by using old-style lambda translation + && (!isSpecialized || (settings.isBCodeActive && settings.target.value == "jvm-1.8")) // DelambdafyTransformer currently only emits generic FunctionN-s, use the old style in the meantime + ) if (inlineFunctionExpansion || !canUseDelamdafyMethod) { val parents = addSerializable(abstractFunctionForFunctionType(fun.tpe)) val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation @@ -421,9 +437,7 @@ abstract class UnCurry extends InfoTransform def isLiftedLambdaBody(target: Tree) = target.symbol.isLocalToBlock && target.symbol.isArtifact && target.symbol.name.containsName(nme.ANON_FUN_NAME) val result = ( - // TODO - settings.noassertions.value temporarily retained to avoid - // breakage until a reasonable interface is settled upon. - if ((sym ne null) && (sym.elisionLevel.exists (_ < settings.elidebelow.value || settings.noassertions))) + if ((sym ne null) && sym.elisionLevel.exists(_ < settings.elidebelow.value)) replaceElidableTree(tree) else translateSynchronized(tree) match { case dd @ DefDef(mods, name, tparams, _, tpt, rhs) => diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala index 0b53dc37de..227c45b3a7 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala @@ -9,8 +9,8 @@ package tools.nsc.transform.patmat import scala.language.postfixOps import scala.collection.mutable -import scala.reflect.internal.util.Statistics -import scala.reflect.internal.util.HashSet +import scala.reflect.internal.util.{NoPosition, Position, Statistics, HashSet} +import scala.tools.nsc.Global trait Logic extends Debugging { import PatternMatchingStats._ @@ -71,6 +71,8 @@ trait Logic extends Debugging { def unapply(v: Var): Some[Tree] } + def uncheckedWarning(pos: Position, msg: String): Unit + def reportWarning(message: String): Unit // resets hash consing -- only supposed to be called by TreeMakersToProps @@ -89,6 +91,8 @@ trait Logic extends Debugging { // compute the domain and return it (call registerNull first!) def domainSyms: Option[Set[Sym]] + def groupedDomains: List[Set[Sym]] + // the symbol for this variable being equal to its statically known type // (only available if registerEquality has been called for that type before) def symForStaticTp: Option[Sym] @@ -117,6 +121,9 @@ trait Logic extends Debugging { final case class Not(a: Prop) extends Prop + // mutually exclusive (i.e., not more than one symbol is set) + final case class AtMostOne(ops: List[Sym]) extends Prop + case object True extends Prop case object False extends Prop @@ -191,7 +198,8 @@ trait Logic extends Debugging { case Not(negated) => negationNormalFormNot(negated) case True | False - | (_: Sym) => p + | (_: Sym) + | (_: AtMostOne) => p } def simplifyProp(p: Prop): Prop = p match { @@ -251,6 +259,7 @@ trait Logic extends Debugging { case Not(a) => apply(a) case Eq(a, b) => applyVar(a); applyConst(b) case s: Sym => applySymbol(s) + case AtMostOne(ops) => ops.foreach(applySymbol) case _ => } def applyVar(x: Var): Unit = {} @@ -283,6 +292,23 @@ trait Logic extends Debugging { } } + // to govern how much time we spend analyzing matches for unreachability/exhaustivity + object AnalysisBudget { + val maxDPLLdepth = global.settings.YpatmatExhaustdepth.value + val maxFormulaSize = 100 * math.min(Int.MaxValue / 100, maxDPLLdepth) + + private def advice = + s"Please try with scalac -Ypatmat-exhaust-depth ${maxDPLLdepth * 2} or -Ypatmat-exhaust-depth off." + + def recursionDepthReached = + s"Exhaustivity analysis reached max recursion depth, not all missing cases are reported.\n($advice)" + + abstract class Exception(val advice: String) extends RuntimeException("CNF budget exceeded") + + object formulaSizeExceeded extends Exception(s"The analysis required more space than allowed.\n$advice") + + } + // TODO: remove since deprecated val budgetProp = scala.sys.Prop[String]("scalac.patmat.analysisBudget") if (budgetProp.isSet) { @@ -356,7 +382,22 @@ trait Logic extends Debugging { // when sym is true, what must hold... implied foreach (impliedSym => addAxiom(Or(Not(sym), impliedSym))) // ... and what must not? - excluded foreach (excludedSym => addAxiom(Or(Not(sym), Not(excludedSym)))) + excluded foreach { + excludedSym => + val exclusive = v.groupedDomains.exists { + domain => domain.contains(sym) && domain.contains(excludedSym) + } + + // TODO: populate `v.exclusiveDomains` with `Set`s from the start, and optimize to: + // val exclusive = v.exclusiveDomains.exists { inDomain => inDomain(sym) && inDomain(excludedSym) } + if (!exclusive) + addAxiom(Or(Not(sym), Not(excludedSym))) + } + } + + // all symbols in a domain are mutually exclusive + v.groupedDomains.foreach { + syms => if (syms.size > 1) addAxiom(AtMostOne(syms.toList)) } } @@ -385,7 +426,7 @@ trait Logic extends Debugging { def findModelFor(solvable: Solvable): Model - def findAllModelsFor(solvable: Solvable): List[Solution] + def findAllModelsFor(solvable: Solvable, pos: Position = NoPosition): List[Solution] } } @@ -431,7 +472,9 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { // once we go to run-time checks (on Const's), convert them to checkable types // TODO: there seems to be bug for singleton domains (variable does not show up in model) lazy val domain: Option[Set[Const]] = { - val subConsts = enumerateSubtypes(staticTp).map{ tps => + val subConsts = + enumerateSubtypes(staticTp, grouped = false) + .headOption.map { tps => tps.toSet[Type].map{ tp => val domainC = TypeConst(tp) registerEquality(domainC) @@ -449,6 +492,15 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { observed(); allConsts } + lazy val groupedDomains: List[Set[Sym]] = { + val subtypes = enumerateSubtypes(staticTp, grouped = true) + subtypes.map { + subTypes => + val syms = subTypes.flatMap(tpe => symForEqualsTo.get(TypeConst(tpe))).toSet + if (mayBeNull) syms + symForEqualsTo(NullConst) else syms + }.filter(_.nonEmpty) + } + // populate equalitySyms // don't care about the result, but want only one fresh symbol per distinct constant c def registerEquality(c: Const): Unit = {ensureCanModify(); symForEqualsTo getOrElseUpdate(c, Sym(this, c))} diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index 34ebbc7463..a11906ace1 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -95,58 +95,84 @@ trait TreeAndTypeAnalysis extends Debugging { val typer: Typer // TODO: domain of other feasibly enumerable built-in types (char?) - def enumerateSubtypes(tp: Type): Option[List[Type]] = + def enumerateSubtypes(tp: Type, grouped: Boolean): List[List[Type]] = tp.typeSymbol match { // TODO case _ if tp.isTupleType => // recurse into component types? - case UnitClass => - Some(List(UnitTpe)) - case BooleanClass => - Some(ConstantTrue :: ConstantFalse :: Nil) + case UnitClass if !grouped => + List(List(UnitTpe)) + case BooleanClass if !grouped => + List(ConstantTrue :: ConstantFalse :: Nil) // TODO case _ if tp.isTupleType => // recurse into component types - case modSym: ModuleClassSymbol => - Some(List(tp)) + case modSym: ModuleClassSymbol if !grouped => + List(List(tp)) case sym: RefinementClassSymbol => - val parentSubtypes: List[Option[List[Type]]] = tp.parents.map(parent => enumerateSubtypes(parent)) - if (parentSubtypes exists (_.isDefined)) + val parentSubtypes = tp.parents.flatMap(parent => enumerateSubtypes(parent, grouped)) + if (parentSubtypes exists (_.nonEmpty)) { // If any of the parents is enumerable, then the refinement type is enumerable. - Some( - // We must only include subtypes of the parents that conform to `tp`. - // See neg/virtpatmat_exhaust_compound.scala for an example. - parentSubtypes flatMap (_.getOrElse(Nil)) filter (_ <:< tp) - ) - else None + // We must only include subtypes of the parents that conform to `tp`. + // See neg/virtpatmat_exhaust_compound.scala for an example. + parentSubtypes map (_.filter(_ <:< tp)) + } + else Nil // make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte case sym if sym.isSealed => - val subclasses = debug.patmatResult(s"enum $sym sealed, subclasses")( - // symbols which are both sealed and abstract need not be covered themselves, because - // all of their children must be and they cannot otherwise be created. - sym.sealedDescendants.toList - sortBy (_.sealedSortName) - filterNot (x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x)) - ) val tpApprox = typer.infer.approximateAbstracts(tp) val pre = tpApprox.prefix - Some(debug.patmatResult(s"enum sealed tp=$tp, tpApprox=$tpApprox as") { - // valid subtypes are turned into checkable types, as we are entering the realm of the dynamic - subclasses flatMap { sym => + def filterChildren(children: List[Symbol]): List[Type] = { + children flatMap { sym => // have to filter out children which cannot match: see ticket #3683 for an example // compare to the fully known type `tp` (modulo abstract types), // so that we can rule out stuff like: sealed trait X[T]; class XInt extends X[Int] --> XInt not valid when enumerating X[String] // however, must approximate abstract types in - val memberType = nestedMemberType(sym, pre, tpApprox.typeSymbol.owner) - val subTp = appliedType(memberType, sym.typeParams.map(_ => WildcardType)) + val memberType = nestedMemberType(sym, pre, tpApprox.typeSymbol.owner) + val subTp = appliedType(memberType, sym.typeParams.map(_ => WildcardType)) val subTpApprox = typer.infer.approximateAbstracts(subTp) // TODO: needed? // debug.patmat("subtp"+(subTpApprox <:< tpApprox, subTpApprox, tpApprox)) if (subTpApprox <:< tpApprox) Some(checkableType(subTp)) else None } - }) + } + + if(grouped) { + def enumerateChildren(sym: Symbol) = { + sym.children.toList + .sortBy(_.sealedSortName) + .filterNot(x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x)) + } + + // enumerate only direct subclasses, + // subclasses of subclasses are enumerated in the next iteration + // and added to a new group + def groupChildren(wl: List[Symbol], + acc: List[List[Type]]): List[List[Type]] = wl match { + case hd :: tl => + val children = enumerateChildren(hd) + groupChildren(tl ++ children, acc :+ filterChildren(children)) + case Nil => acc + } + + groupChildren(sym :: Nil, Nil) + } else { + val subclasses = debug.patmatResult(s"enum $sym sealed, subclasses")( + // symbols which are both sealed and abstract need not be covered themselves, because + // all of their children must be and they cannot otherwise be created. + sym.sealedDescendants.toList + sortBy (_.sealedSortName) + filterNot (x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x)) + ) + + List(debug.patmatResult(s"enum sealed tp=$tp, tpApprox=$tpApprox as") { + // valid subtypes are turned into checkable types, as we are entering the realm of the dynamic + filterChildren(subclasses) + }) + } + case sym => debug.patmat("enum unsealed "+ ((tp, sym, sym.isSealed, isPrimitiveValueClass(sym)))) - None + Nil } // approximate a type to the static type that is fully checkable at run time, @@ -176,7 +202,7 @@ trait TreeAndTypeAnalysis extends Debugging { def uncheckableType(tp: Type): Boolean = { val checkable = ( (isTupleType(tp) && tupleComponents(tp).exists(tp => !uncheckableType(tp))) - || enumerateSubtypes(tp).nonEmpty) + || enumerateSubtypes(tp, grouped = false).nonEmpty) // if (!checkable) debug.patmat("deemed uncheckable: "+ tp) !checkable } @@ -399,6 +425,7 @@ trait MatchAnalysis extends MatchApproximation { trait MatchAnalyzer extends MatchApproximator { def uncheckedWarning(pos: Position, msg: String) = currentRun.reporting.uncheckedWarning(pos, msg) + def warn(pos: Position, ex: AnalysisBudget.Exception, kind: String) = uncheckedWarning(pos, s"Cannot check match for $kind.\n${ex.advice}") def reportWarning(message: String) = global.reporter.warning(typer.context.tree.pos, message) // TODO: model dependencies between variables: if V1 corresponds to (x: List[_]) and V2 is (x.hd), V2 cannot be assigned when V1 = null or V1 = Nil @@ -429,44 +456,50 @@ trait MatchAnalysis extends MatchApproximation { val propsCasesOk = approximate(True) map caseWithoutBodyToProp val propsCasesFail = approximate(False) map (t => Not(caseWithoutBodyToProp(t))) - val (eqAxiomsFail, symbolicCasesFail) = removeVarEq(propsCasesFail, modelNull = true) - val (eqAxiomsOk, symbolicCasesOk) = removeVarEq(propsCasesOk, modelNull = true) - val eqAxioms = simplify(And(eqAxiomsOk, eqAxiomsFail)) // I'm pretty sure eqAxiomsOk == eqAxiomsFail, but not 100% sure. - - val prefix = mutable.ArrayBuffer[Prop]() - prefix += eqAxioms - - var prefixRest = symbolicCasesFail - var current = symbolicCasesOk - var reachable = true - var caseIndex = 0 - - debug.patmat("reachability, vars:\n" + ((propsCasesFail flatMap gatherVariables).distinct map (_.describe) mkString ("\n"))) - debug.patmat(s"equality axioms:\n$eqAxiomsOk") - - // invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail) - // termination: prefixRest.length decreases by 1 - while (prefixRest.nonEmpty && reachable) { - val prefHead = prefixRest.head - caseIndex += 1 - prefixRest = prefixRest.tail - if (prefixRest.isEmpty) reachable = true - else { - prefix += prefHead - current = current.tail + try { + val (eqAxiomsFail, symbolicCasesFail) = removeVarEq(propsCasesFail, modelNull = true) + val (eqAxiomsOk, symbolicCasesOk) = removeVarEq(propsCasesOk, modelNull = true) + val eqAxioms = simplify(And(eqAxiomsOk, eqAxiomsFail)) // I'm pretty sure eqAxiomsOk == eqAxiomsFail, but not 100% sure. + + val prefix = mutable.ArrayBuffer[Prop]() + prefix += eqAxioms + + var prefixRest = symbolicCasesFail + var current = symbolicCasesOk + var reachable = true + var caseIndex = 0 + + debug.patmat("reachability, vars:\n" + ((propsCasesFail flatMap gatherVariables).distinct map (_.describe) mkString ("\n"))) + debug.patmat(s"equality axioms:\n$eqAxiomsOk") + + // invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail) + // termination: prefixRest.length decreases by 1 + while (prefixRest.nonEmpty && reachable) { + val prefHead = prefixRest.head + caseIndex += 1 + prefixRest = prefixRest.tail + if (prefixRest.isEmpty) reachable = true + else { + prefix += prefHead + current = current.tail val and = And((current.head +: prefix): _*) val model = findModelFor(eqFreePropToSolvable(and)) - // debug.patmat("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix)) - // if (NoModel ne model) debug.patmat("reached: "+ modelString(model)) + // debug.patmat("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix)) + // if (NoModel ne model) debug.patmat("reached: "+ modelString(model)) - reachable = NoModel ne model + reachable = NoModel ne model + } } - } - if (Statistics.canEnable) Statistics.stopTimer(patmatAnaReach, start) + if (Statistics.canEnable) Statistics.stopTimer(patmatAnaReach, start) - if (reachable) None else Some(caseIndex) + if (reachable) None else Some(caseIndex) + } catch { + case ex: AnalysisBudget.Exception => + warn(prevBinder.pos, ex, "unreachability") + None // CNF budget exceeded + } } // exhaustivity @@ -507,32 +540,38 @@ trait MatchAnalysis extends MatchApproximation { // when does the match fail? val matchFails = Not(\/(symbolicCases)) - // debug output: + // debug output: debug.patmat("analysing:") showTreeMakers(cases) // debug.patmat("\nvars:\n"+ (vars map (_.describe) mkString ("\n"))) // debug.patmat("\nmatchFails as CNF:\n"+ cnfString(propToSolvable(matchFails))) - // find the models (under which the match fails) - val matchFailModels = findAllModelsFor(propToSolvable(matchFails)) + try { + // find the models (under which the match fails) + val matchFailModels = findAllModelsFor(propToSolvable(matchFails), prevBinder.pos) - val scrutVar = Var(prevBinderTree) - val counterExamples = { - matchFailModels.flatMap { - model => - val varAssignments = expandModel(model) - varAssignments.flatMap(modelToCounterExample(scrutVar) _) + val scrutVar = Var(prevBinderTree) + val counterExamples = { + matchFailModels.flatMap { + model => + val varAssignments = expandModel(model) + varAssignments.flatMap(modelToCounterExample(scrutVar) _) + } } - } - - // sorting before pruning is important here in order to - // keep neg/t7020.scala stable - // since e.g. List(_, _) would cover List(1, _) - val pruned = CounterExample.prune(counterExamples.sortBy(_.toString)).map(_.toString) - if (Statistics.canEnable) Statistics.stopTimer(patmatAnaExhaust, start) - pruned + // sorting before pruning is important here in order to + // keep neg/t7020.scala stable + // since e.g. List(_, _) would cover List(1, _) + val pruned = CounterExample.prune(counterExamples.sortBy(_.toString)).map(_.toString) + + if (Statistics.canEnable) Statistics.stopTimer(patmatAnaExhaust, start) + pruned + } catch { + case ex: AnalysisBudget.Exception => + warn(prevBinder.pos, ex, "exhaustivity") + Nil // CNF budget exceeded + } } } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index b703b5bc6d..e1fe220556 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -577,8 +577,6 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { lengthMax3(casesNoSubstOnly) > 2 } val requireSwitch = hasSwitchAnnotation && exceedsTwoCasesOrAlts - if (hasSwitchAnnotation && !requireSwitch) - reporter.warning(scrut.pos, "matches with two cases or fewer are emitted using if-then-else instead of switch") (suppression, requireSwitch) case _ => (Suppression.NoSuppression, false) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala index 2753baa51d..b1783dc81f 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala @@ -112,8 +112,10 @@ trait ScalacPatternExpanders { arityError("not enough") else if (elementArity > 0 && !isSeq) arityError("too many") - else if (settings.warnStarsAlign && isSeq && productArity > 0 && (elementArity > 0 || !isStar)) - warn("A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).") + else if (settings.warnStarsAlign && isSeq && productArity > 0 && elementArity > 0) warn { + if (isStar) "Sequence wildcard (_*) does not align with repeated case parameter or extracted sequence; the result may be unexpected." + else "A repeated case parameter or extracted sequence is not matched by a sequence wildcard (_*), and may fail at runtime." + } aligned } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala index 27217f0dc2..9710c5c66b 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala @@ -11,6 +11,7 @@ import scala.reflect.internal.util.Statistics import scala.language.postfixOps import scala.collection.mutable import scala.reflect.internal.util.Collections._ +import scala.reflect.internal.util.Position // a literal is a (possibly negated) variable class Lit(val v: Int) extends AnyVal { @@ -64,7 +65,23 @@ trait Solving extends Logic { def size = symbols.size } - case class Solvable(cnf: Cnf, symbolMapping: SymbolMapping) + def cnfString(f: Array[Clause]): String + + final case class Solvable(cnf: Cnf, symbolMapping: SymbolMapping) { + def ++(other: Solvable) = { + require(this.symbolMapping eq other.symbolMapping) + Solvable(cnf ++ other.cnf, symbolMapping) + } + + override def toString: String = { + "Solvable\nLiterals:\n" + + (for { + (lit, sym) <- symbolMapping.symForVar.toSeq.sortBy(_._1) + } yield { + s"$lit -> $sym" + }).mkString("\n") + "Cnf:\n" + cnfString(cnf) + } + } trait CnfBuilder { private[this] val buff = ArrayBuffer[Clause]() @@ -95,7 +112,11 @@ trait Solving extends Logic { } } - def buildCnf: Array[Clause] = buff.toArray + def buildCnf: Array[Clause] = { + val cnf = buff.toArray + buff.clear() + cnf + } } @@ -130,20 +151,23 @@ trait Solving extends Logic { def apply(p: Prop): Solvable = { - def convert(p: Prop): Lit = { + def convert(p: Prop): Option[Lit] = { p match { case And(fv) => - and(fv.map(convert)) + Some(and(fv.flatMap(convert))) case Or(fv) => - or(fv.map(convert)) + Some(or(fv.flatMap(convert))) case Not(a) => - not(convert(a)) + convert(a).map(not) case sym: Sym => - convertSym(sym) + Some(convertSym(sym)) case True => - constTrue + Some(constTrue) case False => - constFalse + Some(constFalse) + case AtMostOne(ops) => + atMostOne(ops) + None case _: Eq => throw new MatchError(p) } @@ -189,8 +213,57 @@ trait Solving extends Logic { // no need for auxiliary variable def not(a: Lit): Lit = -a + /** + * This encoding adds 3n-4 variables auxiliary variables + * to encode that at most 1 symbol can be set. + * See also "Towards an Optimal CNF Encoding of Boolean Cardinality Constraints" + * http://www.carstensinz.de/papers/CP-2005.pdf + */ + def atMostOne(ops: List[Sym]) { + (ops: @unchecked) match { + case hd :: Nil => convertSym(hd) + case x1 :: tail => + // sequential counter: 3n-4 clauses + // pairwise encoding: n*(n-1)/2 clauses + // thus pays off only if n > 5 + if (ops.lengthCompare(5) > 0) { + + @inline + def /\(a: Lit, b: Lit) = addClauseProcessed(clause(a, b)) + + val (mid, xn :: Nil) = tail.splitAt(tail.size - 1) + + // 1 <= x1,...,xn <==> + // + // (!x1 \/ s1) /\ (!xn \/ !sn-1) /\ + // + // /\ + // / \ (!xi \/ si) /\ (!si-1 \/ si) /\ (!xi \/ !si-1) + // 1 < i < n + val s1 = newLiteral() + /\(-convertSym(x1), s1) + val snMinus = mid.foldLeft(s1) { + case (siMinus, sym) => + val xi = convertSym(sym) + val si = newLiteral() + /\(-xi, si) + /\(-siMinus, si) + /\(-xi, -siMinus) + si + } + /\(-convertSym(xn), -snMinus) + } else { + ops.map(convertSym).combinations(2).foreach { + case a :: b :: Nil => + addClauseProcessed(clause(-a, -b)) + case _ => + } + } + } + } + // add intermediate variable since we want the formula to be SAT! - addClauseProcessed(clause(convert(p))) + addClauseProcessed(convert(p).toSet) Solvable(buildCnf, symbolMapping) } @@ -244,19 +317,54 @@ trait Solving extends Logic { def eqFreePropToSolvable(p: Prop): Solvable = { + def doesFormulaExceedSize(p: Prop): Boolean = { + p match { + case And(ops) => + if (ops.size > AnalysisBudget.maxFormulaSize) { + true + } else { + ops.exists(doesFormulaExceedSize) + } + case Or(ops) => + if (ops.size > AnalysisBudget.maxFormulaSize) { + true + } else { + ops.exists(doesFormulaExceedSize) + } + case Not(a) => doesFormulaExceedSize(a) + case _ => false + } + } + + val simplified = simplify(p) + if (doesFormulaExceedSize(simplified)) { + throw AnalysisBudget.formulaSizeExceeded + } + // collect all variables since after simplification / CNF conversion // they could have been removed from the formula val symbolMapping = new SymbolMapping(gatherSymbols(p)) - - val simplified = simplify(p) val cnfExtractor = new AlreadyInCNF(symbolMapping) + val cnfTransformer = new TransformToCnf(symbolMapping) + + def cnfFor(prop: Prop): Solvable = { + prop match { + case cnfExtractor.ToCnf(solvable) => + // this is needed because t6942 would generate too many clauses with Tseitin + // already in CNF, just add clauses + solvable + case p => + cnfTransformer.apply(p) + } + } + simplified match { - case cnfExtractor.ToCnf(solvable) => - // this is needed because t6942 would generate too many clauses with Tseitin - // already in CNF, just add clauses - solvable - case p => - new TransformToCnf(symbolMapping).apply(p) + case And(props) => + // SI-6942: + // CNF(P1 /\ ... /\ PN) == CNF(P1) ++ CNF(...) ++ CNF(PN) + props.map(cnfFor).reduce(_ ++ _) + case p => + cnfFor(p) } } } @@ -288,7 +396,7 @@ trait Solving extends Logic { val NoTseitinModel: TseitinModel = null // returns all solutions, if any (TODO: better infinite recursion backstop -- detect fixpoint??) - def findAllModelsFor(solvable: Solvable): List[Solution] = { + def findAllModelsFor(solvable: Solvable, pos: Position): List[Solution] = { debug.patmat("find all models for\n"+ cnfString(solvable.cnf)) // we must take all vars from non simplified formula @@ -308,13 +416,12 @@ trait Solving extends Logic { final case class TseitinSolution(model: TseitinModel, unassigned: List[Int]) { def projectToSolution(symForVar: Map[Int, Sym]) = Solution(projectToModel(model, symForVar), unassigned map symForVar) } + def findAllModels(clauses: Array[Clause], models: List[TseitinSolution], - recursionDepthAllowed: Int = global.settings.YpatmatExhaustdepth.value): List[TseitinSolution]= + recursionDepthAllowed: Int = AnalysisBudget.maxDPLLdepth): List[TseitinSolution]= if (recursionDepthAllowed == 0) { - val maxDPLLdepth = global.settings.YpatmatExhaustdepth.value - reportWarning("(Exhaustivity analysis reached max recursion depth, not all missing cases are reported. " + - s"Please try with scalac -Ypatmat-exhaust-depth ${maxDPLLdepth * 2} or -Ypatmat-exhaust-depth off.)") + uncheckedWarning(pos, AnalysisBudget.recursionDepthReached) models } else { debug.patmat("find all models for\n" + cnfString(clauses)) diff --git a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala index 2c27bdb03a..0574869714 100644 --- a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala +++ b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala @@ -57,7 +57,7 @@ trait AnalyzerPlugins { self: Analyzer => * `analyzer.transformed` hash map, indexed by the definition's rhs tree. * * NOTE: Invoking the type checker can lead to cyclic reference errors. For instance, if this - * method is called from the type completer of a recursive method, type checking the mehtod + * method is called from the type completer of a recursive method, type checking the method * rhs will invoke the same completer again. It might be possible to avoid this situation by * assigning `tpe` to `defTree.symbol` (untested) - the final type computed by this method * will then be assigned to the definition's symbol by monoTypeCompleter (in Namers). diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index ca25e59c4b..542f58795a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -167,7 +167,7 @@ trait Contexts { self: Analyzer => * afterwards errors are thrown. This is configured in `rootContext`. Additionally, more * fine grained control is needed based on the kind of error; ambiguity errors are often * suppressed during exploratory typing, such as determining whether `a == b` in an argument - * position is an assignment or a named argument, when `Infererencer#isApplicableSafe` type checks + * position is an assignment or a named argument, when `Inferencer#isApplicableSafe` type checks * applications with and without an expected type, or whtn `Typer#tryTypedApply` tries to fit arguments to * a function type with/without implicit views. * @@ -1108,10 +1108,10 @@ trait Contexts { self: Analyzer => // // A type-import-on-demand declaration never causes any other declaration to be shadowed. // - // Scala: Bindings of different kinds have a precedence defined on them: + // Scala: Bindings of different kinds have a precedence defined on them: // - // 1) Definitions and declarations that are local, inherited, or made available by a - // package clause in the same compilation unit where the definition occurs have + // 1) Definitions and declarations that are local, inherited, or made available by a + // package clause in the same compilation unit where the definition occurs have // highest precedence. // 2) Explicit imports have next highest precedence. def depthOk(imp: ImportInfo) = ( diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 27e17fc65f..f9582a54ff 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -376,7 +376,7 @@ trait Infer extends Checkable { } /** Overload which allocates fresh type vars. * The other one exists because apparently inferExprInstance needs access to the typevars - * after the call, and its wasteful to return a tuple and throw it away almost every time. + * after the call, and it's wasteful to return a tuple and throw it away almost every time. */ private def exprTypeArgs(tparams: List[Symbol], restpe: Type, pt: Type, useWeaklyCompatible: Boolean): List[Type] = exprTypeArgs(tparams map freshVar, tparams, restpe, pt, useWeaklyCompatible) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 24238b8e41..77c49a862a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1125,7 +1125,7 @@ trait Namers extends MethodSynthesis { for (vparam <- vparams) { if (vparam.tpt.isEmpty) { val overriddenParamTp = overriddenParams.head.tpe - // references to type parameteres in overriddenParamTp link to the type skolems, so the + // references to type parameters in overriddenParamTp link to the type skolems, so the // assigned type is consistent with the other / existing parameter types in vparamSymss. vparam.symbol setInfo overriddenParamTp vparam.tpt defineType overriddenParamTp setPos vparam.pos.focus diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 5abfbe850f..4b30b4e436 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -584,7 +584,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans !other.isDeferred && other.isJavaDefined && !sym.enclClass.isSubClass(other.enclClass) && { // #3622: erasure operates on uncurried types -- // note on passing sym in both cases: only sym.isType is relevant for uncurry.transformInfo - // !!! erasure.erasure(sym, uncurry.transformInfo(sym, tp)) gives erreneous of inaccessible type - check whether that's still the case! + // !!! erasure.erasure(sym, uncurry.transformInfo(sym, tp)) gives erroneous or inaccessible type - check whether that's still the case! def uncurryAndErase(tp: Type) = erasure.erasure(sym)(uncurry.transformInfo(sym, tp)) val tp1 = uncurryAndErase(clazz.thisType.memberType(sym)) val tp2 = uncurryAndErase(clazz.thisType.memberType(other)) @@ -1122,7 +1122,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } /** Sensibility check examines flavors of equals. */ def checkSensible(pos: Position, fn: Tree, args: List[Tree]) = fn match { - case Select(qual, name @ (nme.EQ | nme.NE | nme.eq | nme.ne)) if args.length == 1 && isObjectOrAnyComparisonMethod(fn.symbol) => + case Select(qual, name @ (nme.EQ | nme.NE | nme.eq | nme.ne)) if args.length == 1 && isObjectOrAnyComparisonMethod(fn.symbol) && !currentOwner.isSynthetic => checkSensibleEquals(pos, qual, name, fn.symbol, args.head) case _ => } diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index db81eecdf5..e0d96df062 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -322,7 +322,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT case Super(_, mix) => if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) { if (!settings.overrideVars) - reporter.error(tree.pos, "super may be not be used on " + sym.accessedOrSelf) + reporter.error(tree.pos, "super may not be used on " + sym.accessedOrSelf) } else if (isDisallowed(sym)) { reporter.error(tree.pos, "super not allowed here: use this." + name.decode + " instead") } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 391ef9e337..27a574a449 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4301,7 +4301,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val selector1 = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) } // SI-8120 If we don't duplicate the cases, the original Match node will share trees with ones that // receive symbols owned by this function. However if, after a silent mode session, we discard - // this Function and try a different approach (e.g. applying a view to the reciever) we end up + // this Function and try a different approach (e.g. applying a view to the receiver) we end up // with orphaned symbols which blows up far down the pipeline (or can be detected with -Ycheck:typer). val body = treeCopy.Match(tree, selector1, (cases map duplicateAndKeepPositions).asInstanceOf[List[CaseDef]]) typed1(atPos(tree.pos) { Function(params, body) }, mode, pt) @@ -4881,10 +4881,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper (// this -> Foo.this if (sym.isThisSym) typed1(This(sym.owner) setPos tree.pos, mode, pt) - // Inferring classOf type parameter from expected type. Otherwise an - // actual call to the stubbed classOf method is generated, returning null. - else if (isPredefClassOf(sym) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty) - typedClassOf(tree, TypeTree(pt.typeArgs.head)) + else if (isPredefClassOf(sym) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty) { + // Inferring classOf type parameter from expected type. Otherwise an + // actual call to the stubbed classOf method is generated, returning null. + typedClassOf(tree, TypeTree(pt.typeArgs.head).setPos(tree.pos.focus)) + } else { val pre1 = if (sym.isTopLevel) sym.owner.thisType else if (qual == EmptyTree) NoPrefix else qual.tpe val tree1 = if (qual == EmptyTree) tree else atPos(tree.pos)(Select(atPos(tree.pos.focusStart)(qual), name)) diff --git a/src/intellij-14/README b/src/intellij-14/README deleted file mode 100644 index 310a766a20..0000000000 --- a/src/intellij-14/README +++ /dev/null @@ -1,12 +0,0 @@ -Use the latest IntelliJ IDEA release and install the Scala plugin from within the IDE. - -Compilation withing IDEA is performed in "-Dlocker.skip=1" mode: the sources are built -directly using the STARR compiler. - -The following steps are required to use IntelliJ IDEA on Scala trunk - - Run "ant init". This will download some JARs from to ./build/deps, which are - included in IntelliJ's classpath. - - Run src/intellij-14/setup.sh - - Open ./src/intellij-14/scala.ipr in IntelliJ - - File, Project Settings, Project, SDK. Create an SDK entry named "1.6" containing the - Java 1.6 SDK diff --git a/src/intellij-14/actors.iml.SAMPLE b/src/intellij-14/actors.iml.SAMPLE deleted file mode 100644 index 3da7a5f777..0000000000 --- a/src/intellij-14/actors.iml.SAMPLE +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../actors"> - <sourceFolder url="file://$MODULE_DIR$/../actors" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="forkjoin" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/asm.iml.SAMPLE b/src/intellij-14/asm.iml.SAMPLE deleted file mode 100644 index 9b2fd58ce7..0000000000 --- a/src/intellij-14/asm.iml.SAMPLE +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../asm"> - <sourceFolder url="file://$MODULE_DIR$/../asm/src" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/../asm" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/compiler.iml.SAMPLE b/src/intellij-14/compiler.iml.SAMPLE deleted file mode 100644 index 858ca2f2c2..0000000000 --- a/src/intellij-14/compiler.iml.SAMPLE +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../compiler"> - <sourceFolder url="file://$MODULE_DIR$/../compiler" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="asm" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="reflect" /> - <orderEntry type="library" name="ant" level="project" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/diff.sh b/src/intellij-14/diff.sh deleted file mode 100755 index 54f9248608..0000000000 --- a/src/intellij-14/diff.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -# -# Diffs the SAMPLE files against the working project config. -# -export SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" -for f in "$SCRIPT_DIR"/*.{iml,ipr}; do - echo $f; diff -u $f.SAMPLE $f; -done diff --git a/src/intellij-14/forkjoin.iml.SAMPLE b/src/intellij-14/forkjoin.iml.SAMPLE deleted file mode 100644 index 42507b2911..0000000000 --- a/src/intellij-14/forkjoin.iml.SAMPLE +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../forkjoin"> - <sourceFolder url="file://$MODULE_DIR$/../forkjoin" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/interactive.iml.SAMPLE b/src/intellij-14/interactive.iml.SAMPLE deleted file mode 100644 index db12a7dc9b..0000000000 --- a/src/intellij-14/interactive.iml.SAMPLE +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../interactive"> - <sourceFolder url="file://$MODULE_DIR$/../interactive" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="scaladoc" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/library.iml.SAMPLE b/src/intellij-14/library.iml.SAMPLE deleted file mode 100644 index 08cccba4b9..0000000000 --- a/src/intellij-14/library.iml.SAMPLE +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../library"> - <sourceFolder url="file://$MODULE_DIR$/../library" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="forkjoin" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/manual.iml.SAMPLE b/src/intellij-14/manual.iml.SAMPLE deleted file mode 100644 index 2e67076e28..0000000000 --- a/src/intellij-14/manual.iml.SAMPLE +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../manual"> - <sourceFolder url="file://$MODULE_DIR$/../manual" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="library" name="ant" level="project" /> - <orderEntry type="library" name="scaladoc-deps" level="project" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/partest-extras.iml.SAMPLE b/src/intellij-14/partest-extras.iml.SAMPLE deleted file mode 100644 index b3537a949a..0000000000 --- a/src/intellij-14/partest-extras.iml.SAMPLE +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../partest-extras"> - <sourceFolder url="file://$MODULE_DIR$/../partest-extras" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="asm" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="repl" /> - <orderEntry type="library" name="partest" level="project" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/partest-javaagent.iml.SAMPLE b/src/intellij-14/partest-javaagent.iml.SAMPLE deleted file mode 100644 index 3a387aab0f..0000000000 --- a/src/intellij-14/partest-javaagent.iml.SAMPLE +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../partest-javaagent"> - <sourceFolder url="file://$MODULE_DIR$/../partest-javaagent" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="asm" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/reflect.iml.SAMPLE b/src/intellij-14/reflect.iml.SAMPLE deleted file mode 100644 index 87da13777b..0000000000 --- a/src/intellij-14/reflect.iml.SAMPLE +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../reflect"> - <sourceFolder url="file://$MODULE_DIR$/../reflect" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/repl.iml.SAMPLE b/src/intellij-14/repl.iml.SAMPLE deleted file mode 100644 index 5a7476b1ef..0000000000 --- a/src/intellij-14/repl.iml.SAMPLE +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../repl"> - <sourceFolder url="file://$MODULE_DIR$/../repl" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="module" module-name="asm" /> - <orderEntry type="module" module-name="reflect" /> - <orderEntry type="library" name="repl-deps" level="project" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/scala.iml.SAMPLE b/src/intellij-14/scala.iml.SAMPLE deleted file mode 100644 index 9e8718dd45..0000000000 --- a/src/intellij-14/scala.iml.SAMPLE +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../.."> - <excludeFolder url="file://$MODULE_DIR$/../../build" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/scala.ipr.SAMPLE b/src/intellij-14/scala.ipr.SAMPLE deleted file mode 100644 index 1e3d07466d..0000000000 --- a/src/intellij-14/scala.ipr.SAMPLE +++ /dev/null @@ -1,261 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="CompilerConfiguration"> - <option name="DEFAULT_COMPILER" value="Javac" /> - <resourceExtensions /> - <wildcardResourcePatterns> - <entry name="!?*.java" /> - <entry name="!?*.form" /> - <entry name="!?*.class" /> - <entry name="!?*.groovy" /> - <entry name="!?*.scala" /> - <entry name="!?*.flex" /> - <entry name="!?*.kt" /> - <entry name="!?*.clj" /> - </wildcardResourcePatterns> - <annotationProcessing> - <profile default="true" name="Default" enabled="false"> - <processorPath useClasspath="true" /> - </profile> - </annotationProcessing> - </component> - <component name="CopyrightManager" default="" /> - <component name="DaemonCodeAnalyzer"> - <disable_hints /> - </component> - <component name="DependencyValidationManager"> - <option name="SKIP_IMPORT_STATEMENTS" value="false" /> - </component> - <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" /> - <component name="EntryPointsManager"> - <entry_points version="2.0" /> - </component> - <component name="ProjectLevelVcsManager" settingsEditedManually="false"> - <OptionsSetting value="true" id="Add" /> - <OptionsSetting value="true" id="Remove" /> - <OptionsSetting value="true" id="Checkout" /> - <OptionsSetting value="true" id="Update" /> - <OptionsSetting value="true" id="Status" /> - <OptionsSetting value="true" id="Edit" /> - <ConfirmationsSetting value="0" id="Add" /> - <ConfirmationsSetting value="0" id="Remove" /> - </component> - <component name="ProjectModuleManager"> - <modules> - <module fileurl="file://$PROJECT_DIR$/actors.iml" filepath="$PROJECT_DIR$/actors.iml" /> - <module fileurl="file://$PROJECT_DIR$/asm.iml" filepath="$PROJECT_DIR$/asm.iml" /> - <module fileurl="file://$PROJECT_DIR$/compiler.iml" filepath="$PROJECT_DIR$/compiler.iml" /> - <module fileurl="file://$PROJECT_DIR$/forkjoin.iml" filepath="$PROJECT_DIR$/forkjoin.iml" /> - <module fileurl="file://$PROJECT_DIR$/interactive.iml" filepath="$PROJECT_DIR$/interactive.iml" /> - <module fileurl="file://$PROJECT_DIR$/library.iml" filepath="$PROJECT_DIR$/library.iml" /> - <module fileurl="file://$PROJECT_DIR$/manual.iml" filepath="$PROJECT_DIR$/manual.iml" /> - <module fileurl="file://$PROJECT_DIR$/partest-extras.iml" filepath="$PROJECT_DIR$/partest-extras.iml" /> - <module fileurl="file://$PROJECT_DIR$/partest-javaagent.iml" filepath="$PROJECT_DIR$/partest-javaagent.iml" /> - <module fileurl="file://$PROJECT_DIR$/reflect.iml" filepath="$PROJECT_DIR$/reflect.iml" /> - <module fileurl="file://$PROJECT_DIR$/repl.iml" filepath="$PROJECT_DIR$/repl.iml" /> - <module fileurl="file://$PROJECT_DIR$/scala.iml" filepath="$PROJECT_DIR$/scala.iml" /> - <module fileurl="file://$PROJECT_DIR$/scaladoc.iml" filepath="$PROJECT_DIR$/scaladoc.iml" /> - <module fileurl="file://$PROJECT_DIR$/scalap.iml" filepath="$PROJECT_DIR$/scalap.iml" /> - <module fileurl="file://$PROJECT_DIR$/test.iml" filepath="$PROJECT_DIR$/test.iml" /> - <module fileurl="file://$PROJECT_DIR$/test-junit.iml" filepath="$PROJECT_DIR$/test-junit.iml" /> - </modules> - </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK"> - <output url="file://$PROJECT_DIR$/../../out" /> - </component> - <component name="PropertiesComponent"> - <property name="GoToClass.includeLibraries" value="false" /> - <property name="GoToClass.toSaveIncludeLibraries" value="false" /> - <property name="GoToFile.includeJavaFiles" value="false" /> - <property name="MemberChooser.sorted" value="false" /> - <property name="MemberChooser.showClasses" value="true" /> - <property name="MemberChooser.copyJavadoc" value="false" /> - <property name="options.lastSelected" value="configurable.group.appearance" /> - <property name="options.splitter.main.proportions" value="0.3" /> - <property name="options.splitter.details.proportions" value="0.2" /> - <property name="options.searchVisible" value="true" /> - </component> - <component name="RunManager"> - <configuration default="true" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" factoryName="Plugin"> - <module name="" /> - <option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" /> - <option name="PROGRAM_PARAMETERS" /> - <method /> - </configuration> - <configuration default="true" type="Remote" factoryName="Remote"> - <option name="USE_SOCKET_TRANSPORT" value="true" /> - <option name="SERVER_MODE" value="false" /> - <option name="SHMEM_ADDRESS" value="javadebug" /> - <option name="HOST" value="localhost" /> - <option name="PORT" value="5005" /> - <method /> - </configuration> - <configuration default="true" type="Applet" factoryName="Applet"> - <module name="" /> - <option name="MAIN_CLASS_NAME" /> - <option name="HTML_FILE_NAME" /> - <option name="HTML_USED" value="false" /> - <option name="WIDTH" value="400" /> - <option name="HEIGHT" value="300" /> - <option name="POLICY_FILE" value="$CARDEA_HOME$/bin/appletviewer.policy" /> - <option name="VM_PARAMETERS" /> - <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> - <option name="ALTERNATIVE_JRE_PATH" /> - <method /> - </configuration> - <configuration default="true" type="TestNG" factoryName="TestNG"> - <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" /> - <module name="" /> - <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> - <option name="ALTERNATIVE_JRE_PATH" /> - <option name="SUITE_NAME" /> - <option name="PACKAGE_NAME" /> - <option name="MAIN_CLASS_NAME" /> - <option name="METHOD_NAME" /> - <option name="GROUP_NAME" /> - <option name="TEST_OBJECT" value="CLASS" /> - <option name="VM_PARAMETERS" value="-ea" /> - <option name="PARAMETERS" /> - <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" /> - <option name="OUTPUT_DIRECTORY" /> - <option name="ANNOTATION_TYPE" /> - <option name="ENV_VARIABLES" /> - <option name="PASS_PARENT_ENVS" value="true" /> - <option name="TEST_SEARCH_SCOPE"> - <value defaultName="moduleWithDependencies" /> - </option> - <option name="USE_DEFAULT_REPORTERS" value="false" /> - <option name="PROPERTIES_FILE" /> - <envs /> - <properties /> - <listeners /> - <method /> - </configuration> - <configuration default="true" type="Application" factoryName="Application"> - <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" /> - <option name="MAIN_CLASS_NAME" /> - <option name="VM_PARAMETERS" /> - <option name="PROGRAM_PARAMETERS" /> - <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" /> - <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> - <option name="ALTERNATIVE_JRE_PATH" /> - <option name="ENABLE_SWING_INSPECTOR" value="false" /> - <option name="ENV_VARIABLES" /> - <option name="PASS_PARENT_ENVS" value="true" /> - <module name="" /> - <envs /> - <method /> - </configuration> - <configuration default="true" type="JUnit" factoryName="JUnit"> - <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" /> - <module name="" /> - <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> - <option name="ALTERNATIVE_JRE_PATH" /> - <option name="PACKAGE_NAME" /> - <option name="MAIN_CLASS_NAME" /> - <option name="METHOD_NAME" /> - <option name="TEST_OBJECT" value="class" /> - <option name="VM_PARAMETERS" value="-ea" /> - <option name="PARAMETERS" /> - <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" /> - <option name="ENV_VARIABLES" /> - <option name="PASS_PARENT_ENVS" value="true" /> - <option name="TEST_SEARCH_SCOPE"> - <value defaultName="moduleWithDependencies" /> - </option> - <envs /> - <patterns /> - <method /> - </configuration> - <list size="0" /> - <configuration name="<template>" type="WebApp" default="true" selected="false"> - <Host>localhost</Host> - <Port>5050</Port> - </configuration> - </component> - <component name="ScalaCompilerConfiguration"> - <parameters> - <parameter value="-sourcepath" /> - <parameter value="$PROJECT_DIR$/../library" /> - </parameters> - </component> - <component name="VcsContentAnnotationSettings"> - <option name="myLimit" value="2678400000" /> - </component> - <component name="VcsDirectoryMappings"> - <mapping directory="$PROJECT_DIR$/../.." vcs="Git" /> - </component> - <component name="VcsManagerConfiguration"> - <option name="myTodoPanelSettings"> - <TodoPanelSettings /> - </option> - </component> - <component name="libraryTable"> - <library name="ant"> - <CLASSES> - <root url="jar://$PROJECT_DIR$/../../lib/ant/ant.jar!/" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - </library> - <library name="junit"> - <CLASSES> - <root url="file://$PROJECT_DIR$/../../build/deps/junit" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/junit" recursive="false" /> - </library> - <library name="partest"> - <CLASSES> - <root url="file://$PROJECT_DIR$/../../build/deps/partest" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/partest" recursive="false" /> - </library> - <library name="repl-deps"> - <CLASSES> - <root url="file://$PROJECT_DIR$/../../build/deps/repl" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/repl" recursive="false" /> - </library> - <library name="scaladoc-deps"> - <CLASSES> - <root url="file://$PROJECT_DIR$/../../build/deps/scaladoc" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/scaladoc" recursive="false" /> - </library> - <library name="starr" type="Scala"> - <properties> - <compiler-classpath> - <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-compiler-#scala-version#.jar" /> - <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-library-#scala-version#.jar" /> - <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-reflect-#scala-version#.jar" /> - </compiler-classpath> - </properties> - <CLASSES> - <root url="jar://$PROJECT_DIR$/../../build/deps/starr/scala-library-#scala-version#.jar!/" /> - <root url="jar://$PROJECT_DIR$/../../build/deps/starr/scala-reflect-#scala-version#.jar!/" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - </library> - <library name="starr-no-deps" type="Scala"> - <properties> - <compiler-classpath> - <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-compiler-#scala-version#.jar" /> - <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-library-#scala-version#.jar" /> - <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-reflect-#scala-version#.jar" /> - </compiler-classpath> - </properties> - <CLASSES /> - <JAVADOC /> - <SOURCES /> - </library> - </component> -</project>
\ No newline at end of file diff --git a/src/intellij-14/scaladoc.iml.SAMPLE b/src/intellij-14/scaladoc.iml.SAMPLE deleted file mode 100644 index 5c7015aa61..0000000000 --- a/src/intellij-14/scaladoc.iml.SAMPLE +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../scaladoc"> - <sourceFolder url="file://$MODULE_DIR$/../scaladoc" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="reflect" /> - <orderEntry type="library" name="scaladoc-deps" level="project" /> - <orderEntry type="library" name="partest" level="project" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - <orderEntry type="library" name="ant" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/scalap.iml.SAMPLE b/src/intellij-14/scalap.iml.SAMPLE deleted file mode 100644 index e09b8d11b6..0000000000 --- a/src/intellij-14/scalap.iml.SAMPLE +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../scalap"> - <sourceFolder url="file://$MODULE_DIR$/../scalap" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="reflect" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/setup.sh b/src/intellij-14/setup.sh deleted file mode 100755 index cf08898f24..0000000000 --- a/src/intellij-14/setup.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -# -# Generates IntelliJ IDEA project files based on the checked-in samples. -# - -set -e -export SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" -echo "About to delete .ipr and .iml files and replace with the .SAMPLE files. Press enter to continue or CTRL-C to cancel." -read - -for f in "$SCRIPT_DIR"/*.SAMPLE; do - g=${f%.SAMPLE} - cp $f $g -done - -SCALA_VERSION="`cat $SCRIPT_DIR/../../versions.properties | grep 'starr.version' | awk '{split($0,a,"="); print a[2]}'`" -sed "s/#scala-version#/$SCALA_VERSION/g" $SCRIPT_DIR/scala.ipr.SAMPLE > $SCRIPT_DIR/scala.ipr
\ No newline at end of file diff --git a/src/intellij-14/test-junit.iml.SAMPLE b/src/intellij-14/test-junit.iml.SAMPLE deleted file mode 100644 index 786f02e2e2..0000000000 --- a/src/intellij-14/test-junit.iml.SAMPLE +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../../test/junit"> - <sourceFolder url="file://$MODULE_DIR$/../../test/junit" isTestSource="true" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="library" name="junit" level="project" /> - <orderEntry type="library" name="scaladoc-deps" level="project" /> - <orderEntry type="module" module-name="actors" /> - <orderEntry type="module" module-name="asm" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="module" module-name="forkjoin" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="partest-extras" /> - <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="repl" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/test.iml.SAMPLE b/src/intellij-14/test.iml.SAMPLE deleted file mode 100644 index a384d72266..0000000000 --- a/src/intellij-14/test.iml.SAMPLE +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../../test"> - <excludeFolder url="file://$MODULE_DIR$/../../test/junit" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="actors" /> - <orderEntry type="module" module-name="asm" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="module" module-name="forkjoin" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="partest-extras" /> - <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="repl" /> - <orderEntry type="library" name="partest" level="project" /> - <orderEntry type="library" name="scaladoc-deps" level="project" /> - <orderEntry type="library" name="starr-no-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij-14/update.sh b/src/intellij-14/update.sh deleted file mode 100755 index eb6fea782f..0000000000 --- a/src/intellij-14/update.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -# -# Updates the .SAMPLE files with the current project files. -# - -set -e -export SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" - -echo "About to create overwrite the .ipr.SAMPLE and .iml.SAMPLE files with the current project files. Press enter to continue or CTRL-C to cancel." -read - -for f in "$SCRIPT_DIR"/*.{iml,ipr}; do - cp $f $f.SAMPLE -done - -for f in "$SCRIPT_DIR"/*.SAMPLE; do - g=${f%.SAMPLE} - if [[ ! -f $g ]]; then - echo "Stale sample file, deleting $f" - rm $f - fi -done diff --git a/src/intellij/README b/src/intellij/README index a39691f4f0..4ecab5561f 100644 --- a/src/intellij/README +++ b/src/intellij/README @@ -7,6 +7,6 @@ The following steps are required to use IntelliJ IDEA on Scala trunk - Run "ant init". This will download some JARs from to ./build/deps, which are included in IntelliJ's classpath. - Run src/intellij/setup.sh - - Open ./src/intellij/scala-lang.ipr in IntelliJ + - Open ./src/intellij/scala.ipr in IntelliJ - File, Project Settings, Project, SDK. Create an SDK entry named "1.6" containing the - java 1.6 SDK + Java 1.6 SDK diff --git a/src/intellij/actors.iml.SAMPLE b/src/intellij/actors.iml.SAMPLE index b15af8b110..dfdf396c46 100644 --- a/src/intellij/actors.iml.SAMPLE +++ b/src/intellij/actors.iml.SAMPLE @@ -1,16 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="languageLevel" value="Scala 2.11" /> - <option name="maximumHeapSize" value="1536" /> - <option name="vmOptions" value="-Xms1536m -Xss1m -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=256m -XX:+CMSClassUnloadingEnabled -XX:+UseCompressedOops -XX:+UseParallelGC" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../actors"> @@ -20,6 +9,6 @@ <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="module" module-name="library" /> <orderEntry type="module" module-name="forkjoin" /> + <orderEntry type="library" name="starr" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/asm.iml.SAMPLE b/src/intellij/asm.iml.SAMPLE index ba9e7e899f..9886154bdf 100644 --- a/src/intellij/asm.iml.SAMPLE +++ b/src/intellij/asm.iml.SAMPLE @@ -8,5 +8,4 @@ <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/compiler.iml.SAMPLE b/src/intellij/compiler.iml.SAMPLE index 50253000ab..0e121925e6 100644 --- a/src/intellij/compiler.iml.SAMPLE +++ b/src/intellij/compiler.iml.SAMPLE @@ -1,27 +1,17 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="languageLevel" value="Scala 2.11" /> - <option name="maximumHeapSize" value="1536" /> - <option name="vmOptions" value="-Xms1536m -Xss1m -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=256m -XX:+CMSClassUnloadingEnabled -XX:+UseCompressedOops -XX:+UseParallelGC" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../compiler"> + <sourceFolder url="file://$MODULE_DIR$/../compiler/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/../compiler" isTestSource="false" /> </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="module" module-name="library" /> <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="asm" /> + <orderEntry type="library" name="starr" level="project" /> <orderEntry type="library" name="ant" level="project" /> + <orderEntry type="library" name="asm" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/forkjoin.iml.SAMPLE b/src/intellij/forkjoin.iml.SAMPLE index be807cc019..42507b2911 100644 --- a/src/intellij/forkjoin.iml.SAMPLE +++ b/src/intellij/forkjoin.iml.SAMPLE @@ -8,5 +8,4 @@ <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/interactive.iml.SAMPLE b/src/intellij/interactive.iml.SAMPLE index 83178021d3..047b5c9069 100644 --- a/src/intellij/interactive.iml.SAMPLE +++ b/src/intellij/interactive.iml.SAMPLE @@ -1,16 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="languageLevel" value="Scala 2.11" /> - <option name="maximumHeapSize" value="1536" /> - <option name="vmOptions" value="-Xms1536m -Xss1m -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=256m -XX:+CMSClassUnloadingEnabled -XX:+UseCompressedOops -XX:+UseParallelGC" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../interactive"> @@ -18,10 +7,9 @@ </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="module" module-name="compiler" /> <orderEntry type="module" module-name="library" /> <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="module" module-name="scaladoc" /> + <orderEntry type="library" name="starr" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/library.iml.SAMPLE b/src/intellij/library.iml.SAMPLE index 137ce6eb9c..b03fef9414 100644 --- a/src/intellij/library.iml.SAMPLE +++ b/src/intellij/library.iml.SAMPLE @@ -1,25 +1,14 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="compilerOptions" value="-sourcepath $MODULE_DIR$/../library" /> - <option name="languageLevel" value="Scala 2.11" /> - <option name="maximumHeapSize" value="1536" /> - <option name="vmOptions" value="-Xms1536m -Xss1m -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=256m -XX:+CMSClassUnloadingEnabled -XX:+UseCompressedOops -XX:+UseParallelGC" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../library"> + <sourceFolder url="file://$MODULE_DIR$/../library/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/../library" isTestSource="false" /> </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="module" module-name="forkjoin" /> + <orderEntry type="library" name="starr" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/manual.iml.SAMPLE b/src/intellij/manual.iml.SAMPLE index 8babde73ea..97bfb5940a 100644 --- a/src/intellij/manual.iml.SAMPLE +++ b/src/intellij/manual.iml.SAMPLE @@ -1,16 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="languageLevel" value="Scala 2.11" /> - <option name="maximumHeapSize" value="1536" /> - <option name="vmOptions" value="-Xms1536m -Xss1m -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=256m -XX:+CMSClassUnloadingEnabled -XX:+UseCompressedOops -XX:+UseParallelGC" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../manual"> @@ -19,8 +8,8 @@ <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="module" module-name="library" /> - <orderEntry type="library" name="ant" level="project" /> <orderEntry type="library" name="scaladoc-deps" level="project" /> + <orderEntry type="library" name="ant" level="project" /> + <orderEntry type="library" name="starr" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/partest-extras.iml.SAMPLE b/src/intellij/partest-extras.iml.SAMPLE index c2ada43493..1cd712184b 100644 --- a/src/intellij/partest-extras.iml.SAMPLE +++ b/src/intellij/partest-extras.iml.SAMPLE @@ -1,14 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="languageLevel" value="Scala 2.11" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../partest-extras"> @@ -16,12 +7,12 @@ </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="asm" /> + <orderEntry type="module" module-name="compiler" /> <orderEntry type="module" module-name="library" /> <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="compiler" /> <orderEntry type="module" module-name="repl" /> <orderEntry type="library" name="partest" level="project" /> + <orderEntry type="library" name="starr" level="project" /> + <orderEntry type="library" name="asm" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/partest-javaagent.iml.SAMPLE b/src/intellij/partest-javaagent.iml.SAMPLE index e47e0f6349..ffc540cdb9 100644 --- a/src/intellij/partest-javaagent.iml.SAMPLE +++ b/src/intellij/partest-javaagent.iml.SAMPLE @@ -7,7 +7,6 @@ </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="asm" /> + <orderEntry type="library" name="asm" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/reflect.iml.SAMPLE b/src/intellij/reflect.iml.SAMPLE index d206304896..c9b7130aef 100644 --- a/src/intellij/reflect.iml.SAMPLE +++ b/src/intellij/reflect.iml.SAMPLE @@ -1,17 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="compilerOptions" value="-sourcepath $MODULE_DIR$/../reflect" /> - <option name="languageLevel" value="Scala 2.11" /> - <option name="maximumHeapSize" value="1536" /> - <option name="vmOptions" value="-Xms1536m -Xss1m -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=256m -XX:+CMSClassUnloadingEnabled -XX:+UseCompressedOops -XX:+UseParallelGC" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../reflect"> @@ -20,6 +8,6 @@ <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="module" module-name="library" /> + <orderEntry type="library" name="starr" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/repl.iml.SAMPLE b/src/intellij/repl.iml.SAMPLE index 83791f4f6e..7476f30131 100644 --- a/src/intellij/repl.iml.SAMPLE +++ b/src/intellij/repl.iml.SAMPLE @@ -1,16 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="languageLevel" value="Scala 2.11" /> - <option name="maximumHeapSize" value="1536" /> - <option name="vmOptions" value="-Xms1536m -Xss1m -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=256m -XX:+CMSClassUnloadingEnabled -XX:+UseCompressedOops -XX:+UseParallelGC" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../repl"> @@ -18,10 +7,11 @@ </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="module" module-name="compiler" /> <orderEntry type="module" module-name="library" /> <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="compiler" /> + <orderEntry type="library" name="starr" level="project" /> <orderEntry type="library" name="repl-deps" level="project" /> + <orderEntry type="library" name="asm" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/scala-lang.ipr.SAMPLE b/src/intellij/scala-lang.ipr.SAMPLE deleted file mode 100644 index 0cd3fdae6a..0000000000 --- a/src/intellij/scala-lang.ipr.SAMPLE +++ /dev/null @@ -1,287 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="CompilerConfiguration"> - <option name="DEFAULT_COMPILER" value="Javac" /> - <resourceExtensions> - <entry name=".+\.(properties|xml|html|dtd|tld)" /> - <entry name=".+\.(gif|png|jpeg|jpg)" /> - </resourceExtensions> - <wildcardResourcePatterns> - <entry name="?*.properties" /> - <entry name="?*.xml" /> - <entry name="?*.gif" /> - <entry name="?*.png" /> - <entry name="?*.jpeg" /> - <entry name="?*.jpg" /> - <entry name="?*.html" /> - <entry name="?*.dtd" /> - <entry name="?*.tld" /> - <entry name="?*.ftl" /> - </wildcardResourcePatterns> - <annotationProcessing> - <profile default="true" name="Default" enabled="false"> - <processorPath useClasspath="true" /> - </profile> - </annotationProcessing> - </component> - <component name="CopyrightManager" default="" /> - <component name="DependencyValidationManager"> - <option name="SKIP_IMPORT_STATEMENTS" value="false" /> - </component> - <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" /> - <component name="EntryPointsManager"> - <entry_points version="2.0" /> - </component> - <component name="HighlightingAdvisor"> - <option name="SUGGEST_TYPE_AWARE_HIGHLIGHTING" value="false" /> - </component> - <component name="InspectionProjectProfileManager"> - <profiles> - <profile version="1.0" is_locked="false"> - <option name="myName" value="Project Default" /> - <option name="myLocal" value="false" /> - <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false"> - <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" /> - <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" /> - </inspection_tool> - <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false"> - <option name="processCode" value="true" /> - <option name="processLiterals" value="true" /> - <option name="processComments" value="true" /> - </inspection_tool> - <inspection_tool class="UnitMethodIsParameterless" enabled="false" level="WARNING" enabled_by_default="false" /> - </profile> - </profiles> - <option name="PROJECT_PROFILE" value="Project Default" /> - <option name="USE_PROJECT_PROFILE" value="true" /> - <version value="1.0" /> - </component> - <component name="JavacSettings"> - <option name="ADDITIONAL_OPTIONS_STRING" value="-source 1.6 -target 1.6" /> - </component> - <component name="JavadocGenerationManager"> - <option name="OUTPUT_DIRECTORY" /> - <option name="OPTION_SCOPE" value="protected" /> - <option name="OPTION_HIERARCHY" value="true" /> - <option name="OPTION_NAVIGATOR" value="true" /> - <option name="OPTION_INDEX" value="true" /> - <option name="OPTION_SEPARATE_INDEX" value="true" /> - <option name="OPTION_DOCUMENT_TAG_USE" value="false" /> - <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" /> - <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" /> - <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" /> - <option name="OPTION_DEPRECATED_LIST" value="true" /> - <option name="OTHER_OPTIONS" value="" /> - <option name="HEAP_SIZE" /> - <option name="LOCALE" /> - <option name="OPEN_IN_BROWSER" value="true" /> - </component> - <component name="Palette2"> - <group name="Swing"> - <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" /> - </item> - <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" /> - </item> - <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" /> - </item> - <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true"> - <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" /> - </item> - <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" /> - <initial-values> - <property name="text" value="Button" /> - </initial-values> - </item> - <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" /> - <initial-values> - <property name="text" value="RadioButton" /> - </initial-values> - </item> - <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" /> - <initial-values> - <property name="text" value="CheckBox" /> - </initial-values> - </item> - <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" /> - <initial-values> - <property name="text" value="Label" /> - </initial-values> - </item> - <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> - <preferred-size width="150" height="-1" /> - </default-constraints> - </item> - <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> - <preferred-size width="150" height="-1" /> - </default-constraints> - </item> - <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> - <preferred-size width="150" height="-1" /> - </default-constraints> - </item> - <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" /> - </item> - <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3"> - <preferred-size width="200" height="200" /> - </default-constraints> - </item> - <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3"> - <preferred-size width="200" height="200" /> - </default-constraints> - </item> - <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" /> - </item> - <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" /> - </item> - <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" /> - </item> - <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" /> - </item> - <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1"> - <preferred-size width="-1" height="20" /> - </default-constraints> - </item> - <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" /> - </item> - <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" /> - </item> - </group> - </component> - <component name="ProjectDictionaryState"> - <dictionary name="luc" /> - </component> - <component name="ProjectModuleManager"> - <modules> - <module fileurl="file://$PROJECT_DIR$/actors.iml" filepath="$PROJECT_DIR$/actors.iml" /> - <module fileurl="file://$PROJECT_DIR$/asm.iml" filepath="$PROJECT_DIR$/asm.iml" /> - <module fileurl="file://$PROJECT_DIR$/compiler.iml" filepath="$PROJECT_DIR$/compiler.iml" /> - <module fileurl="file://$PROJECT_DIR$/forkjoin.iml" filepath="$PROJECT_DIR$/forkjoin.iml" /> - <module fileurl="file://$PROJECT_DIR$/interactive.iml" filepath="$PROJECT_DIR$/interactive.iml" /> - <module fileurl="file://$PROJECT_DIR$/library.iml" filepath="$PROJECT_DIR$/library.iml" /> - <module fileurl="file://$PROJECT_DIR$/manual.iml" filepath="$PROJECT_DIR$/manual.iml" /> - <module fileurl="file://$PROJECT_DIR$/partest-extras.iml" filepath="$PROJECT_DIR$/partest-extras.iml" /> - <module fileurl="file://$PROJECT_DIR$/partest-javaagent.iml" filepath="$PROJECT_DIR$/partest-javaagent.iml" /> - <module fileurl="file://$PROJECT_DIR$/reflect.iml" filepath="$PROJECT_DIR$/reflect.iml" /> - <module fileurl="file://$PROJECT_DIR$/repl.iml" filepath="$PROJECT_DIR$/repl.iml" /> - <module fileurl="file://$PROJECT_DIR$/scala.iml" filepath="$PROJECT_DIR$/scala.iml" /> - <module fileurl="file://$PROJECT_DIR$/scaladoc.iml" filepath="$PROJECT_DIR$/scaladoc.iml" /> - <module fileurl="file://$PROJECT_DIR$/scalap.iml" filepath="$PROJECT_DIR$/scalap.iml" /> - <module fileurl="file://$PROJECT_DIR$/test.iml" filepath="$PROJECT_DIR$/test.iml" /> - <module fileurl="file://$PROJECT_DIR$/test-junit.iml" filepath="$PROJECT_DIR$/test-junit.iml" /> - <module fileurl="file://$PROJECT_DIR$/test-osgi.iml" filepath="$PROJECT_DIR$/test-osgi.iml" /> - </modules> - </component> - <component name="ProjectResources"> - <default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype> - </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK"> - <output url="file://$PROJECT_DIR$/../../out" /> - </component> - <component name="ScalacSettings"> - <option name="COMPILER_LIBRARY_NAME" value="compiler-locker" /> - <option name="COMPILER_LIBRARY_LEVEL" value="Project" /> - </component> - <component name="VcsDirectoryMappings"> - <mapping directory="$PROJECT_DIR$/../.." vcs="Git" /> - </component> - <component name="libraryTable"> - <library name="ant"> - <CLASSES> - <root url="jar://$PROJECT_DIR$/../../lib/ant/ant.jar!/" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - </library> - <library name="junit"> - <CLASSES> - <root url="file://$PROJECT_DIR$/../../build/deps/junit" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/junit" recursive="false" /> - </library> - <library name="partest"> - <CLASSES> - <root url="file://$PROJECT_DIR$/../../build/deps/partest" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/partest" recursive="false" /> - </library> - <library name="repl-deps"> - <CLASSES> - <root url="file://$PROJECT_DIR$/../../build/deps/repl" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/repl" recursive="false" /> - </library> - <library name="scaladoc-deps"> - <CLASSES> - <root url="file://$PROJECT_DIR$/../../build/deps/scaladoc" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/scaladoc" recursive="false" /> - </library> - <library name="starr"> - <CLASSES> - <root url="file://$PROJECT_DIR$/../../build/deps/starr" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/starr" recursive="false" /> - </library> - </component> -</project> - diff --git a/src/intellij/scala.iml.SAMPLE b/src/intellij/scala.iml.SAMPLE index a4d863800b..9e8718dd45 100644 --- a/src/intellij/scala.iml.SAMPLE +++ b/src/intellij/scala.iml.SAMPLE @@ -8,5 +8,4 @@ <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/scala.ipr.SAMPLE b/src/intellij/scala.ipr.SAMPLE new file mode 100644 index 0000000000..47ac2be188 --- /dev/null +++ b/src/intellij/scala.ipr.SAMPLE @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="CompilerConfiguration"> + <option name="DEFAULT_COMPILER" value="Javac" /> + <resourceExtensions /> + <wildcardResourcePatterns> + <entry name="!?*.java" /> + <entry name="!?*.form" /> + <entry name="!?*.class" /> + <entry name="!?*.groovy" /> + <entry name="!?*.scala" /> + <entry name="!?*.flex" /> + <entry name="!?*.kt" /> + <entry name="!?*.clj" /> + </wildcardResourcePatterns> + <annotationProcessing> + <profile default="true" name="Default" enabled="false"> + <processorPath useClasspath="true" /> + </profile> + </annotationProcessing> + </component> + <component name="CopyrightManager" default="" /> + <component name="EntryPointsManager"> + <entry_points version="2.0" /> + </component> + <component name="ProjectLevelVcsManager" settingsEditedManually="false"> + <OptionsSetting value="true" id="Add" /> + <OptionsSetting value="true" id="Remove" /> + <OptionsSetting value="true" id="Checkout" /> + <OptionsSetting value="true" id="Update" /> + <OptionsSetting value="true" id="Status" /> + <OptionsSetting value="true" id="Edit" /> + <ConfirmationsSetting value="0" id="Add" /> + <ConfirmationsSetting value="0" id="Remove" /> + </component> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/actors.iml" filepath="$PROJECT_DIR$/actors.iml" /> + <module fileurl="file://$PROJECT_DIR$/compiler.iml" filepath="$PROJECT_DIR$/compiler.iml" /> + <module fileurl="file://$PROJECT_DIR$/forkjoin.iml" filepath="$PROJECT_DIR$/forkjoin.iml" /> + <module fileurl="file://$PROJECT_DIR$/interactive.iml" filepath="$PROJECT_DIR$/interactive.iml" /> + <module fileurl="file://$PROJECT_DIR$/library.iml" filepath="$PROJECT_DIR$/library.iml" /> + <module fileurl="file://$PROJECT_DIR$/manual.iml" filepath="$PROJECT_DIR$/manual.iml" /> + <module fileurl="file://$PROJECT_DIR$/partest-extras.iml" filepath="$PROJECT_DIR$/partest-extras.iml" /> + <module fileurl="file://$PROJECT_DIR$/partest-javaagent.iml" filepath="$PROJECT_DIR$/partest-javaagent.iml" /> + <module fileurl="file://$PROJECT_DIR$/reflect.iml" filepath="$PROJECT_DIR$/reflect.iml" /> + <module fileurl="file://$PROJECT_DIR$/repl.iml" filepath="$PROJECT_DIR$/repl.iml" /> + <module fileurl="file://$PROJECT_DIR$/scala.iml" filepath="$PROJECT_DIR$/scala.iml" /> + <module fileurl="file://$PROJECT_DIR$/scaladoc.iml" filepath="$PROJECT_DIR$/scaladoc.iml" /> + <module fileurl="file://$PROJECT_DIR$/scalap.iml" filepath="$PROJECT_DIR$/scalap.iml" /> + <module fileurl="file://$PROJECT_DIR$/test.iml" filepath="$PROJECT_DIR$/test.iml" /> + <module fileurl="file://$PROJECT_DIR$/test-junit.iml" filepath="$PROJECT_DIR$/test-junit.iml" /> + </modules> + </component> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK"> + <output url="file://$PROJECT_DIR$/../../out" /> + </component> + <component name="ScalaCompilerConfiguration"> + <parameters> + <parameter value="-sourcepath" /> + <parameter value="$PROJECT_DIR$/../library" /> + </parameters> + </component> + <component name="VcsDirectoryMappings"> + <mapping directory="$PROJECT_DIR$/../.." vcs="Git" /> + </component> + <component name="libraryTable"> + <library name="ant"> + <CLASSES> + <root url="jar://$PROJECT_DIR$/../../lib/ant/ant.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> + <library name="asm"> + <CLASSES> + <root url="file://$PROJECT_DIR$/../../build/deps/asm" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/asm" recursive="false" /> + </library> + <library name="junit"> + <CLASSES> + <root url="file://$PROJECT_DIR$/../../build/deps/junit" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/junit" recursive="false" /> + </library> + <library name="partest"> + <CLASSES> + <root url="file://$PROJECT_DIR$/../../build/deps/partest" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/partest" recursive="false" /> + </library> + <library name="repl-deps"> + <CLASSES> + <root url="file://$PROJECT_DIR$/../../build/deps/repl" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/repl" recursive="false" /> + </library> + <library name="scaladoc-deps"> + <CLASSES> + <root url="file://$PROJECT_DIR$/../../build/deps/scaladoc" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + <jarDirectory url="file://$PROJECT_DIR$/../../build/deps/scaladoc" recursive="false" /> + </library> + <library name="starr" type="Scala"> + <properties> + <compiler-classpath> + <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-compiler-#starr-version#.jar" /> + <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-library-#starr-version#.jar" /> + <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-reflect-#starr-version#.jar" /> + </compiler-classpath> + </properties> + <CLASSES /> + <JAVADOC /> + <SOURCES /> + </library> + </component> +</project>
\ No newline at end of file diff --git a/src/intellij/scaladoc.iml.SAMPLE b/src/intellij/scaladoc.iml.SAMPLE index 8f9a0d8344..4ba0a848c6 100644 --- a/src/intellij/scaladoc.iml.SAMPLE +++ b/src/intellij/scaladoc.iml.SAMPLE @@ -1,16 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="languageLevel" value="Scala 2.11" /> - <option name="maximumHeapSize" value="1536" /> - <option name="vmOptions" value="-Xms1536m -Xss1m -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=256m -XX:+CMSClassUnloadingEnabled -XX:+UseCompressedOops -XX:+UseParallelGC" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../scaladoc"> @@ -18,11 +7,12 @@ </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="module" module-name="compiler" /> <orderEntry type="module" module-name="library" /> <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="library" name="partest" level="project" /> + <orderEntry type="library" name="starr" level="project" /> <orderEntry type="library" name="scaladoc-deps" level="project" /> + <orderEntry type="library" name="ant" level="project" /> + <orderEntry type="library" name="partest" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/scalap.iml.SAMPLE b/src/intellij/scalap.iml.SAMPLE index 27ae451369..665aac07f8 100644 --- a/src/intellij/scalap.iml.SAMPLE +++ b/src/intellij/scalap.iml.SAMPLE @@ -1,16 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="languageLevel" value="Scala 2.11" /> - <option name="maximumHeapSize" value="1536" /> - <option name="vmOptions" value="-Xms1536m -Xss1m -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=256m -XX:+CMSClassUnloadingEnabled -XX:+UseCompressedOops -XX:+UseParallelGC" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../scalap"> @@ -19,8 +8,8 @@ <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="reflect" /> <orderEntry type="module" module-name="compiler" /> + <orderEntry type="module" module-name="reflect" /> + <orderEntry type="library" name="starr" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/setup.sh b/src/intellij/setup.sh index ec303778ed..251f717829 100755 --- a/src/intellij/setup.sh +++ b/src/intellij/setup.sh @@ -12,3 +12,6 @@ for f in "$SCRIPT_DIR"/*.SAMPLE; do g=${f%.SAMPLE} cp $f $g done + +STARR_VERSION="`cat $SCRIPT_DIR/../../versions.properties | grep 'starr.version' | awk '{split($0,a,"="); print a[2]}'`" +sed "s/#starr-version#/$STARR_VERSION/g" $SCRIPT_DIR/scala.ipr.SAMPLE > $SCRIPT_DIR/scala.ipr diff --git a/src/intellij/test-junit.iml.SAMPLE b/src/intellij/test-junit.iml.SAMPLE index bb51c30a4f..86dc39c175 100644 --- a/src/intellij/test-junit.iml.SAMPLE +++ b/src/intellij/test-junit.iml.SAMPLE @@ -1,13 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../../test/junit"> @@ -16,15 +8,16 @@ <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="module" module-name="actors" /> - <orderEntry type="module" module-name="asm" /> <orderEntry type="module" module-name="compiler" /> + <orderEntry type="module" module-name="forkjoin" /> <orderEntry type="module" module-name="library" /> + <orderEntry type="module" module-name="partest-extras" /> <orderEntry type="module" module-name="reflect" /> <orderEntry type="module" module-name="repl" /> - <orderEntry type="module" module-name="partest-extras" /> - <orderEntry type="module" module-name="forkjoin" /> - <orderEntry type="library" name="junit" level="project" /> + <orderEntry type="module" module-name="scaladoc" /> <orderEntry type="library" name="scaladoc-deps" level="project" /> + <orderEntry type="library" name="junit" level="project" /> + <orderEntry type="library" name="starr" level="project" /> + <orderEntry type="library" name="asm" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/intellij/test-osgi.iml.SAMPLE b/src/intellij/test-osgi.iml.SAMPLE deleted file mode 100644 index a589aaa0a9..0000000000 --- a/src/intellij/test-osgi.iml.SAMPLE +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../../test/osgi"> - <sourceFolder url="file://$MODULE_DIR$/../../test/osgi/src" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="actors" /> - <orderEntry type="module" module-name="asm" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="repl" /> - <orderEntry type="module" module-name="partest-extras" /> - <orderEntry type="module" module-name="forkjoin" /> - <orderEntry type="library" name="junit" level="project" /> - <orderEntry type="library" name="scaladoc-deps" level="project" /> - <orderEntry type="library" name="scala-sdk" level="project" /> - <orderEntry type="library" scope="PROVIDED" name="pax.exam-deps" level="project" /> - </component> -</module>
\ No newline at end of file diff --git a/src/intellij/test.iml.SAMPLE b/src/intellij/test.iml.SAMPLE index cb4a8568a1..5047967721 100644 --- a/src/intellij/test.iml.SAMPLE +++ b/src/intellij/test.iml.SAMPLE @@ -1,14 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="scala" name="Scala"> - <configuration> - <option name="compilerLibraryLevel" value="Project" /> - <option name="compilerLibraryName" value="starr" /> - <option name="languageLevel" value="Scala 2.11" /> - </configuration> - </facet> - </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$/../../test"> @@ -16,16 +7,16 @@ </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="library" /> - <orderEntry type="module" module-name="reflect" /> - <orderEntry type="module" module-name="compiler" /> - <orderEntry type="module" module-name="repl" /> <orderEntry type="module" module-name="actors" /> - <orderEntry type="module" module-name="asm" /> + <orderEntry type="module" module-name="compiler" /> <orderEntry type="module" module-name="forkjoin" /> + <orderEntry type="module" module-name="interactive" /> + <orderEntry type="module" module-name="library" /> <orderEntry type="module" module-name="partest-extras" /> - <orderEntry type="library" name="scaladoc-deps" level="project" /> + <orderEntry type="module" module-name="reflect" /> + <orderEntry type="module" module-name="repl" /> <orderEntry type="library" name="partest" level="project" /> + <orderEntry type="library" name="scaladoc-deps" level="project" /> + <orderEntry type="library" name="asm" level="project" /> </component> -</module> - +</module>
\ No newline at end of file diff --git a/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala b/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala index 2e4f6b08e9..9caebb711d 100644 --- a/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala @@ -302,7 +302,7 @@ trait CompilerControl { self: Global => abstract class WorkItem extends (() => Unit) { val onCompilerThread = self.onCompilerThread - /** Raise a MissingReponse, if the work item carries a response. */ + /** Raise a MissingResponse, if the work item carries a response. */ def raiseMissing(): Unit } diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala index 2d09435f60..727bfdd510 100644 --- a/src/interactive/scala/tools/nsc/interactive/Global.scala +++ b/src/interactive/scala/tools/nsc/interactive/Global.scala @@ -315,7 +315,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") private val NoResponse: Response[_] = new Response[Any] /** The response that is currently pending, i.e. the compiler - * is working on providing an asnwer for it. + * is working on providing an answer for it. */ private var pendingResponse: Response[_] = NoResponse diff --git a/src/interactive/scala/tools/nsc/interactive/Lexer.scala b/src/interactive/scala/tools/nsc/interactive/Lexer.scala index 82e8de3f3d..7daf24c204 100644 --- a/src/interactive/scala/tools/nsc/interactive/Lexer.scala +++ b/src/interactive/scala/tools/nsc/interactive/Lexer.scala @@ -195,7 +195,7 @@ class Lexer(rd: Reader) { case 'n' => putAcceptString("null"); token = NullLit case '"' => getString() case '-' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => getNumber() - case _ => error("unrecoginezed start of token: '"+ch+"'") + case _ => error("unrecognized start of token: '"+ch+"'") } //println("["+token+"]") } diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index 6ab82d998e..d89e9d291d 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -483,7 +483,7 @@ object Array extends FallbackArrayBuilding { * * @author Martin Odersky * @version 1.0 - * @see [[http://www.scala-lang.org/docu/files/ScalaReference.pdf 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://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. * @define coll array diff --git a/src/library/scala/Mutable.scala b/src/library/scala/Mutable.scala index 8ef0424db6..43f98ee4df 100644 --- a/src/library/scala/Mutable.scala +++ b/src/library/scala/Mutable.scala @@ -11,7 +11,7 @@ package scala /** - * A marker trait for mutable datatructures such as mutable collections + * A marker trait for mutable data structures such as mutable collections * * @since 2.8 */ diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index bf7739345e..0f300412b7 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -35,9 +35,9 @@ import scala.io.StdIn * === Assertions === * * A set of `assert` functions are provided for use as a way to document - * and dynamically check invariants in code. `assert` statements can be elided - * at runtime by providing the command line argument `-Xdisable-assertions` to - * the `scala` command. + * and dynamically check invariants in code. Invocations of `assert` can be elided + * at compile time by providing the command line option `-Xdisable-assertions`, + * which raises `-Xelide-below` above `elidable.ASSERTION`, to the `scalac` command. * * Variants of `assert` intended for use with static analysis tools are also * provided: `assume`, `require` and `ensuring`. `require` and `ensuring` are @@ -58,7 +58,7 @@ import scala.io.StdIn * condition fails, then the caller of the function is to blame rather than a * logical error having been made within `addNaturals` itself. `ensures` is a * form of `assert` that declares the guarantee the function is providing with - * regards to it's return value. + * regards to its return value. * * === Implicit Conversions === * A number of commonly applied implicit conversions are also defined here, and @@ -85,7 +85,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { type String = java.lang.String type Class[T] = java.lang.Class[T] - // miscelleaneous ----------------------------------------------------- + // miscellaneous ----------------------------------------------------- scala.`package` // to force scala package object to be seen. scala.collection.immutable.List // to force Nil, :: to be seen. diff --git a/src/library/scala/annotation/switch.scala b/src/library/scala/annotation/switch.scala index 23e3923407..00124cf88b 100644 --- a/src/library/scala/annotation/switch.scala +++ b/src/library/scala/annotation/switch.scala @@ -22,6 +22,9 @@ package scala.annotation } }}} * + * Note: for pattern matches with one or two cases, the compiler generates jump instructions. + * Annotating such a match with `@switch` does not issue any warning. + * * @author Paul Phillips * @since 2.8 */ diff --git a/src/library/scala/collection/GenSeqLike.scala b/src/library/scala/collection/GenSeqLike.scala index cf1de0c8e6..f786293822 100644 --- a/src/library/scala/collection/GenSeqLike.scala +++ b/src/library/scala/collection/GenSeqLike.scala @@ -275,6 +275,7 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal * @tparam That $thatinfo * @param bf $bfinfo * @return a new $coll` which is a copy of this $coll with the element at position `index` replaced by `elem`. + * @throws IndexOutOfBoundsException if `index` does not satisfy `0 <= index < length`. * * @usecase def updated(index: Int, elem: A): $Coll[A] * @inheritdoc diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 0783beac0f..c9037eb3e3 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -580,29 +580,21 @@ trait Iterator[+A] extends TraversableOnce[A] { def span(p: A => Boolean): (Iterator[A], Iterator[A]) = { val self = buffered - /* - * Giving a name to following iterator (as opposed to trailing) because - * anonymous class is represented as a structural type that trailing - * iterator is referring (the finish() method) and thus triggering - * handling of structural calls. It's not what's intended here. - */ + // Must be a named class to avoid structural call to finish from trailing iterator class Leading extends AbstractIterator[A] { - val lookahead = new mutable.Queue[A] - def advance() = { - self.hasNext && p(self.head) && { - lookahead += self.next - true - } + private val drained = new mutable.Queue[A] + private var finished = false + def finish(): Unit = { + require(!finished) + finished = true + while (selfish) drained += self.next } - def finish() = { - while (advance()) () - } - def hasNext = lookahead.nonEmpty || advance() + private def selfish = self.hasNext && p(self.head) + def hasNext = if (finished) drained.nonEmpty else selfish def next() = { - if (lookahead.isEmpty) - advance() - - lookahead.dequeue() + if (finished) drained.dequeue() + else if (selfish) self.next() + else empty.next() } } val leading = new Leading diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala index 66fce0f902..b775480532 100644 --- a/src/library/scala/collection/SeqLike.scala +++ b/src/library/scala/collection/SeqLike.scala @@ -413,7 +413,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ * @inheritdoc * * Another way to express this - * is that `xs union ys` computes the order-presevring multi-set union of `xs` and `ys`. + * is that `xs union ys` computes the order-preserving multi-set union of `xs` and `ys`. * `union` is hence a counter-part of `diff` and `intersect` which also work on multi-sets. * * $willNotTerminateInf diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index 32d31f0be8..96374ef653 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -54,7 +54,7 @@ import scala.language.higherKinds * `HashMap` of objects. The traversal order for hash maps will * depend on the hash codes of its elements, and these hash codes might * differ from one run to the next. By contrast, a `LinkedHashMap` - * is ordered because it's `foreach` method visits elements in the + * is ordered because its `foreach` method visits elements in the * order they were inserted into the `HashMap`. * * @author Martin Odersky diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala index 2eab58009c..c5b0d0f085 100644 --- a/src/library/scala/collection/TraversableOnce.scala +++ b/src/library/scala/collection/TraversableOnce.scala @@ -128,8 +128,21 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { * @example `Seq("a", 1, 5L).collectFirst({ case x: Int => x*10 }) = Some(10)` */ def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = { - // make sure to use an iterator or `seq` - self.toIterator.foreach(pf.runWith(b => return Some(b))) + // TODO 2.12 -- move out alternate implementations into child classes + val i: Iterator[A] = self match { + case it: Iterator[A] => it + case _: GenIterable[_] => self.toIterator // If it might be parallel, be sure to .seq or use iterator! + case _ => // Not parallel, not iterable--just traverse + self.foreach(pf.runWith(b => return Some(b))) + return None + } + // Presumably the fastest way to get in and out of a partial function is for a sentinel function to return itself + // (Tested to be lower-overhead than runWith. Would be better yet to not need to (formally) allocate it--change in 2.12.) + val sentinel: Function1[A, Any] = new scala.runtime.AbstractFunction1[A, Any]{ def apply(a: A) = this } + while (i.hasNext) { + val x = pf.applyOrElse(i.next, sentinel) + if (x.asInstanceOf[AnyRef] ne sentinel) return Some(x.asInstanceOf[B]) + } None } diff --git a/src/library/scala/collection/concurrent/Map.scala b/src/library/scala/collection/concurrent/Map.scala index 2eea15b8dc..cfb567abe9 100644 --- a/src/library/scala/collection/concurrent/Map.scala +++ b/src/library/scala/collection/concurrent/Map.scala @@ -49,7 +49,7 @@ trait Map[A, B] extends scala.collection.mutable.Map[A, B] { def putIfAbsent(k: A, v: B): Option[B] /** - * Removes the entry for the specified key if its currently mapped to the + * Removes the entry for the specified key if it's currently mapped to the * specified value. * * $atomicop diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index 98266716cc..53af3ce158 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -56,11 +56,12 @@ class Queue[+A] protected(protected val in: List[A], protected val out: List[A]) * @throws java.util.NoSuchElementException if the queue is too short. */ override def apply(n: Int): A = { - val len = out.length - if (n < len) out.apply(n) + val olen = out.length + if (n < olen) out.apply(n) else { - val m = n - len - if (m < in.length) in.reverse.apply(m) + val m = n - olen + val ilen = in.length + if (m < ilen) in.apply(ilen - m - 1) else throw new NoSuchElementException("index out of range") } } diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index f303e79bb3..cf7b7e272a 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -360,7 +360,7 @@ self => * `List(BigInt(12)) ++ fibs`. * * @tparam B The element type of the returned collection.'''That''' - * @param that The [[scala.collection.GenTraversableOnce]] the be contatenated + * @param that The [[scala.collection.GenTraversableOnce]] the be concatenated * to this `Stream`. * @return A new collection containing the result of concatenating `this` with * `that`. diff --git a/src/library/scala/collection/mutable/AVLTree.scala b/src/library/scala/collection/mutable/AVLTree.scala index cc2acb74d4..b63d0aae33 100644 --- a/src/library/scala/collection/mutable/AVLTree.scala +++ b/src/library/scala/collection/mutable/AVLTree.scala @@ -27,7 +27,7 @@ private[mutable] sealed trait AVLTree[+A] extends Serializable { /** * Returns a new tree containing the given element. - * Thows an IllegalArgumentException if element is already present. + * Throws an IllegalArgumentException if element is already present. * */ def insert[B >: A](value: B, ordering: Ordering[B]): AVLTree[B] = Node(value, Leaf, Leaf) @@ -95,7 +95,7 @@ private case class Node[A](data: A, left: AVLTree[A], right: AVLTree[A]) extends /** * Returns a new tree containing the given element. - * Thows an IllegalArgumentException if element is already present. + * Throws an IllegalArgumentException if element is already present. * */ override def insert[B >: A](value: B, ordering: Ordering[B]) = { diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala index 65d9c35052..b48a32fa37 100644 --- a/src/library/scala/collection/mutable/HashTable.scala +++ b/src/library/scala/collection/mutable/HashTable.scala @@ -449,7 +449,7 @@ private[collection] object HashTable { // h /* OLD VERSION - * quick, but bad for sequence 0-10000 - little enthropy in higher bits + * quick, but bad for sequence 0-10000 - little entropy in higher bits * since 2003 */ // var h: Int = hcode + ~(hcode << 9) // h = h ^ (h >>> 14) diff --git a/src/library/scala/collection/mutable/UnrolledBuffer.scala b/src/library/scala/collection/mutable/UnrolledBuffer.scala index 693c47d86e..2212486bcf 100644 --- a/src/library/scala/collection/mutable/UnrolledBuffer.scala +++ b/src/library/scala/collection/mutable/UnrolledBuffer.scala @@ -85,7 +85,7 @@ extends scala.collection.mutable.AbstractBuffer[T] def classTagCompanion = UnrolledBuffer - /** Concatenates the targer unrolled buffer to this unrolled buffer. + /** Concatenates the target unrolled buffer to this unrolled buffer. * * The specified buffer `that` is cleared after this operation. This is * an O(1) operation. @@ -208,7 +208,7 @@ object UnrolledBuffer extends ClassTagTraversableFactory[UnrolledBuffer] { def newBuilder[T](implicit t: ClassTag[T]): Builder[T, UnrolledBuffer[T]] = new UnrolledBuffer[T] val waterline = 50 - val waterlineDelim = 100 + val waterlineDelim = 100 // TODO -- fix this name! It's a denominator, not a delimiter. (But it's part of the API so we can't just change it.) private[collection] val unrolledlength = 32 /** Unrolled buffer node. @@ -319,13 +319,15 @@ object UnrolledBuffer extends ClassTagTraversableFactory[UnrolledBuffer] { for (elem <- t) curr = curr append elem curr.next = newnextnode - // try to merge the last node of this with the newnextnode + // try to merge the last node of this with the newnextnode and fix tail pointer if needed if (curr.tryMergeWithNext()) buffer.lastPtr = curr + else if (newnextnode.next eq null) buffer.lastPtr = newnextnode } - else if (idx == size) { + else if (idx == size || (next eq null)) { var curr = this for (elem <- t) curr = curr append elem - } else insertAll(idx - size, t, buffer) + } + else next.insertAll(idx - size, t, buffer) } private def nullout(from: Int, until: Int) { var idx = from @@ -344,7 +346,7 @@ object UnrolledBuffer extends ClassTagTraversableFactory[UnrolledBuffer] { tryMergeWithNext() } - override def toString = array.take(size).mkString("Unrolled[" + array.length + "](", ", ", ")") + " -> " + (if (next ne null) next.toString else "") + override def toString = array.take(size).mkString("Unrolled@%08x".format(System.identityHashCode(this)) + "[" + size + "/" + array.length + "](", ", ", ")") + " -> " + (if (next ne null) next.toString else "") } } diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index 53fca9f779..8740bda835 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -93,7 +93,7 @@ object WrappedArray { def empty[T <: AnyRef]: WrappedArray[T] = EmptyWrappedArray.asInstanceOf[WrappedArray[T]] // If make is called explicitly we use whatever we're given, even if it's - // empty. This may be unnecesssary (if WrappedArray is to honor the collections + // empty. This may be unnecessary (if WrappedArray is to honor the collections // contract all empty ones must be equal, so discriminating based on the reference // equality of an empty array should not come up) but we may as well be // conservative since wrapRefArray contributes most of the unnecessary allocations. diff --git a/src/library/scala/concurrent/JavaConversions.scala b/src/library/scala/concurrent/JavaConversions.scala index 3d0597ca22..91e55d30cb 100644 --- a/src/library/scala/concurrent/JavaConversions.scala +++ b/src/library/scala/concurrent/JavaConversions.scala @@ -11,7 +11,7 @@ package scala.concurrent import java.util.concurrent.{ExecutorService, Executor} import scala.language.implicitConversions -/** The `JavaConversions` object provides implicit converstions supporting +/** The `JavaConversions` object provides implicit conversions supporting * interoperability between Scala and Java concurrency classes. * * @author Philipp Haller diff --git a/src/library/scala/concurrent/duration/Duration.scala b/src/library/scala/concurrent/duration/Duration.scala index 2eded9f060..182c2d172a 100644 --- a/src/library/scala/concurrent/duration/Duration.scala +++ b/src/library/scala/concurrent/duration/Duration.scala @@ -182,6 +182,7 @@ object Duration { def compare(other: Duration) = if (other eq this) 0 else 1 def unary_- : Duration = this def toUnit(unit: TimeUnit): Double = Double.NaN + private def readResolve(): AnyRef = Undefined // Instructs deserialization to use this same instance } sealed abstract class Infinite extends Duration { @@ -230,7 +231,7 @@ object Duration { * but itself. This value closely corresponds to Double.PositiveInfinity, * matching its semantics in arithmetic operations. */ - val Inf: Infinite = new Infinite { + val Inf: Infinite = new Infinite { override def toString = "Duration.Inf" def compare(other: Duration) = other match { case x if x eq Undefined => -1 // Undefined != Undefined @@ -239,6 +240,7 @@ object Duration { } def unary_- : Duration = MinusInf def toUnit(unit: TimeUnit): Double = Double.PositiveInfinity + private def readResolve(): AnyRef = Inf // Instructs deserialization to use this same instance } /** @@ -251,6 +253,7 @@ object Duration { def compare(other: Duration) = if (other eq this) 0 else -1 def unary_- : Duration = Inf def toUnit(unit: TimeUnit): Double = Double.NegativeInfinity + private def readResolve(): AnyRef = MinusInf // Instructs deserialization to use this same instance } // Java Factories diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index cf95f945ba..d6e2963ad8 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -431,7 +431,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { * with unequal `hashCode`s. These hash codes agree with `BigInt` * for whole numbers up ~4934 digits (the range of IEEE 128 bit floating * point). Beyond this, hash codes will disagree; this prevents the - * explicit represention of the `BigInt` form for `BigDecimal` values + * explicit representation of the `BigInt` form for `BigDecimal` values * with large exponents. */ override def hashCode(): Int = { diff --git a/src/library/scala/sys/process/BasicIO.scala b/src/library/scala/sys/process/BasicIO.scala index b31bbf0540..066b2f5373 100644 --- a/src/library/scala/sys/process/BasicIO.scala +++ b/src/library/scala/sys/process/BasicIO.scala @@ -203,7 +203,7 @@ object BasicIO { /** Returns a `ProcessIO` connected to stdout and stderr, and, optionally, stdin. */ def standard(connectInput: Boolean): ProcessIO = standard(input(connectInput)) - /** Retruns a `ProcessIO` connected to stdout, stderr and the provided `in` */ + /** Returns a `ProcessIO` connected to stdout, stderr and the provided `in` */ def standard(in: OutputStream => Unit): ProcessIO = new ProcessIO(in, toStdOut, toStdErr) /** Send all the input from the stream to stderr, and closes the input stream diff --git a/src/library/scala/sys/process/ProcessLogger.scala b/src/library/scala/sys/process/ProcessLogger.scala index ae347221ef..6072894007 100644 --- a/src/library/scala/sys/process/ProcessLogger.scala +++ b/src/library/scala/sys/process/ProcessLogger.scala @@ -88,7 +88,7 @@ object ProcessLogger { /** Creates a [[scala.sys.process.ProcessLogger]] that sends all output to the corresponding * function. * - * @param fout This function will receive standard outpout. + * @param fout This function will receive standard output. * * @param ferr This function will receive standard error. */ diff --git a/src/library/scala/util/Sorting.scala b/src/library/scala/util/Sorting.scala index 2e021ad9d9..ee2bdbc4a7 100644 --- a/src/library/scala/util/Sorting.scala +++ b/src/library/scala/util/Sorting.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, Ross Judson ** +** / __/ __// _ | / / / _ | (c) 2006-2015, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -9,518 +9,276 @@ package scala package util -import scala.reflect.{ ClassTag, classTag } -import scala.math.{ Ordering, max, min } +import scala.reflect.ClassTag +import scala.math.Ordering -/** The Sorting object provides functions that can sort various kinds of - * objects. You can provide a comparison function, or you can request a sort - * of items that are viewable as [[scala.math.Ordered]]. Some sorts that - * operate directly on a subset of value types are also provided. These - * implementations are derived from those in the Sun JDK. +/** The `Sorting` object provides convenience wrappers for `java.util.Arrays.sort`. + * Methods that defer to `java.util.Arrays.sort` say that they do or under what + * conditions that they do. * - * Note that stability doesn't matter for value types, so use the `quickSort` - * variants for those. `stableSort` is intended to be used with - * objects when the prior ordering should be preserved, where possible. + * `Sorting` also implements a general-purpose quicksort and stable (merge) sort + * for those cases where `java.util.Arrays.sort` could only be used at the cost + * of a large memory penalty. If performance rather than memory usage is the + * primary concern, one may wish to find alternate strategies to use + * `java.util.Arrays.sort` directly e.g. by boxing primitives to use + * a custom ordering on them. + * + * `Sorting` provides methods where you can provide a comparison function, or + * can request a sort of items that are [[scala.math.Ordered]] or that + * otherwise have an implicit or explicit [[scala.math.Ordering]]. + * + * Note also that high-performance non-default sorts for numeric types + * are not provided. If this is required, it is advisable to investigate + * other libraries that cover this use case. * * @author Ross Judson - * @version 1.0 + * @author Adriaan Moors + * @author Rex Kerr + * @version 1.1 */ object Sorting { - /** Quickly sort an array of Doubles. */ - def quickSort(a: Array[Double]) { sort1(a, 0, a.length) } - - /** Quickly sort an array of items with an implicit Ordering. */ - def quickSort[K: Ordering](a: Array[K]) { sort1(a, 0, a.length) } - - /** Quickly sort an array of Ints. */ - def quickSort(a: Array[Int]) { sort1(a, 0, a.length) } - - /** Quickly sort an array of Floats. */ - def quickSort(a: Array[Float]) { sort1(a, 0, a.length) } - - /** Sort an array of K where K is Ordered, preserving the existing order - * where the values are equal. */ - def stableSort[K: ClassTag: Ordering](a: Array[K]) { - stableSort(a, 0, a.length-1, new Array[K](a.length), Ordering[K].lt _) - } + /** Sort an array of Doubles using `java.util.Arrays.sort`. */ + def quickSort(a: Array[Double]): Unit = java.util.Arrays.sort(a) - /** Sorts an array of `K` given an ordering function `f`. - * `f` should return `true` iff its first parameter is strictly less than its second parameter. - */ - def stableSort[K: ClassTag](a: Array[K], f: (K, K) => Boolean) { - stableSort(a, 0, a.length-1, new Array[K](a.length), f) - } + /** Sort an array of Ints using `java.util.Arrays.sort`. */ + def quickSort(a: Array[Int]): Unit = java.util.Arrays.sort(a) - /** Sorts an arbitrary sequence into an array, given a comparison function - * that should return `true` iff parameter one is strictly less than parameter two. - * - * @param a the sequence to be sorted. - * @param f the comparison function. - * @return the sorted sequence of items. - */ - def stableSort[K: ClassTag](a: Seq[K], f: (K, K) => Boolean): Array[K] = { - val ret = a.toArray - stableSort(ret, f) - ret - } + /** Sort an array of Floats using `java.util.Arrays.sort`. */ + def quickSort(a: Array[Float]): Unit = java.util.Arrays.sort(a) + + private final val qsortThreshold = 16 - /** Sorts an arbitrary sequence of items that are viewable as ordered. */ - def stableSort[K: ClassTag: Ordering](a: Seq[K]): Array[K] = - stableSort(a, Ordering[K].lt _) - - /** Stably sorts a sequence of items given an extraction function that will - * return an ordered key from an item. - * - * @param a the sequence to be sorted. - * @param f the comparison function. - * @return the sorted sequence of items. - */ - def stableSort[K: ClassTag, M: Ordering](a: Seq[K], f: K => M): Array[K] = - stableSort(a)(implicitly[ClassTag[K]], Ordering[M] on f) - - private def sort1[K: Ordering](x: Array[K], off: Int, len: Int) { - val ord = Ordering[K] - import ord._ - - def swap(a: Int, b: Int) { - val t = x(a) - x(a) = x(b) - x(b) = t - } - def vecswap(_a: Int, _b: Int, n: Int) { - var a = _a - var b = _b - var i = 0 - while (i < n) { - swap(a, b) - i += 1 - a += 1 - b += 1 - } - } - def med3(a: Int, b: Int, c: Int) = { - if (x(a) < x(b)) { - if (x(b) < x(c)) b else if (x(a) < x(c)) c else a - } else { - if (x(b) > x(c)) b else if (x(a) > x(c)) c else a - } - } - def sort2(off: Int, len: Int) { - // Insertion sort on smallest arrays - if (len < 7) { - var i = off - while (i < len + off) { - var j = i - while (j > off && x(j-1) > x(j)) { - swap(j, j-1) - j -= 1 + /** Sort array `a` with quicksort, using the Ordering on its elements. + * This algorithm sorts in place, so no additional memory is used aside from + * what might be required to box individual elements during comparison. + */ + def quickSort[K: Ordering](a: Array[K]): Unit = { + // Must have iN >= i0 or math will fail. Also, i0 >= 0. + def inner(a: Array[K], i0: Int, iN: Int, ord: Ordering[K]): Unit = { + if (iN - i0 < qsortThreshold) insertionSort(a, i0, iN, ord) + else { + var iK = (i0 + iN) >>> 1 // Unsigned div by 2 + // Find index of median of first, central, and last elements + var pL = + if (ord.compare(a(i0), a(iN - 1)) <= 0) + if (ord.compare(a(i0), a(iK)) < 0) + if (ord.compare(a(iN - 1), a(iK)) < 0) iN - 1 else iK + else i0 + else + if (ord.compare(a(i0), a(iK)) < 0) i0 + else + if (ord.compare(a(iN - 1), a(iK)) <= 0) iN - 1 + else iK + val pivot = a(pL) + // pL is the start of the pivot block; move it into the middle if needed + if (pL != iK) { a(pL) = a(iK); a(iK) = pivot; pL = iK } + // Elements equal to the pivot will be in range pL until pR + var pR = pL + 1 + // Items known to be less than pivot are below iA (range i0 until iA) + var iA = i0 + // Items known to be greater than pivot are at or above iB (range iB until iN) + var iB = iN + // Scan through everything in the buffer before the pivot(s) + while (pL - iA > 0) { + val current = a(iA) + ord.compare(current, pivot) match { + case 0 => + // Swap current out with pivot block + a(iA) = a(pL - 1) + a(pL - 1) = current + pL -= 1 + case x if x < 0 => + // Already in place. Just update indicies. + iA += 1 + case _ if iB > pR => + // Wrong side. There's room on the other side, so swap + a(iA) = a(iB - 1) + a(iB - 1) = current + iB -= 1 + case _ => + // Wrong side and there is no room. Swap by rotating pivot block. + a(iA) = a(pL - 1) + a(pL - 1) = a(pR - 1) + a(pR - 1) = current + pL -= 1 + pR -= 1 + iB -= 1 } - i += 1 } - } else { - // Choose a partition element, v - var m = off + (len >> 1) // Small arrays, middle element - if (len > 7) { - var l = off - var n = off + len - 1 - if (len > 40) { // Big arrays, pseudomedian of 9 - val s = len / 8 - l = med3(l, l+s, l+2*s) - m = med3(m-s, m, m+s) - n = med3(n-2*s, n-s, n) + // Get anything remaining in buffer after the pivot(s) + while (iB - pR > 0) { + val current = a(iB - 1) + ord.compare(current, pivot) match { + case 0 => + // Swap current out with pivot block + a(iB - 1) = a(pR) + a(pR) = current + pR += 1 + case x if x > 0 => + // Already in place. Just update indices. + iB -= 1 + case _ => + // Wrong side and we already know there is no room. Swap by rotating pivot block. + a(iB - 1) = a(pR) + a(pR) = a(pL) + a(pL) = current + iA += 1 + pL += 1 + pR += 1 } - m = med3(l, m, n) // Mid-size, med of 3 } - val v = x(m) - - // Establish Invariant: v* (<v)* (>v)* v* - var a = off - var b = a - var c = off + len - 1 - var d = c - var done = false - while (!done) { - while (b <= c && x(b) <= v) { - if (x(b) equiv v) { - swap(a, b) - a += 1 - } - b += 1 - } - while (c >= b && x(c) >= v) { - if (x(c) equiv v) { - swap(c, d) - d -= 1 - } - c -= 1 - } - if (b > c) { - done = true - } else { - swap(b, c) - c -= 1 - b += 1 - } + // Use tail recursion on large half (Sedgewick's method) so we don't blow up the stack if pivots are poorly chosen + if (iA - i0 < iN - iB) { + inner(a, i0, iA, ord) // True recursion + inner(a, iB, iN, ord) // Should be tail recursion + } + else { + inner(a, iB, iN, ord) // True recursion + inner(a, i0, iA, ord) // Should be tail recursion } - - // Swap partition elements back to middle - val n = off + len - var s = math.min(a-off, b-a) - vecswap(off, b-s, s) - s = math.min(d-c, n-d-1) - vecswap(b, n-s, s) - - // Recursively sort non-partition-elements - s = b - a - if (s > 1) - sort2(off, s) - s = d - c - if (s > 1) - sort2(n-s, s) } } - sort2(off, len) + inner(a, 0, a.length, implicitly[Ordering[K]]) } - - private def sort1(x: Array[Int], off: Int, len: Int) { - def swap(a: Int, b: Int) { - val t = x(a) - x(a) = x(b) - x(b) = t + + private final val mergeThreshold = 32 + + // Ordering[T] might be slow especially for boxed primitives, so use binary search variant of insertion sort + // Caller must pass iN >= i0 or math will fail. Also, i0 >= 0. + private def insertionSort[@specialized T](a: Array[T], i0: Int, iN: Int, ord: Ordering[T]): Unit = { + val n = iN - i0 + if (n < 2) return + if (ord.compare(a(i0), a(i0+1)) > 0) { + val temp = a(i0) + a(i0) = a(i0+1) + a(i0+1) = temp } - def vecswap(_a: Int, _b: Int, n: Int) { - var a = _a - var b = _b - var i = 0 - while (i < n) { - swap(a, b) - i += 1 - a += 1 - b += 1 - } - } - def med3(a: Int, b: Int, c: Int) = { - if (x(a) < x(b)) { - if (x(b) < x(c)) b else if (x(a) < x(c)) c else a - } else { - if (x(b) > x(c)) b else if (x(a) > x(c)) c else a - } - } - def sort2(off: Int, len: Int) { - // Insertion sort on smallest arrays - if (len < 7) { - var i = off - while (i < len + off) { - var j = i - while (j>off && x(j-1) > x(j)) { - swap(j, j-1) - j -= 1 - } - i += 1 + var m = 2 + while (m < n) { + // Speed up already-sorted case by checking last element first + val next = a(i0 + m) + if (ord.compare(next, a(i0+m-1)) < 0) { + var iA = i0 + var iB = i0 + m - 1 + while (iB - iA > 1) { + val ix = (iA + iB) >>> 1 // Use bit shift to get unsigned div by 2 + if (ord.compare(next, a(ix)) < 0) iB = ix + else iA = ix } - } else { - // Choose a partition element, v - var m = off + (len >> 1) // Small arrays, middle element - if (len > 7) { - var l = off - var n = off + len - 1 - if (len > 40) { // Big arrays, pseudomedian of 9 - val s = len / 8 - l = med3(l, l+s, l+2*s) - m = med3(m-s, m, m+s) - n = med3(n-2*s, n-s, n) - } - m = med3(l, m, n) // Mid-size, med of 3 - } - val v = x(m) - - // Establish Invariant: v* (<v)* (>v)* v* - var a = off - var b = a - var c = off + len - 1 - var d = c - var done = false - while (!done) { - while (b <= c && x(b) <= v) { - if (x(b) == v) { - swap(a, b) - a += 1 - } - b += 1 - } - while (c >= b && x(c) >= v) { - if (x(c) == v) { - swap(c, d) - d -= 1 - } - c -= 1 - } - if (b > c) { - done = true - } else { - swap(b, c) - c -= 1 - b += 1 - } + val ix = iA + (if (ord.compare(next, a(iA)) < 0) 0 else 1) + var i = i0 + m + while (i > ix) { + a(i) = a(i-1) + i -= 1 } - - // Swap partition elements back to middle - val n = off + len - var s = math.min(a-off, b-a) - vecswap(off, b-s, s) - s = math.min(d-c, n-d-1) - vecswap(b, n-s, s) - - // Recursively sort non-partition-elements - s = b - a - if (s > 1) - sort2(off, s) - s = d - c - if (s > 1) - sort2(n-s, s) + a(ix) = next } + m += 1 } - sort2(off, len) } - - private def sort1(x: Array[Double], off: Int, len: Int) { - def swap(a: Int, b: Int) { - val t = x(a) - x(a) = x(b) - x(b) = t + + // Caller is required to pass iN >= i0, else math will fail. Also, i0 >= 0. + private def mergeSort[@specialized T: ClassTag](a: Array[T], i0: Int, iN: Int, ord: Ordering[T], scratch: Array[T] = null): Unit = { + if (iN - i0 < mergeThreshold) insertionSort(a, i0, iN, ord) + else { + val iK = (i0 + iN) >>> 1 // Bit shift equivalent to unsigned math, no overflow + val sc = if (scratch eq null) new Array[T](iK - i0) else scratch + mergeSort(a, i0, iK, ord, sc) + mergeSort(a, iK, iN, ord, sc) + mergeSorted(a, i0, iK, iN, ord, sc) } - def vecswap(_a: Int, _b: Int, n: Int) { - var a = _a - var b = _b - var i = 0 - while (i < n) { - swap(a, b) + } + + // Must have 0 <= i0 < iK < iN + private def mergeSorted[@specialized T](a: Array[T], i0: Int, iK: Int, iN: Int, ord: Ordering[T], scratch: Array[T]): Unit = { + // Check to make sure we're not already in order + if (ord.compare(a(iK-1), a(iK)) > 0) { + var i = i0 + val jN = iK - i0 + var j = 0 + while (i < iK) { + scratch (j) = a(i) i += 1 - a += 1 - b += 1 - } - } - def med3(a: Int, b: Int, c: Int) = { - val ab = x(a) compare x(b) - val bc = x(b) compare x(c) - val ac = x(a) compare x(c) - if (ab < 0) { - if (bc < 0) b else if (ac < 0) c else a - } else { - if (bc > 0) b else if (ac > 0) c else a + j += 1 } - } - def sort2(off: Int, len: Int) { - // Insertion sort on smallest arrays - if (len < 7) { - var i = off - while (i < len + off) { - var j = i - while (j > off && (x(j-1) compare x(j)) > 0) { - swap(j, j-1) - j -= 1 - } - i += 1 - } - } else { - // Choose a partition element, v - var m = off + (len >> 1) // Small arrays, middle element - if (len > 7) { - var l = off - var n = off + len - 1 - if (len > 40) { // Big arrays, pseudomedian of 9 - val s = len / 8 - l = med3(l, l+s, l+2*s) - m = med3(m-s, m, m+s) - n = med3(n-2*s, n-s, n) - } - m = med3(l, m, n) // Mid-size, med of 3 - } - val v = x(m) - - // Establish Invariant: v* (<v)* (>v)* v* - var a = off - var b = a - var c = off + len - 1 - var d = c - var done = false - while (!done) { - var bv = x(b) compare v - while (b <= c && bv <= 0) { - if (bv == 0) { - swap(a, b) - a += 1 - } - b += 1 - if (b <= c) bv = x(b) compare v - } - var cv = x(c) compare v - while (c >= b && cv >= 0) { - if (cv == 0) { - swap(c, d) - d -= 1 - } - c -= 1 - if (c >= b) cv = x(c) compare v - } - if (b > c) { - done = true - } else { - swap(b, c) - c -= 1 - b += 1 - } - } - - // Swap partition elements back to middle - val n = off + len - var s = math.min(a-off, b-a) - vecswap(off, b-s, s) - s = math.min(d-c, n-d-1) - vecswap(b, n-s, s) - - // Recursively sort non-partition-elements - s = b - a - if (s > 1) - sort2(off, s) - s = d - c - if (s > 1) - sort2(n-s, s) + var k = i0 + j = 0 + while (i < iN && j < jN) { + if (ord.compare(a(i), scratch(j)) < 0) { a(k) = a(i); i += 1 } + else { a(k) = scratch(j); j += 1 } + k += 1 } + while (j < jN) { a(k) = scratch(j); j += 1; k += 1 } + // Don't need to finish a(i) because it's already in place, k = i } - sort2(off, len) } - - private def sort1(x: Array[Float], off: Int, len: Int) { - def swap(a: Int, b: Int) { - val t = x(a) - x(a) = x(b) - x(b) = t + + // Why would you even do this? + private def booleanSort(a: Array[Boolean]): Unit = { + var i = 0 + var n = 0 + while (i < a.length) { + if (!a(i)) n += 1 + i += 1 } - def vecswap(_a: Int, _b: Int, n: Int) { - var a = _a - var b = _b - var i = 0 - while (i < n) { - swap(a, b) - i += 1 - a += 1 - b += 1 - } + i = 0 + while (i < n) { + a(i) = false + i += 1 } - def med3(a: Int, b: Int, c: Int) = { - val ab = x(a) compare x(b) - val bc = x(b) compare x(c) - val ac = x(a) compare x(c) - if (ab < 0) { - if (bc < 0) b else if (ac < 0) c else a - } else { - if (bc > 0) b else if (ac > 0) c else a - } + while (i < a.length) { + a(i) = true + i += 1 } - def sort2(off: Int, len: Int) { - // Insertion sort on smallest arrays - if (len < 7) { - var i = off - while (i < len + off) { - var j = i - while (j > off && (x(j-1) compare x(j)) > 0) { - swap(j, j-1) - j -= 1 - } - i += 1 - } - } else { - // Choose a partition element, v - var m = off + (len >> 1) // Small arrays, middle element - if (len > 7) { - var l = off - var n = off + len - 1 - if (len > 40) { // Big arrays, pseudomedian of 9 - val s = len / 8 - l = med3(l, l+s, l+2*s) - m = med3(m-s, m, m+s) - n = med3(n-2*s, n-s, n) - } - m = med3(l, m, n) // Mid-size, med of 3 - } - val v = x(m) + } - // Establish Invariant: v* (<v)* (>v)* v* - var a = off - var b = a - var c = off + len - 1 - var d = c - var done = false - while (!done) { - var bv = x(b) compare v - while (b <= c && bv <= 0) { - if (bv == 0) { - swap(a, b) - a += 1 - } - b += 1 - if (b <= c) bv = x(b) compare v - } - var cv = x(c) compare v - while (c >= b && cv >= 0) { - if (cv == 0) { - swap(c, d) - d -= 1 - } - c -= 1 - if (c >= b) cv = x(c) compare v - } - if (b > c) { - done = true - } else { - swap(b, c) - c -= 1 - b += 1 - } - } + // TODO: add upper bound: T <: AnyRef, propagate to callers below (not binary compatible) + // Maybe also rename all these methods to `sort`. + @inline private def sort[T](a: Array[T], ord: Ordering[T]): Unit = a match { + case _: Array[AnyRef] => + // Note that runtime matches are covariant, so could actually be any Array[T] s.t. T is not primitive (even boxed value classes) + if (a.length > 1 && (ord eq null)) throw new NullPointerException("Ordering") + java.util.Arrays.sort(a, ord) + case a: Array[Int] => if (ord eq Ordering.Int) java.util.Arrays.sort(a) else mergeSort[Int](a, 0, a.length, ord) + case a: Array[Double] => mergeSort[Double](a, 0, a.length, ord) // Because not all NaNs are identical, stability is meaningful! + case a: Array[Long] => if (ord eq Ordering.Long) java.util.Arrays.sort(a) else mergeSort[Long](a, 0, a.length, ord) + case a: Array[Float] => mergeSort[Float](a, 0, a.length, ord) // Because not all NaNs are identical, stability is meaningful! + case a: Array[Char] => if (ord eq Ordering.Char) java.util.Arrays.sort(a) else mergeSort[Char](a, 0, a.length, ord) + case a: Array[Byte] => if (ord eq Ordering.Byte) java.util.Arrays.sort(a) else mergeSort[Byte](a, 0, a.length, ord) + case a: Array[Short] => if (ord eq Ordering.Short) java.util.Arrays.sort(a) else mergeSort[Short](a, 0, a.length, ord) + case a: Array[Boolean] => if (ord eq Ordering.Boolean) booleanSort(a) else mergeSort[Boolean](a, 0, a.length, ord) + // Array[Unit] is matched as an Array[AnyRef] due to covariance in runtime matching. Not worth catching it as a special case. + case null => throw new NullPointerException + } - // Swap partition elements back to middle - val n = off + len - var s = math.min(a-off, b-a) - vecswap(off, b-s, s) - s = math.min(d-c, n-d-1) - vecswap(b, n-s, s) + // TODO: remove unnecessary ClassTag (not binary compatible) + /** Sort array `a` using the Ordering on its elements, preserving the original ordering where possible. Uses `java.util.Arrays.sort` unless `K` is a primitive type. */ + def stableSort[K: ClassTag: Ordering](a: Array[K]): Unit = sort(a, Ordering[K]) - // Recursively sort non-partition-elements - s = b - a - if (s > 1) - sort2(off, s) - s = d - c - if (s > 1) - sort2(n-s, s) - } - } - sort2(off, len) + // TODO: Remove unnecessary ClassTag (not binary compatible) + // TODO: make this fast for primitive K (could be specialized if it didn't go through Ordering) + /** Sort array `a` using function `f` that computes the less-than relation for each element. Uses `java.util.Arrays.sort` unless `K` is a primitive type. */ + def stableSort[K: ClassTag](a: Array[K], f: (K, K) => Boolean): Unit = sort(a, Ordering fromLessThan f) + + /** A sorted Array, using the Ordering for the elements in the sequence `a`. Uses `java.util.Arrays.sort` unless `K` is a primitive type. */ + def stableSort[K: ClassTag: Ordering](a: Seq[K]): Array[K] = { + val ret = a.toArray + sort(ret, Ordering[K]) + ret } - private def stableSort[K : ClassTag](a: Array[K], lo: Int, hi: Int, scratch: Array[K], f: (K,K) => Boolean) { - if (lo < hi) { - val mid = (lo+hi) / 2 - stableSort(a, lo, mid, scratch, f) - stableSort(a, mid+1, hi, scratch, f) - var k, t_lo = lo - var t_hi = mid + 1 - while (k <= hi) { - if ((t_lo <= mid) && ((t_hi > hi) || (!f(a(t_hi), a(t_lo))))) { - scratch(k) = a(t_lo) - t_lo += 1 - } else { - scratch(k) = a(t_hi) - t_hi += 1 - } - k += 1 - } - k = lo - while (k <= hi) { - a(k) = scratch(k) - k += 1 - } - } + // TODO: make this fast for primitive K (could be specialized if it didn't go through Ordering) + /** A sorted Array, given a function `f` that computes the less-than relation for each item in the sequence `a`. Uses `java.util.Arrays.sort` unless `K` is a primitive type. */ + def stableSort[K: ClassTag](a: Seq[K], f: (K, K) => Boolean): Array[K] = { + val ret = a.toArray + sort(ret, Ordering fromLessThan f) + ret + } + + /** A sorted Array, given an extraction function `f` that returns an ordered key for each item in the sequence `a`. Uses `java.util.Arrays.sort` unless `K` is a primitive type. */ + def stableSort[K: ClassTag, M: Ordering](a: Seq[K], f: K => M): Array[K] = { + val ret = a.toArray + sort(ret, Ordering[M] on f) + ret } } diff --git a/src/library/scala/util/Try.scala b/src/library/scala/util/Try.scala index b0cf122f2a..0a6a7972c2 100644 --- a/src/library/scala/util/Try.scala +++ b/src/library/scala/util/Try.scala @@ -24,11 +24,12 @@ import scala.language.implicitConversions * * Example: * {{{ + * import scala.io.StdIn * import scala.util.{Try, Success, Failure} * * def divide: Try[Int] = { - * val dividend = Try(Console.readLine("Enter an Int that you'd like to divide:\n").toInt) - * val divisor = Try(Console.readLine("Enter an Int that you'd like to divide by:\n").toInt) + * val dividend = Try(StdIn.readLine("Enter an Int that you'd like to divide:\n").toInt) + * val divisor = Try(StdIn.readLine("Enter an Int that you'd like to divide by:\n").toInt) * val problem = dividend.flatMap(x => divisor.map(y => x/y)) * problem match { * case Success(v) => @@ -164,8 +165,8 @@ sealed abstract class Try[+T] { def flatten[U](implicit ev: T <:< Try[U]): Try[U] /** - * Completes this `Try` with an exception wrapped in a `Success`. The exception is either the exception that the - * `Try` failed with (if a `Failure`) or an `UnsupportedOperationException`. + * Inverts this `Try`. If this is a `Failure`, returns its exception wrapped in a `Success`. + * If this is a `Success`, returns a `Failure` containing an `UnsupportedOperationException`. */ def failed: Try[Throwable] diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala index be6d03a145..aa30887ba0 100644 --- a/src/library/scala/util/control/Exception.scala +++ b/src/library/scala/util/control/Exception.scala @@ -155,7 +155,7 @@ object Exception { /** A `Catch` object which catches everything. */ final def allCatch[T]: Catch[T] = new Catch(allCatcher[T]) withDesc "<everything>" - /** A `Catch` object witch catches non-fatal exceptions. */ + /** A `Catch` object which catches non-fatal exceptions. */ final def nonFatalCatch[T]: Catch[T] = new Catch(nonFatalCatcher[T]) withDesc "<non-fatal>" /** Creates a `Catch` object which will catch any of the supplied exceptions. diff --git a/src/library/scala/util/hashing/MurmurHash3.scala b/src/library/scala/util/hashing/MurmurHash3.scala index 1bfaeb255b..4e5537954f 100644 --- a/src/library/scala/util/hashing/MurmurHash3.scala +++ b/src/library/scala/util/hashing/MurmurHash3.scala @@ -191,7 +191,7 @@ private[hashing] class MurmurHash3 { * This is based on the earlier MurmurHash3 code by Rex Kerr, but the * MurmurHash3 algorithm was since changed by its creator Austin Appleby * to remedy some weaknesses and improve performance. This represents the - * latest and supposedly final version of the algortihm (revision 136). + * latest and supposedly final version of the algorithm (revision 136). * * @see [[http://code.google.com/p/smhasher]] */ diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala index 5c4e706dc1..6d3d015b1a 100644 --- a/src/library/scala/util/matching/Regex.scala +++ b/src/library/scala/util/matching/Regex.scala @@ -477,7 +477,7 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends /** * Replaces some of the matches using a replacer function that returns an [[scala.Option]]. * The replacer function takes a [[scala.util.matching.Regex.Match]] so that extra - * information can be btained from the match. For example: + * information can be obtained from the match. For example: * * {{{ * import scala.util.matching.Regex._ diff --git a/src/manual/scala/man1/scalac.scala b/src/manual/scala/man1/scalac.scala index 3954ed588e..c658fe89f8 100644 --- a/src/manual/scala/man1/scalac.scala +++ b/src/manual/scala/man1/scalac.scala @@ -152,11 +152,12 @@ object scalac extends Command { CmdOption("sourcepath", Argument("path")), "Specify location(s) of source files."), Definition( - CmdOptionBound("target:", "{jvm-1.5,jvm-1.6,jvm-1.7}"), + CmdOptionBound("target:", "{jvm-1.5,jvm-1.6,jvm-1.7,jvm-1.8}"), SeqPara( Mono("\"jvm-1.5\"") & " target JVM 1.5 (deprecated),", Mono("\"jvm-1.6\"") & " target JVM 1.6 (default),", - Mono("\"jvm-1.7\"") & " target JVM 1.7,")), + Mono("\"jvm-1.7\"") & " target JVM 1.7,", + Mono("\"jvm-1.8\"") & " target JVM 1.8,")), Definition( CmdOption("toolcp", Argument("path")), "Add to the runner classpath."), diff --git a/src/partest-extras/scala/tools/partest/ASMConverters.scala b/src/partest-extras/scala/tools/partest/ASMConverters.scala index 67a4e8ae01..f6e2d2a9ec 100644 --- a/src/partest-extras/scala/tools/partest/ASMConverters.scala +++ b/src/partest-extras/scala/tools/partest/ASMConverters.scala @@ -89,7 +89,7 @@ object ASMConverters { private def lst[T](xs: java.util.List[T]): List[T] = if (xs == null) Nil else xs.asScala.toList - // Heterogenous List[Any] is used in FrameNode: type information about locals / stack values + // Heterogeneous List[Any] is used in FrameNode: type information about locals / stack values // are stored in a List[Any] (Integer, String or LabelNode), see Javadoc of MethodNode#visitFrame. // Opcodes (eg Opcodes.INTEGER) and Reference types (eg "java/lang/Object") are returned unchanged, // LabelNodes are mapped to their LabelEntry. diff --git a/src/partest-extras/scala/tools/partest/ParserTest.scala b/src/partest-extras/scala/tools/partest/ParserTest.scala new file mode 100644 index 0000000000..e4c92e3dc3 --- /dev/null +++ b/src/partest-extras/scala/tools/partest/ParserTest.scala @@ -0,0 +1,21 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2014 LAMP/EPFL + */ + +package scala.tools.partest + +/** A class for testing parser output. + * Just supply the `code` and update the check file. + */ +abstract class ParserTest extends DirectTest { + + override def extraSettings: String = "-usejavacp -Ystop-after:parser -Xprint:parser" + + override def show(): Unit = { + // redirect err to out, for logging + val prevErr = System.err + System.setErr(System.out) + compile() + System.setErr(prevErr) + } +} diff --git a/src/reflect/scala/reflect/api/Constants.scala b/src/reflect/scala/reflect/api/Constants.scala index fbcf7f3e4f..4cc2cb86b2 100644 --- a/src/reflect/scala/reflect/api/Constants.scala +++ b/src/reflect/scala/reflect/api/Constants.scala @@ -95,7 +95,7 @@ trait Constants { * broken down or evaluated, such as "true", "0", "classOf[List]". Such values become parts of the Scala abstract * syntax tree representing the program. The constants * correspond to section 6.24 "Constant Expressions" of the - * [[http://www.scala-lang.org/docu/files/ScalaReference.pdf Scala language specification]]. + * [[http://www.scala-lang.org/files/archive/spec/2.11/ Scala Language Specification]]. * * Such constants are used to represent literals in abstract syntax trees (the [[scala.reflect.api.Trees#Literal]] node) * and literal arguments for Java class file annotations (the [[scala.reflect.api.Annotations#LiteralArgument]] class). diff --git a/src/reflect/scala/reflect/api/Quasiquotes.scala b/src/reflect/scala/reflect/api/Quasiquotes.scala index eaae05bed5..554b43afaf 100644 --- a/src/reflect/scala/reflect/api/Quasiquotes.scala +++ b/src/reflect/scala/reflect/api/Quasiquotes.scala @@ -3,7 +3,7 @@ package api trait Quasiquotes { self: Universe => - /** Implicit class that introduces `q`, `tq`, `cq,` `p` and `fq` string interpolators + /** Implicit class that introduces `q`, `tq`, `cq,` `pq` and `fq` string interpolators * that are also known as quasiquotes. With their help you can easily manipulate * Scala reflection ASTs. * diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 756ed870ca..f3dd6a3280 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -369,6 +369,8 @@ trait Definitions extends api.StandardDefinitions { lazy val JavaEnumClass = requiredClass[java.lang.Enum[_]] lazy val RemoteInterfaceClass = requiredClass[java.rmi.Remote] lazy val RemoteExceptionClass = requiredClass[java.rmi.RemoteException] + lazy val JavaUtilMap = requiredClass[java.util.Map[_, _]] + lazy val JavaUtilHashMap = requiredClass[java.util.HashMap[_, _]] lazy val ByNameParamClass = specialPolyClass(tpnme.BYNAME_PARAM_CLASS_NAME, COVARIANT)(_ => AnyTpe) lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.tpe)) @@ -514,6 +516,7 @@ trait Definitions extends api.StandardDefinitions { lazy val ScalaSignatureAnnotation = requiredClass[scala.reflect.ScalaSignature] lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature] + lazy val LambdaMetaFactory = getClassIfDefined("java.lang.invoke.LambdaMetafactory") lazy val MethodHandle = getClassIfDefined("java.lang.invoke.MethodHandle") // Option classes @@ -936,7 +939,7 @@ trait Definitions extends api.StandardDefinitions { // TODO these aren't final! They are now overridden in AnyRef/Object. Prior to the fix // for SI-8129, they were actually *overloaded* by the members in AnyRef/Object. // We should unfinalize these, override in AnyValClass, and make the overrides final. - // Refchecks never actually looks at these, so its just for consistency. + // Refchecks never actually looks at these, so it's just for consistency. lazy val Any_== = enterNewMethod(AnyClass, nme.EQ, AnyTpe :: Nil, BooleanTpe, FINAL) lazy val Any_!= = enterNewMethod(AnyClass, nme.NE, AnyTpe :: Nil, BooleanTpe, FINAL) @@ -1513,6 +1516,9 @@ trait Definitions extends api.StandardDefinitions { def isPolymorphicSignature(sym: Symbol) = PolySigMethods(sym) private lazy val PolySigMethods: Set[Symbol] = Set[Symbol](MethodHandle.info.decl(sn.Invoke), MethodHandle.info.decl(sn.InvokeExact)).filter(_.exists) + + lazy val Scala_Java8_CompatPackage = rootMirror.getPackageIfDefined("scala.compat.java8") + lazy val Scala_Java8_CompatPackage_JFunction = (0 to MaxFunctionArity).toArray map (i => getMemberIfDefined(Scala_Java8_CompatPackage.moduleClass, TypeName("JFunction" + i))) } } } diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala index c418321234..eddfec82e7 100644 --- a/src/reflect/scala/reflect/internal/ReificationSupport.scala +++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala @@ -292,7 +292,7 @@ trait ReificationSupport { self: SymbolTable => if (ctorMods.isTrait) result(ctorMods, Nil, edefs, body) else { - // undo conversion from (implicit ... ) to ()(implicit ... ) when its the only parameter section + // undo conversion from (implicit ... ) to ()(implicit ... ) when it's the only parameter section val vparamssRestoredImplicits = ctorVparamss match { case Nil :: (tail @ ((head :: _) :: _)) if head.mods.isImplicit => tail case other => other diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index c0562b0679..63e2ca0dbe 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -1167,6 +1167,8 @@ trait StdNames { final val Invoke: TermName = newTermName("invoke") final val InvokeExact: TermName = newTermName("invokeExact") + final val AltMetafactory: TermName = newTermName("altMetafactory") + val Boxed = immutable.Map[TypeName, TypeName]( tpnme.Boolean -> BoxedBoolean, tpnme.Byte -> BoxedByte, diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index d85ec22a84..abe966920b 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -794,6 +794,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME) final def isDelambdafyFunction = isSynthetic && (name containsName tpnme.DELAMBDAFY_LAMBDA_CLASS_NAME) + final def isDelambdafyTarget = isArtifact && isMethod && (name containsName tpnme.ANON_FUN_NAME) final def isDefinedInPackage = effectiveOwner.isPackageClass final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass @@ -2060,7 +2061,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ final def outerClass: Symbol = if (this == NoSymbol) { - // ideally we shouldn't get here, but its better to harden against this than suffer the infinite loop in SI-9133 + // ideally we shouldn't get here, but it's better to harden against this than suffer the infinite loop in SI-9133 devWarningDumpStack("NoSymbol.outerClass", 15) NoSymbol } else if (owner.isClass) owner diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index 75a1969d22..b2248ad518 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -365,7 +365,7 @@ abstract class TreeGen { DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, Nil, ListOfNil, TypeTree(), Block(lvdefs, Literal(Constant(())))))) } else { - // convert (implicit ... ) to ()(implicit ... ) if its the only parameter section + // convert (implicit ... ) to ()(implicit ... ) if it's the only parameter section if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit) vparamss1 = List() :: vparamss1 val superCall = pendingSuperCall // we can't know in advance which of the parents will end up as a superclass diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 86a53a1b02..f74d976b82 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3658,7 +3658,7 @@ trait Types // JZ: We used to register this as a perRunCache so it would be cleared eagerly at // the end of the compilation run. But, that facility didn't actually clear this map (SI-8129)! // When i fixed that bug, run/tpeCache-tyconCache.scala started failing. Why was that? - // I've removed the registration for now. I don't think its particularly harmful anymore + // I've removed the registration for now. I don't think it's particularly harmful anymore // as a) this is now a weak set, and b) it is discarded completely before the next run. uniqueRunId = currentRunId } @@ -4535,7 +4535,7 @@ trait Types /** Adds the @uncheckedBound annotation if the given `tp` has type arguments */ final def uncheckedBounds(tp: Type): Type = { - if (tp.typeArgs.isEmpty || UncheckedBoundsClass == NoSymbol) tp // second condition for backwards compatibilty with older scala-reflect.jar + if (tp.typeArgs.isEmpty || UncheckedBoundsClass == NoSymbol) tp // second condition for backwards compatibility with older scala-reflect.jar else tp.withAnnotation(AnnotationInfo marker UncheckedBoundsClass.tpe) } diff --git a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala index 42b13944f6..83a5d23e7c 100644 --- a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala +++ b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala @@ -155,7 +155,7 @@ trait FindMembers { && ( (member.owner eq other.owner) // same owner, therefore overload || (member.flags & PRIVATE) != 0 // (unqualified) private members never participate in overriding || (other.flags & PRIVATE) != 0 // ... as overrider or overridee. - || !(memberTypeLow(member) matches memberTypeHi(other)) // do the member types match? If so, its an override. Otherwise it's an overload. + || !(memberTypeLow(member) matches memberTypeHi(other)) // do the member types match? If so, it's an override. Otherwise it's an overload. ) ) diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index d5b5967145..707972242a 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -254,6 +254,8 @@ trait Erasure { def mergeParents(parents: List[Type]): Type = if (parents.isEmpty) ObjectTpe else parents.head + + override protected def eraseDerivedValueClassRef(tref: TypeRef): Type = eraseNormalClassRef(tref) } object scalaErasure extends ScalaErasureMap diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 6efac6d873..ce60ade9f5 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -591,6 +591,7 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive // don't use classOf[scala.reflect.ScalaSignature] here, because it will use getClass.getClassLoader, not mirror's classLoader // don't use asInstanceOf either because of the same reason (lol, I cannot believe I fell for it) // don't use structural types to simplify reflective invocations because of the same reason + // TODO SI-9296 duplicated code, refactor def loadAnnotation(name: String): Option[java.lang.annotation.Annotation] = tryJavaClass(name) flatMap { annotClass => val anns = jclazz.getAnnotations @@ -1285,16 +1286,12 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive jclazz getDeclaredConstructor (effectiveParamClasses: _*) } - private def jArrayClass(elemClazz: jClass[_]): jClass[_] = { - jArray.newInstance(elemClazz, 0).getClass - } - /** The Java class that corresponds to given Scala type. * Pre: Scala type is already transformed to Java level. */ def typeToJavaClass(tpe: Type): jClass[_] = tpe match { case ExistentialType(_, rtpe) => typeToJavaClass(rtpe) - case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe)) + case TypeRef(_, ArrayClass, List(elemtpe)) => ScalaRunTime.arrayClass(typeToJavaClass(elemtpe)) case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClass) case tpe @ TypeRef(_, sym: AliasTypeSymbol, _) => typeToJavaClass(tpe.dealias) case SingleType(_, sym: ModuleSymbol) => classToJava(sym.moduleClass.asClass) diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 1c0aa7cf6d..ea213cadd9 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -255,6 +255,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.JavaEnumClass definitions.RemoteInterfaceClass definitions.RemoteExceptionClass + definitions.JavaUtilMap + definitions.JavaUtilHashMap definitions.ByNameParamClass definitions.JavaRepeatedParamClass definitions.RepeatedParamClass @@ -310,6 +312,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.QuasiquoteClass_api_unapply definitions.ScalaSignatureAnnotation definitions.ScalaLongSignatureAnnotation + definitions.LambdaMetaFactory definitions.MethodHandle definitions.OptionClass definitions.OptionModule diff --git a/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala b/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala index d8efcda8b5..a8d537e314 100644 --- a/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala +++ b/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala @@ -112,8 +112,12 @@ trait VariColumnTabulator extends Tabulator { def layout(ncols: Int): Option[(Int, Seq[Int], Seq[Seq[String]])] = { val nrows = items.size /% ncols val xwise = isAcross || ncols >= items.length - def maxima(sss: Seq[Seq[String]]) = - (0 until (ncols min items.size)) map (i => (sss map (ss => ss(i).length)).max) + // max width item in each column + def maxima(rows: Seq[Seq[String]]) = + (0 until (ncols min items.size)) map { col => + val widths = for (r <- rows if r.size > col) yield r(col).length + widths.max + } def resulting(rows: Seq[Seq[String]]) = { val columnWidths = maxima(rows) map (_ + marginSize) val linelen = columnWidths.sum @@ -124,9 +128,10 @@ trait VariColumnTabulator extends Tabulator { else if (xwise) resulting((items grouped ncols).toSeq) else { val cols = (items grouped nrows).toList - val rows = for (i <- 0 until nrows) yield - for (j <- 0 until ncols) yield - if (j < cols.size && i < cols(j).size) cols(j)(i) else "" + val rows = + for (i <- 0 until nrows) yield + for (j <- 0 until ncols) yield + if (j < cols.size && i < cols(j).size) cols(j)(i) else "" resulting(rows) } } diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index c281126d5f..e355d9f864 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -69,6 +69,8 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set // Used in a test case. def showDirectory() = replOutput.show(out) + lazy val isClassBased: Boolean = settings.Yreplclassbased.value + private[nsc] var printResults = true // whether to print result lines private[nsc] var totalSilence = false // whether to print anything private var _initializeComplete = false // compiler is initialized @@ -310,8 +312,14 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set } def originalPath(name: String): String = originalPath(TermName(name)) - def originalPath(name: Name): String = typerOp path name - def originalPath(sym: Symbol): String = typerOp path sym + def originalPath(name: Name): String = translateOriginalPath(typerOp path name) + def originalPath(sym: Symbol): String = translateOriginalPath(typerOp path sym) + /** For class based repl mode we use an .INSTANCE accessor. */ + val readInstanceName = if(isClassBased) ".INSTANCE" else "" + def translateOriginalPath(p: String): String = { + val readName = java.util.regex.Matcher.quoteReplacement(sessionNames.read) + p.replaceFirst(readName, readName + readInstanceName) + } def flatPath(sym: Symbol): String = flatOp shift sym.javaClassName def translatePath(path: String) = { @@ -758,11 +766,13 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set // object and we can do that much less wrapping. def packageDecl = "package " + packageName + def pathToInstance(name: String) = packageName + "." + name + readInstanceName def pathTo(name: String) = packageName + "." + name def packaged(code: String) = packageDecl + "\n\n" + code - def readPath = pathTo(readName) - def evalPath = pathTo(evalName) + def readPathInstance = pathToInstance(readName) + def readPath = pathTo(readName) + def evalPath = pathTo(evalName) def call(name: String, args: Any*): AnyRef = { val m = evalMethod(name) @@ -802,7 +812,8 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set /** The innermost object inside the wrapper, found by * following accessPath into the outer one. */ - def resolvePathToSymbol(accessPath: String): Symbol = { + def resolvePathToSymbol(fullAccessPath: String): Symbol = { + val accessPath = fullAccessPath.stripPrefix(readPath) val readRoot = readRootPath(readPath) // the outermost wrapper (accessPath split '.').foldLeft(readRoot: Symbol) { case (sym, "") => sym @@ -849,7 +860,6 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set def defines = defHandlers flatMap (_.definedSymbols) def imports = importedSymbols def value = Some(handlers.last) filter (h => h.definesValue) map (h => definedSymbols(h.definesTerm.get)) getOrElse NoSymbol - val lineRep = new ReadEvalPrint() private var _originalLine: String = null @@ -858,6 +868,11 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set /** handlers for each tree in this request */ val handlers: List[MemberHandler] = trees map (memberHandlers chooseHandler _) + val definesClass = handlers.exists { + case _: ClassHandler => true + case _ => false + } + def defHandlers = handlers collect { case x: MemberDefHandler => x } /** list of names used by this expression */ @@ -875,13 +890,13 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set * append to objectName to access anything bound by request. */ lazy val ComputedImports(importsPreamble, importsTrailer, accessPath) = - exitingTyper(importsCode(referencedNames.toSet, ObjectSourceCode)) + exitingTyper(importsCode(referencedNames.toSet, ObjectSourceCode, definesClass)) /** the line of code to compute */ def toCompute = line /** The path of the value that contains the user code. */ - def fullAccessPath = s"${lineRep.readPath}$accessPath" + def fullAccessPath = s"${lineRep.readPathInstance}$accessPath" /** The path of the given member of the wrapping instance. */ def fullPath(vname: String) = s"$fullAccessPath.`$vname`" @@ -911,7 +926,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set def postwrap: String } - private class ObjectBasedWrapper extends Wrapper { + class ObjectBasedWrapper extends Wrapper { def preambleHeader = "object %s {" def postamble = importsTrailer + "\n}" @@ -919,13 +934,16 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set def postwrap = "}\n" } - private class ClassBasedWrapper extends Wrapper { - def preambleHeader = "class %s extends Serializable {" + class ClassBasedWrapper extends Wrapper { + def preambleHeader = "class %s extends Serializable { " /** Adds an object that instantiates the outer wrapping class. */ - def postamble = s"""$importsTrailer + def postamble = s""" + |$importsTrailer + |} + |object ${lineRep.readName} { + | val INSTANCE = new ${lineRep.readName}(); |} - |object ${lineRep.readName} extends ${lineRep.readName} |""".stripMargin import nme.{ INTERPRETER_IMPORT_WRAPPER => iw } @@ -935,7 +953,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set } private lazy val ObjectSourceCode: Wrapper = - if (settings.Yreplclassbased) new ClassBasedWrapper else new ObjectBasedWrapper + if (isClassBased) new ClassBasedWrapper else new ObjectBasedWrapper private object ResultObjectSourceCode extends IMain.CodeAssembler[MemberHandler] { /** We only want to generate this code when the result @@ -994,7 +1012,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set } } - lazy val resultSymbol = lineRep.resolvePathToSymbol(accessPath) + lazy val resultSymbol = lineRep.resolvePathToSymbol(fullAccessPath) def applyToResultMember[T](name: Name, f: Symbol => T) = exitingTyper(f(resultSymbol.info.nonPrivateDecl(name))) /* typeOf lookup with encoding */ diff --git a/src/repl/scala/tools/nsc/interpreter/Imports.scala b/src/repl/scala/tools/nsc/interpreter/Imports.scala index 5244858a62..3ec77e46f1 100644 --- a/src/repl/scala/tools/nsc/interpreter/Imports.scala +++ b/src/repl/scala/tools/nsc/interpreter/Imports.scala @@ -92,7 +92,7 @@ trait Imports { * last one imported is actually usable. */ case class ComputedImports(prepend: String, append: String, access: String) - protected def importsCode(wanted: Set[Name], wrapper: Request#Wrapper): ComputedImports = { + protected def importsCode(wanted: Set[Name], wrapper: Request#Wrapper, definesClass: Boolean): ComputedImports = { /** Narrow down the list of requests from which imports * should be taken. Removes requests which cannot contribute * useful imports for the specified set of wanted names. @@ -107,6 +107,8 @@ trait Imports { // Single symbol imports might be implicits! See bug #1752. Rather than // try to finesse this, we will mimic all imports for now. def keepHandler(handler: MemberHandler) = handler match { + /* While defining classes in class based mode - implicits are not needed. */ + case h: ImportHandler if isClassBased && definesClass => h.importedNames.exists(x => wanted.contains(x)) case _: ImportHandler => true case x => x.definesImplicit || (x.definedNames exists wanted) } @@ -146,7 +148,10 @@ trait Imports { // loop through previous requests, adding imports for each one wrapBeforeAndAfter { + // Reusing a single temporary value when import from a line with multiple definitions. + val tempValLines = mutable.Set[Int]() for (ReqAndHandler(req, handler) <- reqsToUse) { + val objName = req.lineRep.readPathInstance handler match { // If the user entered an import, then just use it; add an import wrapping // level if the import might conflict with some other import @@ -157,6 +162,23 @@ trait Imports { code append (x.member + "\n") currentImps ++= x.importedNames + case x if isClassBased => + for (imv <- x.definedNames) { + if (!currentImps.contains(imv)) { + x match { + case _: ClassHandler => + code.append("import " + objName + req.accessPath + ".`" + imv + "`\n") + case _ => + val valName = req.lineRep.packageName + req.lineRep.readName + if (!tempValLines.contains(req.lineRep.lineId)) { + code.append(s"val $valName = $objName\n") + tempValLines += req.lineRep.lineId + } + code.append(s"import $valName${req.accessPath}.`$imv`;\n") + } + currentImps += imv + } + } // For other requests, import each defined name. // import them explicitly instead of with _, so that // ambiguity errors will not be generated. Also, quote diff --git a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala index c80b94bf89..1ccade2172 100644 --- a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala +++ b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala @@ -8,6 +8,7 @@ package tools.nsc package interpreter import java.lang.{ ClassLoader => JavaClassLoader, Iterable => JIterable } +import scala.tools.asm.Opcodes import scala.tools.nsc.util.ScalaClassLoader import java.io.{ ByteArrayInputStream, CharArrayWriter, FileNotFoundException, PrintWriter, StringWriter, Writer } import java.util.{ Locale } @@ -758,32 +759,19 @@ object JavapClass { import scala.tools.asm.ClassReader import scala.tools.asm.Opcodes.INVOKESTATIC import scala.tools.asm.tree.{ ClassNode, MethodInsnNode } - // the accessor methods invoked statically by the apply of the given closure class - def accesses(s: String): Seq[(String, String)] = { - val accessor = """accessor\$\d+""".r + def callees(s: String): List[(String, String)] = { loader classReader s withMethods { ms => - ms filter (_.name == "apply") flatMap (_.instructions.toArray.collect { - case i: MethodInsnNode if i.getOpcode == INVOKESTATIC && when(i.name) { case accessor(_*) => true } => (i.owner, i.name) - }) + val nonBridgeApplyMethods = ms filter (_.name == "apply") filter (n => (n.access & Opcodes.ACC_BRIDGE) == 0) + val instructions = nonBridgeApplyMethods flatMap (_.instructions.toArray) + instructions.collect { + case i: MethodInsnNode => (i.owner, i.name) + }.toList } } - // get the k.$anonfun for the accessor k.m - def anonOf(k: String, m: String): String = { - val res = - loader classReader k withMethods { ms => - ms filter (_.name == m) flatMap (_.instructions.toArray.collect { - case i: MethodInsnNode if i.getOpcode == INVOKESTATIC && i.name.startsWith("$anonfun") => i.name - }) - } - assert(res.size == 1) - res.head - } - // the lambdas invoke accessors that call the anonfuns of interest. Filter k on the k#$anonfuns. - val ack = accesses(lambda) - assert(ack.size == 1) // There can be only one. - ack.head match { - case (k, _) if target.isModule && !(k endsWith "$") => None - case (k, m) => Some(s"${k}#${anonOf(k, m)}") + callees(lambda) match { + case (k, _) :: Nil if target.isModule && !(k endsWith "$") => None + case (k, m) :: _ => Some(s"${k}#${m}") + case _ => None } } /** Translate the supplied targets to patterns for anonfuns. diff --git a/src/scaladoc/scala/tools/nsc/doc/Index.scala b/src/scaladoc/scala/tools/nsc/doc/Index.scala index 84545e9201..a11ca38a86 100644 --- a/src/scaladoc/scala/tools/nsc/doc/Index.scala +++ b/src/scaladoc/scala/tools/nsc/doc/Index.scala @@ -11,4 +11,6 @@ trait Index { type SymbolMap = SortedMap[String, SortedSet[model.MemberEntity]] def firstLetterIndex: Map[Char, SymbolMap] + + def hasDeprecatedMembers: Boolean } diff --git a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala index d31b877262..fb4ed34571 100755 --- a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala +++ b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala @@ -281,13 +281,16 @@ trait CommentFactoryBase { this: MemberLookupBase => parse0(docBody, tags + (key -> value), Some(key), ls, inCodeBlock) case line :: ls if (lastTagKey.isDefined) => - val key = lastTagKey.get - val value = - ((tags get key): @unchecked) match { - case Some(b :: bs) => (b + endOfLine + line) :: bs - case None => oops("lastTagKey set when no tag exists for key") - } - parse0(docBody, tags + (key -> value), lastTagKey, ls, inCodeBlock) + val newtags = if (!line.isEmpty) { + val key = lastTagKey.get + val value = + ((tags get key): @unchecked) match { + case Some(b :: bs) => (b + endOfLine + line) :: bs + case None => oops("lastTagKey set when no tag exists for key") + } + tags + (key -> value) + } else tags + parse0(docBody, newtags, lastTagKey, ls, inCodeBlock) case line :: ls => if (docBody.length > 0) docBody append endOfLine @@ -315,18 +318,18 @@ trait CommentFactoryBase { this: MemberLookupBase => val bodyTags: mutable.Map[TagKey, List[Body]] = mutable.Map(tagsWithoutDiagram mapValues {tag => tag map (parseWikiAtSymbol(_, pos, site))} toSeq: _*) - def oneTag(key: SimpleTagKey): Option[Body] = + def oneTag(key: SimpleTagKey, filterEmpty: Boolean = true): Option[Body] = ((bodyTags remove key): @unchecked) match { - case Some(r :: rs) => + case Some(r :: rs) if !(filterEmpty && r.blocks.isEmpty) => if (!rs.isEmpty) reporter.warning(pos, "Only one '@" + key.name + "' tag is allowed") Some(r) - case None => None + case _ => None } def allTags(key: SimpleTagKey): List[Body] = - (bodyTags remove key) getOrElse Nil + (bodyTags remove key).getOrElse(Nil).filterNot(_.blocks.isEmpty) - def allSymsOneTag(key: TagKey): Map[String, Body] = { + def allSymsOneTag(key: TagKey, filterEmpty: Boolean = true): Map[String, Body] = { val keys: Seq[SymbolTagKey] = bodyTags.keys.toSeq flatMap { case stk: SymbolTagKey if (stk.name == key.name) => Some(stk) @@ -342,11 +345,11 @@ trait CommentFactoryBase { this: MemberLookupBase => reporter.warning(pos, "Only one '@" + key.name + "' tag for symbol " + key.symbol + " is allowed") (key.symbol, bs.head) } - Map.empty[String, Body] ++ pairs + Map.empty[String, Body] ++ (if (filterEmpty) pairs.filterNot(_._2.blocks.isEmpty) else pairs) } def linkedExceptions: Map[String, Body] = { - val m = allSymsOneTag(SimpleTagKey("throws")) + val m = allSymsOneTag(SimpleTagKey("throws"), filterEmpty = false) m.map { case (name,body) => val link = memberLookup(pos, name, site) @@ -372,7 +375,7 @@ trait CommentFactoryBase { this: MemberLookupBase => version0 = oneTag(SimpleTagKey("version")), since0 = oneTag(SimpleTagKey("since")), todo0 = allTags(SimpleTagKey("todo")), - deprecated0 = oneTag(SimpleTagKey("deprecated")), + deprecated0 = oneTag(SimpleTagKey("deprecated"), filterEmpty = false), note0 = allTags(SimpleTagKey("note")), example0 = allTags(SimpleTagKey("example")), constructor0 = oneTag(SimpleTagKey("constructor")), diff --git a/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala index 61ab18d42d..8313d842e5 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala @@ -123,6 +123,8 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) { new page.Index(universe, index) writeFor this new page.IndexScript(universe, index) writeFor this + if (index.hasDeprecatedMembers) + new page.DeprecatedIndex(universe, index) writeFor this try { writeTemplates(_ writeFor this) for (letter <- index.firstLetterIndex) { diff --git a/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala b/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala index ce75749859..6cdd99c9ee 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala @@ -59,6 +59,7 @@ abstract class HtmlPage extends Page { thisPage => writeFile(site) { (w: Writer) => w.write(doctype.toString + "\n") w.write(xml.Xhtml.toXhtml(html)) + w.write('\n') } if (site.universe.settings.docRawOutput) @@ -206,25 +207,42 @@ abstract class HtmlPage extends Page { thisPage => case tpl :: tpls => templateToHtml(tpl) ++ sep ++ templatesToHtml(tpls, sep) } - /** Returns the _big image name corresponding to the DocTemplate Entity (upper left icon) */ - def docEntityKindToBigImage(ety: DocTemplateEntity) = - if (ety.isTrait && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None) "trait_to_object_big.png" - else if (ety.isTrait) "trait_big.png" - else if (ety.isClass && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None) "class_to_object_big.png" - else if (ety.isClass) "class_big.png" - else if ((ety.isAbstractType || ety.isAliasType) && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None) "type_to_object_big.png" - else if ((ety.isAbstractType || ety.isAliasType)) "type_big.png" - else if (ety.isObject && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None && ety.companion.get.isClass) "object_to_class_big.png" - else if (ety.isObject && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None && ety.companion.get.isTrait) "object_to_trait_big.png" - else if (ety.isObject && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None && (ety.companion.get.isAbstractType || ety.companion.get.isAliasType)) "object_to_trait_big.png" - else if (ety.isObject) "object_big.png" - else if (ety.isPackage) "package_big.png" - else "class_big.png" // FIXME: an entity *should* fall into one of the above categories, but AnyRef is somehow not + object Image extends Enumeration { + val Trait, Class, Type, Object, Package = Value + } + + /** Returns the _big image name and the alt attribute + * corresponding to the DocTemplate Entity (upper left icon) */ + def docEntityKindToBigImage(ety: DocTemplateEntity) = { + def entityToImage(e: DocTemplateEntity) = + if (e.isTrait) Image.Trait + else if (e.isClass) Image.Class + else if (e.isAbstractType || e.isAliasType) Image.Type + else if (e.isObject) Image.Object + else if (e.isPackage) Image.Package + else { + // FIXME: an entity *should* fall into one of the above categories, + // but AnyRef is somehow not + Image.Class + } + + val image = entityToImage(ety) + val companionImage = ety.companion filter { + e => e.visibility.isPublic && ! e.inSource.isEmpty + } map { entityToImage } + + (image, companionImage) match { + case (from, Some(to)) => + ((from + "_to_" + to + "_big.png").toLowerCase, from + "/" + to) + case (from, None) => + ((from + "_big.png").toLowerCase, from.toString) + } + } def permalink(template: Entity, isSelf: Boolean = true): Elem = <span class="permalink"> <a href={ memberToUrl(template, isSelf) } title="Permalink" target="_top"> - <img src={ relativeLinkTo(List("permalink.png", "lib")) } /> + <img src={ relativeLinkTo(List("permalink.png", "lib")) } alt="Permalink" /> </a> </span> diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala new file mode 100755 index 0000000000..f257153bd7 --- /dev/null +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala @@ -0,0 +1,58 @@ +/* NSC -- new Scala compiler + * Copyright 2007-2013 LAMP/EPFL + */ + +package scala +package tools +package nsc +package doc +package html +package page + +import doc.model._ + +class DeprecatedIndex(universe: Universe, index: doc.Index) extends HtmlPage { + + def path = List("deprecated-list.html") + + def title = { + val s = universe.settings + ( if (!s.doctitle.isDefault) s.doctitle.value else "" ) + + ( if (!s.docversion.isDefault) (" " + s.docversion.value) else "" ) + } + + def headers = + <xml:group> + <link href={ relativeLinkTo(List("ref-index.css", "lib")) } media="screen" type="text/css" rel="stylesheet"/> + <script type="text/javascript" src={ relativeLinkTo{List("jquery.js", "lib")} }></script> + </xml:group> + + + private def entry(name: String, methods: Iterable[MemberEntity]) = { + val occurrences = methods.filter(_.deprecation.isDefined).map(method => + templateToHtml(method.inDefinitionTemplates.head) + ).toList.distinct + + <div class="entry"> + <div class="name">{ name }</div> + <div class="occurrences">{ + for (owner <- occurrences) yield owner ++ scala.xml.Text(" ") + }</div> + </div> + } + + def deprecatedEntries = { + val available = ('_' +: ('a' to 'z')).flatMap(index.firstLetterIndex.get) + + for (group <- available; + value <- group if value._2.find(_.deprecation.isDefined).isDefined) + yield value + } + + def body = + <body>{ + for(value <- deprecatedEntries) yield + entry(value._1, value._2.view) + }</body> + +} diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala index ce3a5eb1fc..6bfe480e33 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala @@ -61,12 +61,17 @@ class Index(universe: doc.Universe, val index: doc.Index) extends HtmlPage { } } + def deprecated: NodeSeq = if (index.hasDeprecatedMembers) + <a target="template" href="deprecated-list.html">deprecated</a> + else + <span>deprecated</span> + def browser = <div id="browser" class="ui-layout-west"> <div class="ui-west-center"> <div id="filter"> <div id="textfilter"></div> - <div id="letters">{ letters }</div> + <div id="letters">{ letters } – { deprecated }</div> </div> <div class="pack" id="tpl">{ def packageElem(pack: model.Package): NodeSeq = { diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Source.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Source.scala deleted file mode 100644 index 37145756d9..0000000000 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/Source.scala +++ /dev/null @@ -1,127 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2007-2013 LAMP/EPFL - * @author David Bernard, Manohar Jonnalagedda - */ - -package scala.tools.nsc -package doc -package html -package page - -import scala.xml.NodeSeq -import java.io.File - -class Source(sourceFile: File) extends HtmlPage { - - val path = List("source.html") - - val title = "Scaladoc: page source" - - val headers = - NodeSeq.Empty - - val body = - <body> - <h1>Page source is not implemented yet</h1> - </body> - - /* - - - def readTextFromSrcDir(subPath: String) :Option[String] = { - readTextFromFile(new File(sourceDir, subPath)) - } - - def readTextFromFile(f : File) :Option[String] = { - if (f.exists) { - Some(Source.fromFile(f)(Codec.default).getLines().mkString("")) - } else { - None - } - } - - - def writeTextToFile(f : File, txt : String, header: Option[String], footer: Option[String]) { - val out = new FileOutputStream(f) - try { - val enc = "UTF-8" - header.foreach(s => out.write(s.getBytes(enc))) - out.write(txt.getBytes(enc)) - footer.foreach(s => out.write(s.getBytes(enc))) - } finally { - try { - out.close() - } catch { - case _ => //ignore - } - } - } - - trait SourceHtmlizer { - def scalaToHtml(src :File) : Option[File] - } - - lazy val sourceHtmlizer : SourceHtmlizer = { - if (cfg.htmlizeSource) { - new SourceHtmlizer { - - val inDir: File = cfg.sourcedir - val outDir: File = cfg.outputdir - - private def relativize(uri: URI, from: URI) = linkHelper.relativize(uri, from).getOrElse("__notFound__" + uri.getPath) - - def header(dest: URI) = Some(""" - <html> - <head> - <link href='""" + relativize(new URI("site:/_highlighter/SyntaxHighlighter.css"), dest) + """' rel='stylesheet' type='text/css'/> - <script language='javascript' src='""" + relativize(new URI("site:/_highlighter/shAll.js"), dest) + """'></script> - </head> - <body> - <pre name="code" class="scala" style="width:100%"> - """) - - def footer(dest: URI) = Some("""</pre> - <script language='javascript'> - dp.SyntaxHighlighter.ClipboardSwf = '""" + relativize(new URI("site:/_highlighter/clipboard.swf"), dest) + """'; - dp.SyntaxHighlighter.HighlightAll('code'); - </script> - </body> - </html> - """) - - //TODO: escape the source code - def scalaToHtml(src :File) = { - val dest = new File(outDir, fileHelper.relativePathUnderDir(src, inDir) + ".html") - if (!dest.exists || dest.lastModified < src.lastModified) { - - //we need to verify whether the directory we are trying to write to has already been created or not - if(!dest.getParentFile.exists) dest.getParentFile.mkdirs - - val uri = linkHelper.uriFor(dest).get - var txt = fileHelper.readTextFromFile(src).getOrElse("") - txt = txt.replace("<", "<") - fileHelper.writeTextToFile(dest, txt, header(uri), footer(uri)) - } - Some(dest) - } - - def copyResources() { - val loader = this.getClass().getClassLoader() - val buf = new Array[Byte](1024) - def copyResource(name: String) = fileHelper.copyResource("/scala/tools/nsc/doc/html/resource/", name, outDir, loader, buf) - copyResource("_highlighter/clipboard.swf") - copyResource("_highlighter/shAll.js") - copyResource("_highlighter/SyntaxHighlighter.css") - } - - copyResources() - } - } else { - new SourceHtmlizer { - def scalaToHtml(src :File) = None - } - } - } - */ - -} 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 e10c54a414..c384ed7034 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala @@ -103,11 +103,13 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp <body class={ if (tpl.isType) "type" else "value" }> <div id="definition"> { + val (src, alt) = docEntityKindToBigImage(tpl) + tpl.companion match { case Some(companion) if (companion.visibility.isPublic && companion.inSource != None) => - <a href={relativeLinkTo(companion)} title={docEntityKindToCompanionTitle(tpl)}><img src={ relativeLinkTo(List(docEntityKindToBigImage(tpl), "lib")) }/></a> + <a href={relativeLinkTo(companion)} title={docEntityKindToCompanionTitle(tpl)}><img alt={alt} src={ relativeLinkTo(List(src, "lib")) }/></a> case _ => - <img src={ relativeLinkTo(List(docEntityKindToBigImage(tpl), "lib")) }/> + <img alt={alt} src={ relativeLinkTo(List(src, "lib")) }/> }} { owner } <h1>{ displayName }</h1>{ 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 e129e6cf6a..e84d7c1ca6 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 @@ -210,6 +210,7 @@ dl.attributes > dd { display: block; padding-left: 10em; margin-bottom: 5px; + min-height: 15px; } #template .values > h3 { @@ -669,6 +670,7 @@ div.fullcomment dl.paramcmts > dd { padding-left: 10px; margin-bottom: 5px; margin-left: 70px; + min-height: 15px; } /* Members filter tool */ 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 1ebcb67f04..798a2d430b 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 @@ -179,7 +179,7 @@ $(document).ready(function(){ filter(); }); - $("#visbl > ol > li.public").click(function() { + $("#order > ol > li.alpha").click(function() { if ($(this).hasClass("out")) { orderAlpha(); } diff --git a/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala index 643a089aae..ad53dc6bfa 100755 --- a/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala @@ -14,10 +14,12 @@ object IndexModelFactory { def makeIndex(universe: Universe): Index = new Index { - lazy val firstLetterIndex: Map[Char, SymbolMap] = { + lazy val (firstLetterIndex, hasDeprecatedMembers): (Map[Char, SymbolMap], Boolean) = { object result extends mutable.HashMap[Char,SymbolMap] { + var deprecated = false + /* symbol name ordering */ implicit def orderingMap = math.Ordering.String @@ -32,6 +34,8 @@ object IndexModelFactory { val members = letter.get(d.name).getOrElse { SortedSet.empty[MemberEntity](Ordering.by { _.toString }) } + d + if (!deprecated && members.find(_.deprecation.isDefined).isDefined) + deprecated = true this(firstLetter) = letter + (d.name -> members) } } @@ -50,7 +54,7 @@ object IndexModelFactory { gather(universe.rootPackage) - result.toMap + (result.toMap, result.deprecated) } } } diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala index 7c554d196c..3d2bfd7251 100644 --- a/src/scalap/scala/tools/scalap/Main.scala +++ b/src/scalap/scala/tools/scalap/Main.scala @@ -28,6 +28,7 @@ import scalax.rules.scalasig._ class Main { val SCALA_SIG = "ScalaSig" val SCALA_SIG_ANNOTATION = "Lscala/reflect/ScalaSignature;" + val SCALA_LONG_SIG_ANNOTATION = "Lscala/reflect/ScalaLongSignature;" val BYTES_VALUE = "bytes" val versionMsg = "Scala classfile decoder %s -- %s\n".format(Properties.versionString, Properties.copyrightString) diff --git a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala index e3076322dd..c36fdd02cd 100644 --- a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala +++ b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala @@ -14,20 +14,32 @@ package scalasig import scala.language.postfixOps import scala.language.implicitConversions -import ClassFileParser.{ ConstValueIndex, Annotation } +import ClassFileParser._ import scala.reflect.internal.pickling.ByteCodecs object ScalaSigParser { - import Main.{ SCALA_SIG, SCALA_SIG_ANNOTATION, BYTES_VALUE } + import Main.{ BYTES_VALUE, SCALA_LONG_SIG_ANNOTATION, SCALA_SIG, SCALA_SIG_ANNOTATION } + // TODO SI-9296 duplicated code, refactor def scalaSigFromAnnotation(classFile: ClassFile): Option[ScalaSig] = { import classFile._ - classFile.annotation(SCALA_SIG_ANNOTATION) map { + def getBytes(bytesElem: AnnotationElement): Array[Byte] = bytesElem.elementValue match { + case ConstValueIndex(index) => bytesForIndex(index) + case ArrayValue(signatureParts) => mergedLongSignatureBytes(signatureParts) + } + + def mergedLongSignatureBytes(signatureParts: Seq[ElementValue]): Array[Byte] = signatureParts.flatMap { + case ConstValueIndex(index) => bytesForIndex(index) + }(collection.breakOut) + + def bytesForIndex(index: Int) = constantWrapped(index).asInstanceOf[StringBytesPair].bytes + + classFile.annotation(SCALA_SIG_ANNOTATION) + .orElse(classFile.annotation(SCALA_LONG_SIG_ANNOTATION)).map { case Annotation(_, elements) => val bytesElem = elements.find(elem => constant(elem.elementNameIndex) == BYTES_VALUE).get - val bytes = ((bytesElem.elementValue match {case ConstValueIndex(index) => constantWrapped(index)}) - .asInstanceOf[StringBytesPair].bytes) + val bytes = getBytes(bytesElem) val length = ByteCodecs.decode(bytes) ScalaSigAttributeParsers.parse(ByteCode(bytes.take(length))) diff --git a/test/disabled/presentation/timeofday/src/timeofday.scala b/test/disabled/presentation/timeofday/src/timeofday.scala index d6355097f1..c8dc7cf820 100644 --- a/test/disabled/presentation/timeofday/src/timeofday.scala +++ b/test/disabled/presentation/timeofday/src/timeofday.scala @@ -2,7 +2,7 @@ object timeofday { class DateError extends Exception /** Simulating properties in Scala - * (example 4.2.1 in ScalaReference.pdf) + * (example 4.2.1 in the Scala Language Specification) */ class TimeOfDayVar { private var h, m, s: Int = 0 @@ -32,4 +32,4 @@ object timeofday { d.hours = 8; d./*!*/minutes = 30; d.seconds = 0 d.hours/*#*/ = 25 // throws a DateError exception } -}
\ No newline at end of file +} diff --git a/test/files/instrumented/inline-in-constructors.flags b/test/files/instrumented/inline-in-constructors.flags index 068318e8ac..d1ebc4c940 100644 --- a/test/files/instrumented/inline-in-constructors.flags +++ b/test/files/instrumented/inline-in-constructors.flags @@ -1 +1 @@ --optimise -Ydelambdafy:inline +-optimise -Ydelambdafy:inline -Ybackend:GenASM diff --git a/test/files/jvm/constant-optimization/Foo_1.flags b/test/files/jvm/constant-optimization/Foo_1.flags index 86f52af447..67a1dbe8da 100644 --- a/test/files/jvm/constant-optimization/Foo_1.flags +++ b/test/files/jvm/constant-optimization/Foo_1.flags @@ -1 +1 @@ --Ynooptimise -Yconst-opt
\ No newline at end of file +-Ynooptimise -Yconst-opt -Ybackend:GenASM
\ No newline at end of file diff --git a/test/files/jvm/inner.scala b/test/files/jvm/inner.scala index c05e803449..dc01b124c5 100644 --- a/test/files/jvm/inner.scala +++ b/test/files/jvm/inner.scala @@ -77,7 +77,7 @@ object Scalatest { def java(cname: String) = exec(javacmd, "-cp", classpath, cname) - /** Execute cmd, wait for the process to end and pipe it's output to stdout */ + /** Execute cmd, wait for the process to end and pipe its output to stdout */ private def exec(args: String*) { val proc = Runtime.getRuntime().exec(args.toArray) val inp = new BufferedReader(new InputStreamReader(proc.getInputStream)) diff --git a/test/files/jvm/innerClassAttribute.check b/test/files/jvm/innerClassAttribute.check index bb532e4f36..41448f359b 100644 --- a/test/files/jvm/innerClassAttribute.check +++ b/test/files/jvm/innerClassAttribute.check @@ -14,27 +14,27 @@ A19 / null / null A19 / null / null A19 / null / null -- A20 -- -A20$$anonfun$6 / null / null / 17 +A20$$anonfun$4 / null / null / 17 fun1: attribute for itself and the two child closures `() => ()` and `() => () => 1` -A20$$anonfun$6 / null / null / 17 -A20$$anonfun$6$$anonfun$apply$1 / null / null / 17 -A20$$anonfun$6$$anonfun$apply$3 / null / null / 17 +A20$$anonfun$4 / null / null / 17 +A20$$anonfun$4$$anonfun$apply$1 / null / null / 17 +A20$$anonfun$4$$anonfun$apply$2 / null / null / 17 fun2 () => (): itself and the outer closure -A20$$anonfun$6 / null / null / 17 -A20$$anonfun$6$$anonfun$apply$1 / null / null / 17 +A20$$anonfun$4 / null / null / 17 +A20$$anonfun$4$$anonfun$apply$1 / null / null / 17 fun3 () => () => (): itself, the outer closure and its child closure -A20$$anonfun$6 / null / null / 17 -A20$$anonfun$6$$anonfun$apply$3 / null / null / 17 -A20$$anonfun$6$$anonfun$apply$3$$anonfun$apply$2 / null / null / 17 +A20$$anonfun$4 / null / null / 17 +A20$$anonfun$4$$anonfun$apply$2 / null / null / 17 +A20$$anonfun$4$$anonfun$apply$2$$anonfun$apply$3 / null / null / 17 fun4: () => 1: itself and the two outer closures -A20$$anonfun$6 / null / null / 17 -A20$$anonfun$6$$anonfun$apply$3 / null / null / 17 -A20$$anonfun$6$$anonfun$apply$3$$anonfun$apply$2 / null / null / 17 +A20$$anonfun$4 / null / null / 17 +A20$$anonfun$4$$anonfun$apply$2 / null / null / 17 +A20$$anonfun$4$$anonfun$apply$2$$anonfun$apply$3 / null / null / 17 enclosing: nested closures have outer class defined, but no outer method A20 / null / null -A20$$anonfun$6 / null / null -A20$$anonfun$6 / null / null -A20$$anonfun$6$$anonfun$apply$3 / null / null +A20$$anonfun$4 / null / null +A20$$anonfun$4 / null / null +A20$$anonfun$4$$anonfun$apply$2 / null / null #partest -Ydelambdafy:method -- A4 -- null / null / null diff --git a/test/files/jvm/innerClassAttribute/Classes_1.scala b/test/files/jvm/innerClassAttribute/Classes_1.scala index fb1f32aa3d..62c7d94d90 100644 --- a/test/files/jvm/innerClassAttribute/Classes_1.scala +++ b/test/files/jvm/innerClassAttribute/Classes_1.scala @@ -12,8 +12,8 @@ object A3 { } class A4 { - def f(l: List[Int]): List[Int] = { - l map (_ + 1) + def f(l: List[String]): List[String] = { + l map (_ + "1") } } @@ -114,21 +114,21 @@ class A18 { } class A19 { - ((x: Int) => x + 3) + ((x: String) => x + "3") val x = { - ((x: Int) => x + 1) + ((x: String) => x + "1") } { - ((x: Int) => x + 2) + ((x: String) => x + "2") } } class A20 { - () => { - {() => ()} - {() => () => 1} + (s: String) => { + {(s: String) => ()} + {(s: String) => (s: String) => 1} } } @@ -189,13 +189,13 @@ trait A24 extends A24Base { class SI_9105 { // the EnclosingMethod attributes depend on the delambdafy strategy (inline vs method) - // outerClass-inline enclMeth-inline outerClass-method enclMeth-method - val fun = () => { + // outerClass-inline enclMeth-inline outerClass-method enclMeth-method + val fun = (s: String) => { class A // closure null (*) SI_9105 null def m: Object = { class B; new B } // closure m$1 SI_9105 m$1 val f: Object = { class C; new C } // closure null (*) SI_9105 null } - def met = () => { + def met = (s: String) => { class D // closure null (*) SI_9105 met def m: Object = { class E; new E } // closure m$1 SI_9105 m$1 val f: Object = { class F; new F } // closure null (*) SI_9105 met @@ -210,17 +210,19 @@ class SI_9105 { // So using `null` looks more like the situation in the source code: C / F are nested classes of the anon-fun, and // there's no method in between. - def byName[T](op: => T) = 0 + def byName(op: => Any) = 0 val bnV = byName { class G // closure null (*) SI_9105 null def m: Object = { class H; new H } // closure m$1 SI_9105 m$1 val f: Object = { class I; new I } // closure null (*) SI_9105 null + "" } def bnM = byName { class J // closure null (*) SI_9105 bnM def m: Object = { class K; new K } // closure m$1 SI_9105 m$1 val f: Object = { class L; new L } // closure null (*) SI_9105 bnM + "" } } @@ -283,8 +285,8 @@ object NestedInValueClass { class A(val arg: String) extends AnyVal { // A has InnerClass entries for the two closures (and for A and A$). not for B / C def f = { - def g = List().map(x => (() => x)) // outer class A, no outer method (g is moved to the companion, doesn't exist in A) - g.map(x => (() => x)) // outer class A, outer method f + def g = List().map(x => ((s: String) => x)) // outer class A, no outer method (g is moved to the companion, doesn't exist in A) + g.map(x => ((s: String) => x)) // outer class A, outer method f } // statements and field declarations are not allowed in value classes } diff --git a/test/files/jvm/innerClassAttribute/Test.scala b/test/files/jvm/innerClassAttribute/Test.scala index bc9aa2376a..376b3c895b 100644 --- a/test/files/jvm/innerClassAttribute/Test.scala +++ b/test/files/jvm/innerClassAttribute/Test.scala @@ -5,11 +5,14 @@ import asm.{Opcodes => Flags} import scala.collection.JavaConverters._ object Test extends BytecodeTest { + // Helpful for debugging the test: + // println(new java.io.File(classpath.asURLs.head.toURI).list().sorted.mkString("\n")) + def assertSame(a: Any, b: Any) = { assert(a == b, s"\na: $a\nb: $b") } - val publicStatic = Flags.ACC_PUBLIC | Flags.ACC_STATIC + val publicStatic = Flags.ACC_PUBLIC | Flags.ACC_STATIC val publicAbstractInterface = Flags.ACC_PUBLIC | Flags.ACC_ABSTRACT | Flags.ACC_INTERFACE def innerClassNodes(className: String): List[InnerClassNode] = { @@ -266,10 +269,10 @@ object Test extends BytecodeTest { printInnerClassNodes("A20") - val fun1 = lambdaClass("A20$$anonfun$6", "A20$lambda$1") - val fun2 = lambdaClass("A20$$anonfun$6$$anonfun$apply$1", "A20$lambda$$$nestedInAnonfun$5$1") - val fun3 = lambdaClass("A20$$anonfun$6$$anonfun$apply$3", "A20$lambda$$$nestedInAnonfun$5$2") - val fun4 = lambdaClass("A20$$anonfun$6$$anonfun$apply$3$$anonfun$apply$2", "A20$lambda$$$nestedInAnonfun$7$1") + val fun1 = lambdaClass("A20$$anonfun$4", "A20$lambda$1") + val fun2 = lambdaClass("A20$$anonfun$4$$anonfun$apply$1", "A20$lambda$$$nestedInAnonfun$5$1") + val fun3 = lambdaClass("A20$$anonfun$4$$anonfun$apply$2", "A20$lambda$$$nestedInAnonfun$5$2") + val fun4 = lambdaClass("A20$$anonfun$4$$anonfun$apply$2$$anonfun$apply$3", "A20$lambda$$$nestedInAnonfun$7$1") println("fun1: attribute for itself and the two child closures `() => ()` and `() => () => 1`") printInnerClassNodes(fun1) @@ -339,9 +342,9 @@ object Test extends BytecodeTest { assertEnclosingMethod ("SI_9105$A$3" , "SI_9105", null , null) assertEnclosingMethod ("SI_9105$B$5" , "SI_9105", "m$1", "()Ljava/lang/Object;") assertEnclosingMethod ("SI_9105$C$1" , "SI_9105", null , null) - assertEnclosingMethod ("SI_9105$D$1" , "SI_9105", "met", "()Lscala/Function0;") + assertEnclosingMethod ("SI_9105$D$1" , "SI_9105", "met", "()Lscala/Function1;") assertEnclosingMethod ("SI_9105$E$1" , "SI_9105", "m$3", "()Ljava/lang/Object;") - assertEnclosingMethod ("SI_9105$F$1" , "SI_9105", "met", "()Lscala/Function0;") + assertEnclosingMethod ("SI_9105$F$1" , "SI_9105", "met", "()Lscala/Function1;") assertNoEnclosingMethod("SI_9105$lambda$$met$1") assertNoEnclosingMethod("SI_9105$lambda$1") assertNoEnclosingMethod("SI_9105") @@ -366,35 +369,35 @@ object Test extends BytecodeTest { assert(innerClassNodes("SI_9105").length == 12) // the 12 local classes } else { // comment in innerClassAttribute/Classes_1.scala explains the difference between A / C and D / F. - assertEnclosingMethod ("SI_9105$$anonfun$4$A$3" , "SI_9105$$anonfun$4" , null , null) - assertEnclosingMethod ("SI_9105$$anonfun$4$B$5" , "SI_9105$$anonfun$4" , "m$1" , "()Ljava/lang/Object;") - assertEnclosingMethod ("SI_9105$$anonfun$4$C$1" , "SI_9105$$anonfun$4" , null , null) + assertEnclosingMethod ("SI_9105$$anonfun$5$A$3" , "SI_9105$$anonfun$5" , null , null) + assertEnclosingMethod ("SI_9105$$anonfun$5$B$5" , "SI_9105$$anonfun$5" , "m$1" , "()Ljava/lang/Object;") + assertEnclosingMethod ("SI_9105$$anonfun$5$C$1" , "SI_9105$$anonfun$5" , null , null) assertEnclosingMethod ("SI_9105$$anonfun$met$1$D$1", "SI_9105$$anonfun$met$1", null , null) assertEnclosingMethod ("SI_9105$$anonfun$met$1$E$1", "SI_9105$$anonfun$met$1", "m$3" , "()Ljava/lang/Object;") assertEnclosingMethod ("SI_9105$$anonfun$met$1$F$1", "SI_9105$$anonfun$met$1", null , null) - assertEnclosingMethod ("SI_9105$$anonfun$4" , "SI_9105" , null , null) - assertEnclosingMethod ("SI_9105$$anonfun$met$1" , "SI_9105" , "met" , "()Lscala/Function0;") + assertEnclosingMethod ("SI_9105$$anonfun$5" , "SI_9105" , null , null) + assertEnclosingMethod ("SI_9105$$anonfun$met$1" , "SI_9105" , "met" , "()Lscala/Function1;") assertNoEnclosingMethod("SI_9105") - assertLocal(ownInnerClassNode("SI_9105$$anonfun$4$A$3"), "SI_9105$$anonfun$4$A$3" , "A$3") - assertLocal(ownInnerClassNode("SI_9105$$anonfun$4$B$5"), "SI_9105$$anonfun$4$B$5" , "B$5") - assertLocal(ownInnerClassNode("SI_9105$$anonfun$4$C$1"), "SI_9105$$anonfun$4$C$1" , "C$1") + assertLocal(ownInnerClassNode("SI_9105$$anonfun$5$A$3"), "SI_9105$$anonfun$5$A$3" , "A$3") + assertLocal(ownInnerClassNode("SI_9105$$anonfun$5$B$5"), "SI_9105$$anonfun$5$B$5" , "B$5") + assertLocal(ownInnerClassNode("SI_9105$$anonfun$5$C$1"), "SI_9105$$anonfun$5$C$1" , "C$1") assertLocal(ownInnerClassNode("SI_9105$$anonfun$met$1$D$1"), "SI_9105$$anonfun$met$1$D$1", "D$1") assertLocal(ownInnerClassNode("SI_9105$$anonfun$met$1$E$1"), "SI_9105$$anonfun$met$1$E$1", "E$1") assertLocal(ownInnerClassNode("SI_9105$$anonfun$met$1$F$1"), "SI_9105$$anonfun$met$1$F$1", "F$1") // by-name - assertEnclosingMethod("SI_9105$$anonfun$5$G$1", "SI_9105$$anonfun$5", null, null) - assertEnclosingMethod("SI_9105$$anonfun$5$H$1", "SI_9105$$anonfun$5", "m$2", "()Ljava/lang/Object;") - assertEnclosingMethod("SI_9105$$anonfun$5$I$1", "SI_9105$$anonfun$5", null, null) + assertEnclosingMethod("SI_9105$$anonfun$6$G$1", "SI_9105$$anonfun$6", null, null) + assertEnclosingMethod("SI_9105$$anonfun$6$H$1", "SI_9105$$anonfun$6", "m$2", "()Ljava/lang/Object;") + assertEnclosingMethod("SI_9105$$anonfun$6$I$1", "SI_9105$$anonfun$6", null, null) assertEnclosingMethod("SI_9105$$anonfun$bnM$1$J$1", "SI_9105$$anonfun$bnM$1", null, null) assertEnclosingMethod("SI_9105$$anonfun$bnM$1$K$2", "SI_9105$$anonfun$bnM$1", "m$4", "()Ljava/lang/Object;") assertEnclosingMethod("SI_9105$$anonfun$bnM$1$L$1", "SI_9105$$anonfun$bnM$1", null, null) - assertAnonymous(ownInnerClassNode("SI_9105$$anonfun$4"), "SI_9105$$anonfun$4") + assertAnonymous(ownInnerClassNode("SI_9105$$anonfun$5"), "SI_9105$$anonfun$5") assertAnonymous(ownInnerClassNode("SI_9105$$anonfun$met$1"), "SI_9105$$anonfun$met$1") - assert(innerClassNodes("SI_9105$$anonfun$4").length == 4) // itself and three of the local classes + assert(innerClassNodes("SI_9105$$anonfun$5").length == 4) // itself and three of the local classes assert(innerClassNodes("SI_9105$$anonfun$met$1").length == 4) // itself and three of the local classes assert(innerClassNodes("SI_9105").length == 4) // the four anon funs } @@ -474,7 +477,7 @@ object Test extends BytecodeTest { testInner("ImplClassesAreTopLevel$B2$1$class", b2) testInner("ImplClassesAreTopLevel$B3$1$class", b3) testInner("ImplClassesAreTopLevel$B4$class", b4) - + testInner("ImplClassesAreTopLevel$B1", b1) testInner("ImplClassesAreTopLevel$B2$1", b2) testInner("ImplClassesAreTopLevel$B3$1", b3) @@ -533,13 +536,13 @@ object Test extends BytecodeTest { "NestedInValueClass$A$lambda$$g$2$1", "NestedInValueClass$A$lambda$$f$extension$1", "NestedInValueClass$A$lambda$$$nestedInAnonfun$13$1", - "NestedInValueClass$A$lambda$$$nestedInAnonfun$15$1").foreach(assertNoEnclosingMethod) + "NestedInValueClass$A$lambda$$NestedInValueClass$A$$$nestedInAnonfun$15$1").foreach(assertNoEnclosingMethod) testInner("NestedInValueClass$A", a, am) testInner("NestedInValueClass$A$", a, am, b, c) testInner("NestedInValueClass$A$lambda$$g$2$1", am) testInner("NestedInValueClass$A$lambda$$f$extension$1", am) testInner("NestedInValueClass$A$lambda$$$nestedInAnonfun$13$1", am) - testInner("NestedInValueClass$A$lambda$$$nestedInAnonfun$15$1", am) + testInner("NestedInValueClass$A$lambda$$NestedInValueClass$A$$$nestedInAnonfun$15$1", am) } else { assertEnclosingMethod("NestedInValueClass$A$$anonfun$g$2$1" , "NestedInValueClass$A" , null, null) assertEnclosingMethod("NestedInValueClass$A$$anonfun$g$2$1$$anonfun$apply$4" , "NestedInValueClass$A$$anonfun$g$2$1" , null, null) diff --git a/test/files/jvm/javaReflection/Classes_1.scala b/test/files/jvm/javaReflection/Classes_1.scala index 11963e2770..e9cd4f756a 100644 --- a/test/files/jvm/javaReflection/Classes_1.scala +++ b/test/files/jvm/javaReflection/Classes_1.scala @@ -13,7 +13,7 @@ class A { trait C object D new T { } - (() => -1) + (() => "-1") def f = { class KB } } @@ -21,21 +21,21 @@ class A { new T { } // anonymous function, not a member - (() => 1) + (() => "1") def f = { class E trait F object G new T { } - (() => 2) + (() => "2") if (new Object().hashCode == 1) { class H trait I object J new T { } - (() => 3) + (() => "3") } else { () } @@ -46,7 +46,7 @@ class A { trait L object M new T { } - (() => 4) + (() => "4") } val x = { @@ -54,7 +54,7 @@ class A { trait O object P new T { } - (() => 5) + (() => "5") } def this(x: Int) { @@ -63,7 +63,7 @@ class A { trait R object S new T { } - (() => () => 5) + (() => () => "5") } } @@ -72,7 +72,7 @@ object AO { trait C object D new T { } - (() => 1) + (() => "1") } trait AT { @@ -80,5 +80,5 @@ trait AT { trait C object D new T { } - (() => 1) + (() => "1") } diff --git a/test/files/jvm/javaReflection/Test.scala b/test/files/jvm/javaReflection/Test.scala index 5b6ef1b573..ae5a36eeb2 100644 --- a/test/files/jvm/javaReflection/Test.scala +++ b/test/files/jvm/javaReflection/Test.scala @@ -124,8 +124,8 @@ object Test { // exclude files from Test.scala, just take those from Classes_1.scala case s if !s.startsWith("Test") && s.endsWith(".class") => s.substring(0, s.length - 6) }).sortWith((a, b) => { - // sort such that first there are all anonymous funcitions, then all other classes. - // within those cathegories, sort lexically. + // sort such that first there are all anonymous functions, then all other classes. + // within those categories, sort lexically. // this makes the check file smaller: it differs for anonymous functions between -Ydelambdafy:inline/method. // the other classes are the same. if (isAnonFunClassName(a)) !isAnonFunClassName(b) || a < b diff --git a/test/files/jvm/patmat_opt_ignore_underscore.flags b/test/files/jvm/patmat_opt_ignore_underscore.flags index 1182725e86..2cd4b38726 100644 --- a/test/files/jvm/patmat_opt_ignore_underscore.flags +++ b/test/files/jvm/patmat_opt_ignore_underscore.flags @@ -1 +1 @@ --optimize
\ No newline at end of file +-optimize -Ybackend:GenASM
\ No newline at end of file diff --git a/test/files/jvm/patmat_opt_no_nullcheck.flags b/test/files/jvm/patmat_opt_no_nullcheck.flags index 1182725e86..2cd4b38726 100644 --- a/test/files/jvm/patmat_opt_no_nullcheck.flags +++ b/test/files/jvm/patmat_opt_no_nullcheck.flags @@ -1 +1 @@ --optimize
\ No newline at end of file +-optimize -Ybackend:GenASM
\ No newline at end of file diff --git a/test/files/jvm/patmat_opt_primitive_typetest.flags b/test/files/jvm/patmat_opt_primitive_typetest.flags index 49d036a887..b9bb09167e 100644 --- a/test/files/jvm/patmat_opt_primitive_typetest.flags +++ b/test/files/jvm/patmat_opt_primitive_typetest.flags @@ -1 +1 @@ --optimize +-optimize -Ybackend:GenASM diff --git a/test/files/jvm/t7006/Foo_1.flags b/test/files/jvm/t7006/Foo_1.flags index 37b2116413..29a9d424f0 100644 --- a/test/files/jvm/t7006/Foo_1.flags +++ b/test/files/jvm/t7006/Foo_1.flags @@ -1 +1 @@ --optimise -Ydebug -Xfatal-warnings +-optimise -Ydebug -Xfatal-warnings -Ybackend:GenASM diff --git a/test/files/neg/case-collision2.flags b/test/files/neg/case-collision2.flags index 5bfa9da5c5..bea46902c9 100644 --- a/test/files/neg/case-collision2.flags +++ b/test/files/neg/case-collision2.flags @@ -1 +1 @@ --Ynooptimize -Ybackend:GenBCode -Xfatal-warnings +-Ybackend:GenBCode -Xfatal-warnings diff --git a/test/files/neg/inlineMaxSize.check b/test/files/neg/inlineMaxSize.check new file mode 100644 index 0000000000..9d790e154c --- /dev/null +++ b/test/files/neg/inlineMaxSize.check @@ -0,0 +1,9 @@ +inlineMaxSize.scala:7: warning: C::i()I is annotated @inline but could not be inlined: +The size of the callsite method C::j()I +would exceed the JVM method size limit after inlining C::i()I. + + @inline final def j = i + i + i + ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found +one error found diff --git a/test/files/neg/inlineMaxSize.flags b/test/files/neg/inlineMaxSize.flags new file mode 100644 index 0000000000..9c6b811622 --- /dev/null +++ b/test/files/neg/inlineMaxSize.flags @@ -0,0 +1 @@ +-Ybackend:GenBCode -Ydelambdafy:method -Yopt:l:classpath -Yopt-warnings -Xfatal-warnings
\ No newline at end of file diff --git a/test/files/neg/inlineMaxSize.scala b/test/files/neg/inlineMaxSize.scala new file mode 100644 index 0000000000..9d2db1a357 --- /dev/null +++ b/test/files/neg/inlineMaxSize.scala @@ -0,0 +1,8 @@ +// not a JUnit test because of https://github.com/scala-opt/scala/issues/23 +class C { + @inline final def f = 0 + @inline final def g = f + f + f + f + f + f + f + f + f + f + @inline final def h = g + g + g + g + g + g + g + g + g + g + @inline final def i = h + h + h + h + h + h + h + h + h + h + @inline final def j = i + i + i +} diff --git a/test/files/neg/patmatexhaust-huge.check b/test/files/neg/patmatexhaust-huge.check new file mode 100644 index 0000000000..66dbd42ef3 --- /dev/null +++ b/test/files/neg/patmatexhaust-huge.check @@ -0,0 +1,7 @@ +patmatexhaust-huge.scala:404: warning: match may not be exhaustive. +It would fail on the following inputs: C392, C397 + def f(c: C): Int = c match { + ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found +one error found diff --git a/test/files/neg/patmatexhaust-huge.flags b/test/files/neg/patmatexhaust-huge.flags new file mode 100644 index 0000000000..591a950f83 --- /dev/null +++ b/test/files/neg/patmatexhaust-huge.flags @@ -0,0 +1 @@ +-Xfatal-warnings -unchecked -Ypatmat-exhaust-depth off
\ No newline at end of file diff --git a/test/files/neg/patmatexhaust-huge.scala b/test/files/neg/patmatexhaust-huge.scala new file mode 100644 index 0000000000..8f87655b7a --- /dev/null +++ b/test/files/neg/patmatexhaust-huge.scala @@ -0,0 +1,806 @@ +sealed trait C +case object C1 extends C +case object C2 extends C +case object C3 extends C +case object C4 extends C +case object C5 extends C +case object C6 extends C +case object C7 extends C +case object C8 extends C +case object C9 extends C +case object C10 extends C +case object C11 extends C +case object C12 extends C +case object C13 extends C +case object C14 extends C +case object C15 extends C +case object C16 extends C +case object C17 extends C +case object C18 extends C +case object C19 extends C +case object C20 extends C +case object C21 extends C +case object C22 extends C +case object C23 extends C +case object C24 extends C +case object C25 extends C +case object C26 extends C +case object C27 extends C +case object C28 extends C +case object C29 extends C +case object C30 extends C +case object C31 extends C +case object C32 extends C +case object C33 extends C +case object C34 extends C +case object C35 extends C +case object C36 extends C +case object C37 extends C +case object C38 extends C +case object C39 extends C +case object C40 extends C +case object C41 extends C +case object C42 extends C +case object C43 extends C +case object C44 extends C +case object C45 extends C +case object C46 extends C +case object C47 extends C +case object C48 extends C +case object C49 extends C +case object C50 extends C +case object C51 extends C +case object C52 extends C +case object C53 extends C +case object C54 extends C +case object C55 extends C +case object C56 extends C +case object C57 extends C +case object C58 extends C +case object C59 extends C +case object C60 extends C +case object C61 extends C +case object C62 extends C +case object C63 extends C +case object C64 extends C +case object C65 extends C +case object C66 extends C +case object C67 extends C +case object C68 extends C +case object C69 extends C +case object C70 extends C +case object C71 extends C +case object C72 extends C +case object C73 extends C +case object C74 extends C +case object C75 extends C +case object C76 extends C +case object C77 extends C +case object C78 extends C +case object C79 extends C +case object C80 extends C +case object C81 extends C +case object C82 extends C +case object C83 extends C +case object C84 extends C +case object C85 extends C +case object C86 extends C +case object C87 extends C +case object C88 extends C +case object C89 extends C +case object C90 extends C +case object C91 extends C +case object C92 extends C +case object C93 extends C +case object C94 extends C +case object C95 extends C +case object C96 extends C +case object C97 extends C +case object C98 extends C +case object C99 extends C +case object C100 extends C +case object C101 extends C +case object C102 extends C +case object C103 extends C +case object C104 extends C +case object C105 extends C +case object C106 extends C +case object C107 extends C +case object C108 extends C +case object C109 extends C +case object C110 extends C +case object C111 extends C +case object C112 extends C +case object C113 extends C +case object C114 extends C +case object C115 extends C +case object C116 extends C +case object C117 extends C +case object C118 extends C +case object C119 extends C +case object C120 extends C +case object C121 extends C +case object C122 extends C +case object C123 extends C +case object C124 extends C +case object C125 extends C +case object C126 extends C +case object C127 extends C +case object C128 extends C +case object C129 extends C +case object C130 extends C +case object C131 extends C +case object C132 extends C +case object C133 extends C +case object C134 extends C +case object C135 extends C +case object C136 extends C +case object C137 extends C +case object C138 extends C +case object C139 extends C +case object C140 extends C +case object C141 extends C +case object C142 extends C +case object C143 extends C +case object C144 extends C +case object C145 extends C +case object C146 extends C +case object C147 extends C +case object C148 extends C +case object C149 extends C +case object C150 extends C +case object C151 extends C +case object C152 extends C +case object C153 extends C +case object C154 extends C +case object C155 extends C +case object C156 extends C +case object C157 extends C +case object C158 extends C +case object C159 extends C +case object C160 extends C +case object C161 extends C +case object C162 extends C +case object C163 extends C +case object C164 extends C +case object C165 extends C +case object C166 extends C +case object C167 extends C +case object C168 extends C +case object C169 extends C +case object C170 extends C +case object C171 extends C +case object C172 extends C +case object C173 extends C +case object C174 extends C +case object C175 extends C +case object C176 extends C +case object C177 extends C +case object C178 extends C +case object C179 extends C +case object C180 extends C +case object C181 extends C +case object C182 extends C +case object C183 extends C +case object C184 extends C +case object C185 extends C +case object C186 extends C +case object C187 extends C +case object C188 extends C +case object C189 extends C +case object C190 extends C +case object C191 extends C +case object C192 extends C +case object C193 extends C +case object C194 extends C +case object C195 extends C +case object C196 extends C +case object C197 extends C +case object C198 extends C +case object C199 extends C +case object C200 extends C +case object C201 extends C +case object C202 extends C +case object C203 extends C +case object C204 extends C +case object C205 extends C +case object C206 extends C +case object C207 extends C +case object C208 extends C +case object C209 extends C +case object C210 extends C +case object C211 extends C +case object C212 extends C +case object C213 extends C +case object C214 extends C +case object C215 extends C +case object C216 extends C +case object C217 extends C +case object C218 extends C +case object C219 extends C +case object C220 extends C +case object C221 extends C +case object C222 extends C +case object C223 extends C +case object C224 extends C +case object C225 extends C +case object C226 extends C +case object C227 extends C +case object C228 extends C +case object C229 extends C +case object C230 extends C +case object C231 extends C +case object C232 extends C +case object C233 extends C +case object C234 extends C +case object C235 extends C +case object C236 extends C +case object C237 extends C +case object C238 extends C +case object C239 extends C +case object C240 extends C +case object C241 extends C +case object C242 extends C +case object C243 extends C +case object C244 extends C +case object C245 extends C +case object C246 extends C +case object C247 extends C +case object C248 extends C +case object C249 extends C +case object C250 extends C +case object C251 extends C +case object C252 extends C +case object C253 extends C +case object C254 extends C +case object C255 extends C +case object C256 extends C +case object C257 extends C +case object C258 extends C +case object C259 extends C +case object C260 extends C +case object C261 extends C +case object C262 extends C +case object C263 extends C +case object C264 extends C +case object C265 extends C +case object C266 extends C +case object C267 extends C +case object C268 extends C +case object C269 extends C +case object C270 extends C +case object C271 extends C +case object C272 extends C +case object C273 extends C +case object C274 extends C +case object C275 extends C +case object C276 extends C +case object C277 extends C +case object C278 extends C +case object C279 extends C +case object C280 extends C +case object C281 extends C +case object C282 extends C +case object C283 extends C +case object C284 extends C +case object C285 extends C +case object C286 extends C +case object C287 extends C +case object C288 extends C +case object C289 extends C +case object C290 extends C +case object C291 extends C +case object C292 extends C +case object C293 extends C +case object C294 extends C +case object C295 extends C +case object C296 extends C +case object C297 extends C +case object C298 extends C +case object C299 extends C +case object C300 extends C +case object C301 extends C +case object C302 extends C +case object C303 extends C +case object C304 extends C +case object C305 extends C +case object C306 extends C +case object C307 extends C +case object C308 extends C +case object C309 extends C +case object C310 extends C +case object C311 extends C +case object C312 extends C +case object C313 extends C +case object C314 extends C +case object C315 extends C +case object C316 extends C +case object C317 extends C +case object C318 extends C +case object C319 extends C +case object C320 extends C +case object C321 extends C +case object C322 extends C +case object C323 extends C +case object C324 extends C +case object C325 extends C +case object C326 extends C +case object C327 extends C +case object C328 extends C +case object C329 extends C +case object C330 extends C +case object C331 extends C +case object C332 extends C +case object C333 extends C +case object C334 extends C +case object C335 extends C +case object C336 extends C +case object C337 extends C +case object C338 extends C +case object C339 extends C +case object C340 extends C +case object C341 extends C +case object C342 extends C +case object C343 extends C +case object C344 extends C +case object C345 extends C +case object C346 extends C +case object C347 extends C +case object C348 extends C +case object C349 extends C +case object C350 extends C +case object C351 extends C +case object C352 extends C +case object C353 extends C +case object C354 extends C +case object C355 extends C +case object C356 extends C +case object C357 extends C +case object C358 extends C +case object C359 extends C +case object C360 extends C +case object C361 extends C +case object C362 extends C +case object C363 extends C +case object C364 extends C +case object C365 extends C +case object C366 extends C +case object C367 extends C +case object C368 extends C +case object C369 extends C +case object C370 extends C +case object C371 extends C +case object C372 extends C +case object C373 extends C +case object C374 extends C +case object C375 extends C +case object C376 extends C +case object C377 extends C +case object C378 extends C +case object C379 extends C +case object C380 extends C +case object C381 extends C +case object C382 extends C +case object C383 extends C +case object C384 extends C +case object C385 extends C +case object C386 extends C +case object C387 extends C +case object C388 extends C +case object C389 extends C +case object C390 extends C +case object C391 extends C +case object C392 extends C +case object C393 extends C +case object C394 extends C +case object C395 extends C +case object C396 extends C +case object C397 extends C +case object C398 extends C +case object C399 extends C +case object C400 extends C + +object M { + def f(c: C): Int = c match { + case C1 => 1 + case C2 => 2 + case C3 => 3 + case C4 => 4 + case C5 => 5 + case C6 => 6 + case C7 => 7 + case C8 => 8 + case C9 => 9 + case C10 => 10 + case C11 => 11 + case C12 => 12 + case C13 => 13 + case C14 => 14 + case C15 => 15 + case C16 => 16 + case C17 => 17 + case C18 => 18 + case C19 => 19 + case C20 => 20 + case C21 => 21 + case C22 => 22 + case C23 => 23 + case C24 => 24 + case C25 => 25 + case C26 => 26 + case C27 => 27 + case C28 => 28 + case C29 => 29 + case C30 => 30 + case C31 => 31 + case C32 => 32 + case C33 => 33 + case C34 => 34 + case C35 => 35 + case C36 => 36 + case C37 => 37 + case C38 => 38 + case C39 => 39 + case C40 => 40 + case C41 => 41 + case C42 => 42 + case C43 => 43 + case C44 => 44 + case C45 => 45 + case C46 => 46 + case C47 => 47 + case C48 => 48 + case C49 => 49 + case C50 => 50 + case C51 => 51 + case C52 => 52 + case C53 => 53 + case C54 => 54 + case C55 => 55 + case C56 => 56 + case C57 => 57 + case C58 => 58 + case C59 => 59 + case C60 => 60 + case C61 => 61 + case C62 => 62 + case C63 => 63 + case C64 => 64 + case C65 => 65 + case C66 => 66 + case C67 => 67 + case C68 => 68 + case C69 => 69 + case C70 => 70 + case C71 => 71 + case C72 => 72 + case C73 => 73 + case C74 => 74 + case C75 => 75 + case C76 => 76 + case C77 => 77 + case C78 => 78 + case C79 => 79 + case C80 => 80 + case C81 => 81 + case C82 => 82 + case C83 => 83 + case C84 => 84 + case C85 => 85 + case C86 => 86 + case C87 => 87 + case C88 => 88 + case C89 => 89 + case C90 => 90 + case C91 => 91 + case C92 => 92 + case C93 => 93 + case C94 => 94 + case C95 => 95 + case C96 => 96 + case C97 => 97 + case C98 => 98 + case C99 => 99 + case C100 => 100 + case C101 => 101 + case C102 => 102 + case C103 => 103 + case C104 => 104 + case C105 => 105 + case C106 => 106 + case C107 => 107 + case C108 => 108 + case C109 => 109 + case C110 => 110 + case C111 => 111 + case C112 => 112 + case C113 => 113 + case C114 => 114 + case C115 => 115 + case C116 => 116 + case C117 => 117 + case C118 => 118 + case C119 => 119 + case C120 => 120 + case C121 => 121 + case C122 => 122 + case C123 => 123 + case C124 => 124 + case C125 => 125 + case C126 => 126 + case C127 => 127 + case C128 => 128 + case C129 => 129 + case C130 => 130 + case C131 => 131 + case C132 => 132 + case C133 => 133 + case C134 => 134 + case C135 => 135 + case C136 => 136 + case C137 => 137 + case C138 => 138 + case C139 => 139 + case C140 => 140 + case C141 => 141 + case C142 => 142 + case C143 => 143 + case C144 => 144 + case C145 => 145 + case C146 => 146 + case C147 => 147 + case C148 => 148 + case C149 => 149 + case C150 => 150 + case C151 => 151 + case C152 => 152 + case C153 => 153 + case C154 => 154 + case C155 => 155 + case C156 => 156 + case C157 => 157 + case C158 => 158 + case C159 => 159 + case C160 => 160 + case C161 => 161 + case C162 => 162 + case C163 => 163 + case C164 => 164 + case C165 => 165 + case C166 => 166 + case C167 => 167 + case C168 => 168 + case C169 => 169 + case C170 => 170 + case C171 => 171 + case C172 => 172 + case C173 => 173 + case C174 => 174 + case C175 => 175 + case C176 => 176 + case C177 => 177 + case C178 => 178 + case C179 => 179 + case C180 => 180 + case C181 => 181 + case C182 => 182 + case C183 => 183 + case C184 => 184 + case C185 => 185 + case C186 => 186 + case C187 => 187 + case C188 => 188 + case C189 => 189 + case C190 => 190 + case C191 => 191 + case C192 => 192 + case C193 => 193 + case C194 => 194 + case C195 => 195 + case C196 => 196 + case C197 => 197 + case C198 => 198 + case C199 => 199 + case C200 => 200 + case C201 => 201 + case C202 => 202 + case C203 => 203 + case C204 => 204 + case C205 => 205 + case C206 => 206 + case C207 => 207 + case C208 => 208 + case C209 => 209 + case C210 => 210 + case C211 => 211 + case C212 => 212 + case C213 => 213 + case C214 => 214 + case C215 => 215 + case C216 => 216 + case C217 => 217 + case C218 => 218 + case C219 => 219 + case C220 => 220 + case C221 => 221 + case C222 => 222 + case C223 => 223 + case C224 => 224 + case C225 => 225 + case C226 => 226 + case C227 => 227 + case C228 => 228 + case C229 => 229 + case C230 => 230 + case C231 => 231 + case C232 => 232 + case C233 => 233 + case C234 => 234 + case C235 => 235 + case C236 => 236 + case C237 => 237 + case C238 => 238 + case C239 => 239 + case C240 => 240 + case C241 => 241 + case C242 => 242 + case C243 => 243 + case C244 => 244 + case C245 => 245 + case C246 => 246 + case C247 => 247 + case C248 => 248 + case C249 => 249 + case C250 => 250 + case C251 => 251 + case C252 => 252 + case C253 => 253 + case C254 => 254 + case C255 => 255 + case C256 => 256 + case C257 => 257 + case C258 => 258 + case C259 => 259 + case C260 => 260 + case C261 => 261 + case C262 => 262 + case C263 => 263 + case C264 => 264 + case C265 => 265 + case C266 => 266 + case C267 => 267 + case C268 => 268 + case C269 => 269 + case C270 => 270 + case C271 => 271 + case C272 => 272 + case C273 => 273 + case C274 => 274 + case C275 => 275 + case C276 => 276 + case C277 => 277 + case C278 => 278 + case C279 => 279 + case C280 => 280 + case C281 => 281 + case C282 => 282 + case C283 => 283 + case C284 => 284 + case C285 => 285 + case C286 => 286 + case C287 => 287 + case C288 => 288 + case C289 => 289 + case C290 => 290 + case C291 => 291 + case C292 => 292 + case C293 => 293 + case C294 => 294 + case C295 => 295 + case C296 => 296 + case C297 => 297 + case C298 => 298 + case C299 => 299 + case C300 => 300 + case C301 => 301 + case C302 => 302 + case C303 => 303 + case C304 => 304 + case C305 => 305 + case C306 => 306 + case C307 => 307 + case C308 => 308 + case C309 => 309 + case C310 => 310 + case C311 => 311 + case C312 => 312 + case C313 => 313 + case C314 => 314 + case C315 => 315 + case C316 => 316 + case C317 => 317 + case C318 => 318 + case C319 => 319 + case C320 => 320 + case C321 => 321 + case C322 => 322 + case C323 => 323 + case C324 => 324 + case C325 => 325 + case C326 => 326 + case C327 => 327 + case C328 => 328 + case C329 => 329 + case C330 => 330 + case C331 => 331 + case C332 => 332 + case C333 => 333 + case C334 => 334 + case C335 => 335 + case C336 => 336 + case C337 => 337 + case C338 => 338 + case C339 => 339 + case C340 => 340 + case C341 => 341 + case C342 => 342 + case C343 => 343 + case C344 => 344 + case C345 => 345 + case C346 => 346 + case C347 => 347 + case C348 => 348 + case C349 => 349 + case C350 => 350 + case C351 => 351 + case C352 => 352 + case C353 => 353 + case C354 => 354 + case C355 => 355 + case C356 => 356 + case C357 => 357 + case C358 => 358 + case C359 => 359 + case C360 => 360 + case C361 => 361 + case C362 => 362 + case C363 => 363 + case C364 => 364 + case C365 => 365 + case C366 => 366 + case C367 => 367 + case C368 => 368 + case C369 => 369 + case C370 => 370 + case C371 => 371 + case C372 => 372 + case C373 => 373 + case C374 => 374 + case C375 => 375 + case C376 => 376 + case C377 => 377 + case C378 => 378 + case C379 => 379 + case C380 => 380 + case C381 => 381 + case C382 => 382 + case C383 => 383 + case C384 => 384 + case C385 => 385 + case C386 => 386 + case C387 => 387 + case C388 => 388 + case C389 => 389 + case C390 => 390 + case C391 => 391 +// case C392 => 392 + case C393 => 393 + case C394 => 394 + case C395 => 395 + case C396 => 396 +// case C397 => 397 + case C398 => 398 + case C399 => 399 + case C400 => 400 + } +} diff --git a/test/files/neg/t0899.check b/test/files/neg/t0899.check index 8b71be8e0c..28cb06ae5a 100644 --- a/test/files/neg/t0899.check +++ b/test/files/neg/t0899.check @@ -1,10 +1,10 @@ -t0899.scala:9: error: super may be not be used on value o +t0899.scala:9: error: super may not be used on value o override val o = "Ha! " + super.o ^ -t0899.scala:11: error: super may be not be used on variable v +t0899.scala:11: error: super may not be used on variable v super.v = "aa" ^ -t0899.scala:12: error: super may be not be used on variable v +t0899.scala:12: error: super may not be used on variable v println(super.v) ^ three errors found diff --git a/test/files/neg/t3234.flags b/test/files/neg/t3234.flags index cc3d9fb6f0..406231bd96 100644 --- a/test/files/neg/t3234.flags +++ b/test/files/neg/t3234.flags @@ -1 +1 @@ --Yinline -Yinline-warnings -Xfatal-warnings +-Yinline -Yinline-warnings -Xfatal-warnings -Ybackend:GenASM diff --git a/test/files/neg/t562.check b/test/files/neg/t562.check index 8c3823642a..95be075af1 100644 --- a/test/files/neg/t562.check +++ b/test/files/neg/t562.check @@ -1,4 +1,4 @@ -t562.scala:10: error: super may be not be used on value y +t562.scala:10: error: super may not be used on value y override val y = super.y; ^ one error found diff --git a/test/files/neg/t7623.check b/test/files/neg/t7623.check index db368dd369..de35023664 100644 --- a/test/files/neg/t7623.check +++ b/test/files/neg/t7623.check @@ -1,21 +1,15 @@ -t7623.scala:19: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). - def f = "" match { case X(s) => } +t7623.scala:21: warning: A repeated case parameter or extracted sequence is not matched by a sequence wildcard (_*), and may fail at runtime. + def g = "" match { case X(s, t) => } // warn ^ -t7623.scala:21: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). - def g = "" match { case X(s, t) => } +t7623.scala:23: warning: Sequence wildcard (_*) does not align with repeated case parameter or extracted sequence; the result may be unexpected. + def h = "" match { case X(s, t, u @ _*) => } // warn ^ -t7623.scala:23: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). - def h = "" match { case X(s, t, u @ _*) => } - ^ -t7623.scala:9: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). - def f = C("") match { case C(s) => } - ^ -t7623.scala:11: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). - def g = C("") match { case C(s, t) => } +t7623.scala:11: warning: A repeated case parameter or extracted sequence is not matched by a sequence wildcard (_*), and may fail at runtime. + def g = C("") match { case C(s, t) => } // warn ^ -t7623.scala:13: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). - def h = C("") match { case C(s, t, u @ _*) => } +t7623.scala:13: warning: Sequence wildcard (_*) does not align with repeated case parameter or extracted sequence; the result may be unexpected. + def h = C("") match { case C(s, t, u @ _*) => } // warn ^ error: No warnings can be incurred under -Xfatal-warnings. -6 warnings found +four warnings found one error found diff --git a/test/files/neg/t7623.scala b/test/files/neg/t7623.scala index 5c40f37bc1..5334cc5f69 100644 --- a/test/files/neg/t7623.scala +++ b/test/files/neg/t7623.scala @@ -8,9 +8,9 @@ object X { def unapplySeq(a: Any): Option[(String, Seq[Int])] = Some("", List(1, trait Ctest { def f = C("") match { case C(s) => } - def g = C("") match { case C(s, t) => } + def g = C("") match { case C(s, t) => } // warn - def h = C("") match { case C(s, t, u @ _*) => } + def h = C("") match { case C(s, t, u @ _*) => } // warn def ok = C("") match { case C(s, u @ _*) => } } @@ -18,9 +18,9 @@ trait Ctest { trait Xtest { def f = "" match { case X(s) => } - def g = "" match { case X(s, t) => } + def g = "" match { case X(s, t) => } // warn - def h = "" match { case X(s, t, u @ _*) => } + def h = "" match { case X(s, t, u @ _*) => } // warn def ok = "" match { case X(s, u @ _*) => } } diff --git a/test/files/neg/t8731.check b/test/files/neg/t8731.check index 2a9af475fc..d47bd55b45 100644 --- a/test/files/neg/t8731.check +++ b/test/files/neg/t8731.check @@ -1,9 +1,6 @@ -t8731.scala:5: warning: matches with two cases or fewer are emitted using if-then-else instead of switch - def f(x: Int) = (x: @annotation.switch) match { - ^ t8731.scala:10: warning: could not emit switch for @switch annotated match def g(x: Int) = (x: @annotation.switch) match { ^ error: No warnings can be incurred under -Xfatal-warnings. -two warnings found +one warning found one error found diff --git a/test/files/neg/t9273.check b/test/files/neg/t9273.check new file mode 100644 index 0000000000..1dca63a736 --- /dev/null +++ b/test/files/neg/t9273.check @@ -0,0 +1,10 @@ +t9273.scala:2: error: class type required but ? found + val foo: Class[_] = classOf // error without position, line or file + ^ +t9273.scala:3: error: not found: type X + val foo1: Class[_] = classOf[X] // good error, all info contained + ^ +t9273.scala:7: error: not found: type X + val foo4: Class[_] = Predef.classOf[X] // good error, all info contained + ^ +three errors found diff --git a/test/files/neg/t9273.scala b/test/files/neg/t9273.scala new file mode 100644 index 0000000000..3f99dff17f --- /dev/null +++ b/test/files/neg/t9273.scala @@ -0,0 +1,9 @@ +class MissingLineNumbers { + val foo: Class[_] = classOf // error without position, line or file + val foo1: Class[_] = classOf[X] // good error, all info contained + val foo2 = classOf // Infers T=Nothing + + val foo3: Class[_] = Predef.classOf // Infers T=Nothing. Irregular wrt typedIdent. + val foo4: Class[_] = Predef.classOf[X] // good error, all info contained + val foo5 = Predef.classOf // Infers T=Nothing +} diff --git a/test/files/neg/t9286a.check b/test/files/neg/t9286a.check new file mode 100644 index 0000000000..2bc7c0cf15 --- /dev/null +++ b/test/files/neg/t9286a.check @@ -0,0 +1,7 @@ +t9286a.scala:6: error: name clash between defined and inherited member: +def foo(o: (String,)): Unit in class T and +private def foo(o: (Any,)): Unit at line 6 +have same type after erasure: (o: Tuple1)Unit + private def foo(o: Tuple1[Any]) = () + ^ +one error found diff --git a/test/files/neg/t9286a.scala b/test/files/neg/t9286a.scala new file mode 100644 index 0000000000..0375ac591f --- /dev/null +++ b/test/files/neg/t9286a.scala @@ -0,0 +1,13 @@ +class T { + def foo(o: Tuple1[String]) = () +} + +class U extends T { + private def foo(o: Tuple1[Any]) = () +} + +object Test { + def main(args: Array[String]): Unit = { + new U().foo(null) // IllegalAccessError: tried to access method U.foo(Lscala/Tuple1;)V from class Test$ + } +} diff --git a/test/files/neg/t9286b.check b/test/files/neg/t9286b.check new file mode 100644 index 0000000000..89a191bfee --- /dev/null +++ b/test/files/neg/t9286b.check @@ -0,0 +1,7 @@ +t9286b.scala:2: error: name clash between defined and inherited member: +def foo: Int in class C and +private def foo[A]: Int at line 2 +have same type after erasure: ()Int +class D extends C { private def foo[A] = 0 } + ^ +one error found diff --git a/test/files/neg/t9286b.scala b/test/files/neg/t9286b.scala new file mode 100644 index 0000000000..5c23075426 --- /dev/null +++ b/test/files/neg/t9286b.scala @@ -0,0 +1,5 @@ +class C { def foo = 0 } +class D extends C { private def foo[A] = 0 } + +class E { private def foo = 0 } +class F extends E { def foo[A] = 0 } // okay diff --git a/test/files/neg/t9286c.check b/test/files/neg/t9286c.check new file mode 100644 index 0000000000..785cb3f937 --- /dev/null +++ b/test/files/neg/t9286c.check @@ -0,0 +1,7 @@ +t9286c.scala:8: error: name clash between defined and inherited member: +def foo(m: M[_ >: String]): Int in trait T and +private def foo(m: M[_ >: Any]): Int at line 8 +have same type after erasure: (m: M)Int + def foo(m: M[_ >: Any]) = 0 // Expected: "same type after erasure" + ^ +one error found diff --git a/test/files/neg/t9286c.scala b/test/files/neg/t9286c.scala new file mode 100644 index 0000000000..3df08dcfe6 --- /dev/null +++ b/test/files/neg/t9286c.scala @@ -0,0 +1,14 @@ +class M[_] +trait T { + def foo(m: M[_ >: String]) = 42 +} + +object Test { + def t: T = new T { + def foo(m: M[_ >: Any]) = 0 // Expected: "same type after erasure" + } + def main(args: Array[String]): Unit = { + val m: M[String] = null + t.foo(m) // VeriyError: Duplicate method name&signature + } +} diff --git a/src/intellij/test/files/neg/virtpatmat_exhaust_big.check b/test/files/neg/virtpatmat_exhaust_big.check index fddc85a362..fddc85a362 100644 --- a/src/intellij/test/files/neg/virtpatmat_exhaust_big.check +++ b/test/files/neg/virtpatmat_exhaust_big.check diff --git a/src/intellij/test/files/neg/virtpatmat_exhaust_big.flags b/test/files/neg/virtpatmat_exhaust_big.flags index b5a8748652..b5a8748652 100644 --- a/src/intellij/test/files/neg/virtpatmat_exhaust_big.flags +++ b/test/files/neg/virtpatmat_exhaust_big.flags diff --git a/src/intellij/test/files/neg/virtpatmat_exhaust_big.scala b/test/files/neg/virtpatmat_exhaust_big.scala index dd639eb56e..dd639eb56e 100644 --- a/src/intellij/test/files/neg/virtpatmat_exhaust_big.scala +++ b/test/files/neg/virtpatmat_exhaust_big.scala diff --git a/test/files/pos/t3368.flags b/test/files/pos/t3368.flags new file mode 100644 index 0000000000..cb20509902 --- /dev/null +++ b/test/files/pos/t3368.flags @@ -0,0 +1 @@ +-Ystop-after:parser diff --git a/test/files/pos/t3368.scala b/test/files/pos/t3368.scala new file mode 100644 index 0000000000..c8e861a899 --- /dev/null +++ b/test/files/pos/t3368.scala @@ -0,0 +1,5 @@ + +trait X { + // error: in XML literal: name expected, but char '!' cannot start a name + def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]> +} diff --git a/test/files/pos/t6942.flags b/test/files/pos/t6942.flags index e8fb65d50c..0f96f1f872 100644 --- a/test/files/pos/t6942.flags +++ b/test/files/pos/t6942.flags @@ -1 +1 @@ --Xfatal-warnings
\ No newline at end of file +-nowarn
\ No newline at end of file diff --git a/test/files/pos/t7815.scala b/test/files/pos/t7815.scala index 12a434c5b0..0a126f9faa 100644 --- a/test/files/pos/t7815.scala +++ b/test/files/pos/t7815.scala @@ -21,7 +21,7 @@ object Foo { object Main extends App { def mapWithFoo[A <: AnyRef, B](as: List[A])(implicit foo: Foo.Aux[A, B]) = { // Should be Eta expandable because the result type of `f` is not - // dependant on the value, it is just `B`. + // dependent on the value, it is just `B`. as map foo.f as map foo.g as map foo.m diff --git a/test/files/pos/t8359-closelim-crash.flags b/test/files/pos/t8359-closelim-crash.flags new file mode 100644 index 0000000000..49d036a887 --- /dev/null +++ b/test/files/pos/t8359-closelim-crash.flags @@ -0,0 +1 @@ +-optimize diff --git a/test/files/pos/t8359-closelim-crash.scala b/test/files/pos/t8359-closelim-crash.scala new file mode 100644 index 0000000000..1413694d10 --- /dev/null +++ b/test/files/pos/t8359-closelim-crash.scala @@ -0,0 +1,23 @@ +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/t9181.flags b/test/files/pos/t9181.flags new file mode 100644 index 0000000000..0f96f1f872 --- /dev/null +++ b/test/files/pos/t9181.flags @@ -0,0 +1 @@ +-nowarn
\ No newline at end of file diff --git a/test/files/pos/t9181.scala b/test/files/pos/t9181.scala new file mode 100644 index 0000000000..2edf6fe4a3 --- /dev/null +++ b/test/files/pos/t9181.scala @@ -0,0 +1,806 @@ +sealed trait C +case object C1 extends C +case object C2 extends C +case object C3 extends C +case object C4 extends C +case object C5 extends C +case object C6 extends C +case object C7 extends C +case object C8 extends C +case object C9 extends C +case object C10 extends C +case object C11 extends C +case object C12 extends C +case object C13 extends C +case object C14 extends C +case object C15 extends C +case object C16 extends C +case object C17 extends C +case object C18 extends C +case object C19 extends C +case object C20 extends C +case object C21 extends C +case object C22 extends C +case object C23 extends C +case object C24 extends C +case object C25 extends C +case object C26 extends C +case object C27 extends C +case object C28 extends C +case object C29 extends C +case object C30 extends C +case object C31 extends C +case object C32 extends C +case object C33 extends C +case object C34 extends C +case object C35 extends C +case object C36 extends C +case object C37 extends C +case object C38 extends C +case object C39 extends C +case object C40 extends C +case object C41 extends C +case object C42 extends C +case object C43 extends C +case object C44 extends C +case object C45 extends C +case object C46 extends C +case object C47 extends C +case object C48 extends C +case object C49 extends C +case object C50 extends C +case object C51 extends C +case object C52 extends C +case object C53 extends C +case object C54 extends C +case object C55 extends C +case object C56 extends C +case object C57 extends C +case object C58 extends C +case object C59 extends C +case object C60 extends C +case object C61 extends C +case object C62 extends C +case object C63 extends C +case object C64 extends C +case object C65 extends C +case object C66 extends C +case object C67 extends C +case object C68 extends C +case object C69 extends C +case object C70 extends C +case object C71 extends C +case object C72 extends C +case object C73 extends C +case object C74 extends C +case object C75 extends C +case object C76 extends C +case object C77 extends C +case object C78 extends C +case object C79 extends C +case object C80 extends C +case object C81 extends C +case object C82 extends C +case object C83 extends C +case object C84 extends C +case object C85 extends C +case object C86 extends C +case object C87 extends C +case object C88 extends C +case object C89 extends C +case object C90 extends C +case object C91 extends C +case object C92 extends C +case object C93 extends C +case object C94 extends C +case object C95 extends C +case object C96 extends C +case object C97 extends C +case object C98 extends C +case object C99 extends C +case object C100 extends C +case object C101 extends C +case object C102 extends C +case object C103 extends C +case object C104 extends C +case object C105 extends C +case object C106 extends C +case object C107 extends C +case object C108 extends C +case object C109 extends C +case object C110 extends C +case object C111 extends C +case object C112 extends C +case object C113 extends C +case object C114 extends C +case object C115 extends C +case object C116 extends C +case object C117 extends C +case object C118 extends C +case object C119 extends C +case object C120 extends C +case object C121 extends C +case object C122 extends C +case object C123 extends C +case object C124 extends C +case object C125 extends C +case object C126 extends C +case object C127 extends C +case object C128 extends C +case object C129 extends C +case object C130 extends C +case object C131 extends C +case object C132 extends C +case object C133 extends C +case object C134 extends C +case object C135 extends C +case object C136 extends C +case object C137 extends C +case object C138 extends C +case object C139 extends C +case object C140 extends C +case object C141 extends C +case object C142 extends C +case object C143 extends C +case object C144 extends C +case object C145 extends C +case object C146 extends C +case object C147 extends C +case object C148 extends C +case object C149 extends C +case object C150 extends C +case object C151 extends C +case object C152 extends C +case object C153 extends C +case object C154 extends C +case object C155 extends C +case object C156 extends C +case object C157 extends C +case object C158 extends C +case object C159 extends C +case object C160 extends C +case object C161 extends C +case object C162 extends C +case object C163 extends C +case object C164 extends C +case object C165 extends C +case object C166 extends C +case object C167 extends C +case object C168 extends C +case object C169 extends C +case object C170 extends C +case object C171 extends C +case object C172 extends C +case object C173 extends C +case object C174 extends C +case object C175 extends C +case object C176 extends C +case object C177 extends C +case object C178 extends C +case object C179 extends C +case object C180 extends C +case object C181 extends C +case object C182 extends C +case object C183 extends C +case object C184 extends C +case object C185 extends C +case object C186 extends C +case object C187 extends C +case object C188 extends C +case object C189 extends C +case object C190 extends C +case object C191 extends C +case object C192 extends C +case object C193 extends C +case object C194 extends C +case object C195 extends C +case object C196 extends C +case object C197 extends C +case object C198 extends C +case object C199 extends C +case object C200 extends C +case object C201 extends C +case object C202 extends C +case object C203 extends C +case object C204 extends C +case object C205 extends C +case object C206 extends C +case object C207 extends C +case object C208 extends C +case object C209 extends C +case object C210 extends C +case object C211 extends C +case object C212 extends C +case object C213 extends C +case object C214 extends C +case object C215 extends C +case object C216 extends C +case object C217 extends C +case object C218 extends C +case object C219 extends C +case object C220 extends C +case object C221 extends C +case object C222 extends C +case object C223 extends C +case object C224 extends C +case object C225 extends C +case object C226 extends C +case object C227 extends C +case object C228 extends C +case object C229 extends C +case object C230 extends C +case object C231 extends C +case object C232 extends C +case object C233 extends C +case object C234 extends C +case object C235 extends C +case object C236 extends C +case object C237 extends C +case object C238 extends C +case object C239 extends C +case object C240 extends C +case object C241 extends C +case object C242 extends C +case object C243 extends C +case object C244 extends C +case object C245 extends C +case object C246 extends C +case object C247 extends C +case object C248 extends C +case object C249 extends C +case object C250 extends C +case object C251 extends C +case object C252 extends C +case object C253 extends C +case object C254 extends C +case object C255 extends C +case object C256 extends C +case object C257 extends C +case object C258 extends C +case object C259 extends C +case object C260 extends C +case object C261 extends C +case object C262 extends C +case object C263 extends C +case object C264 extends C +case object C265 extends C +case object C266 extends C +case object C267 extends C +case object C268 extends C +case object C269 extends C +case object C270 extends C +case object C271 extends C +case object C272 extends C +case object C273 extends C +case object C274 extends C +case object C275 extends C +case object C276 extends C +case object C277 extends C +case object C278 extends C +case object C279 extends C +case object C280 extends C +case object C281 extends C +case object C282 extends C +case object C283 extends C +case object C284 extends C +case object C285 extends C +case object C286 extends C +case object C287 extends C +case object C288 extends C +case object C289 extends C +case object C290 extends C +case object C291 extends C +case object C292 extends C +case object C293 extends C +case object C294 extends C +case object C295 extends C +case object C296 extends C +case object C297 extends C +case object C298 extends C +case object C299 extends C +case object C300 extends C +case object C301 extends C +case object C302 extends C +case object C303 extends C +case object C304 extends C +case object C305 extends C +case object C306 extends C +case object C307 extends C +case object C308 extends C +case object C309 extends C +case object C310 extends C +case object C311 extends C +case object C312 extends C +case object C313 extends C +case object C314 extends C +case object C315 extends C +case object C316 extends C +case object C317 extends C +case object C318 extends C +case object C319 extends C +case object C320 extends C +case object C321 extends C +case object C322 extends C +case object C323 extends C +case object C324 extends C +case object C325 extends C +case object C326 extends C +case object C327 extends C +case object C328 extends C +case object C329 extends C +case object C330 extends C +case object C331 extends C +case object C332 extends C +case object C333 extends C +case object C334 extends C +case object C335 extends C +case object C336 extends C +case object C337 extends C +case object C338 extends C +case object C339 extends C +case object C340 extends C +case object C341 extends C +case object C342 extends C +case object C343 extends C +case object C344 extends C +case object C345 extends C +case object C346 extends C +case object C347 extends C +case object C348 extends C +case object C349 extends C +case object C350 extends C +case object C351 extends C +case object C352 extends C +case object C353 extends C +case object C354 extends C +case object C355 extends C +case object C356 extends C +case object C357 extends C +case object C358 extends C +case object C359 extends C +case object C360 extends C +case object C361 extends C +case object C362 extends C +case object C363 extends C +case object C364 extends C +case object C365 extends C +case object C366 extends C +case object C367 extends C +case object C368 extends C +case object C369 extends C +case object C370 extends C +case object C371 extends C +case object C372 extends C +case object C373 extends C +case object C374 extends C +case object C375 extends C +case object C376 extends C +case object C377 extends C +case object C378 extends C +case object C379 extends C +case object C380 extends C +case object C381 extends C +case object C382 extends C +case object C383 extends C +case object C384 extends C +case object C385 extends C +case object C386 extends C +case object C387 extends C +case object C388 extends C +case object C389 extends C +case object C390 extends C +case object C391 extends C +case object C392 extends C +case object C393 extends C +case object C394 extends C +case object C395 extends C +case object C396 extends C +case object C397 extends C +case object C398 extends C +case object C399 extends C +case object C400 extends C + +object M { + def f(c: C): Int = c match { + case C1 => 1 + case C2 => 2 + case C3 => 3 + case C4 => 4 + case C5 => 5 + case C6 => 6 + case C7 => 7 + case C8 => 8 + case C9 => 9 + case C10 => 10 + case C11 => 11 + case C12 => 12 + case C13 => 13 + case C14 => 14 + case C15 => 15 + case C16 => 16 + case C17 => 17 + case C18 => 18 + case C19 => 19 + case C20 => 20 + case C21 => 21 + case C22 => 22 + case C23 => 23 + case C24 => 24 + case C25 => 25 + case C26 => 26 + case C27 => 27 + case C28 => 28 + case C29 => 29 + case C30 => 30 + case C31 => 31 + case C32 => 32 + case C33 => 33 + case C34 => 34 + case C35 => 35 + case C36 => 36 + case C37 => 37 + case C38 => 38 + case C39 => 39 + case C40 => 40 + case C41 => 41 + case C42 => 42 + case C43 => 43 + case C44 => 44 + case C45 => 45 + case C46 => 46 + case C47 => 47 + case C48 => 48 + case C49 => 49 + case C50 => 50 + case C51 => 51 + case C52 => 52 + case C53 => 53 + case C54 => 54 + case C55 => 55 + case C56 => 56 + case C57 => 57 + case C58 => 58 + case C59 => 59 + case C60 => 60 + case C61 => 61 + case C62 => 62 + case C63 => 63 + case C64 => 64 + case C65 => 65 + case C66 => 66 + case C67 => 67 + case C68 => 68 + case C69 => 69 + case C70 => 70 + case C71 => 71 + case C72 => 72 + case C73 => 73 + case C74 => 74 + case C75 => 75 + case C76 => 76 + case C77 => 77 + case C78 => 78 + case C79 => 79 + case C80 => 80 + case C81 => 81 + case C82 => 82 + case C83 => 83 + case C84 => 84 + case C85 => 85 + case C86 => 86 + case C87 => 87 + case C88 => 88 + case C89 => 89 + case C90 => 90 + case C91 => 91 + case C92 => 92 + case C93 => 93 + case C94 => 94 + case C95 => 95 + case C96 => 96 + case C97 => 97 + case C98 => 98 + case C99 => 99 + case C100 => 100 + case C101 => 101 + case C102 => 102 + case C103 => 103 + case C104 => 104 + case C105 => 105 + case C106 => 106 + case C107 => 107 + case C108 => 108 + case C109 => 109 + case C110 => 110 + case C111 => 111 + case C112 => 112 + case C113 => 113 + case C114 => 114 + case C115 => 115 + case C116 => 116 + case C117 => 117 + case C118 => 118 + case C119 => 119 + case C120 => 120 + case C121 => 121 + case C122 => 122 + case C123 => 123 + case C124 => 124 + case C125 => 125 + case C126 => 126 + case C127 => 127 + case C128 => 128 + case C129 => 129 + case C130 => 130 + case C131 => 131 + case C132 => 132 + case C133 => 133 + case C134 => 134 + case C135 => 135 + case C136 => 136 + case C137 => 137 + case C138 => 138 + case C139 => 139 + case C140 => 140 + case C141 => 141 + case C142 => 142 + case C143 => 143 + case C144 => 144 + case C145 => 145 + case C146 => 146 + case C147 => 147 + case C148 => 148 + case C149 => 149 + case C150 => 150 + case C151 => 151 + case C152 => 152 + case C153 => 153 + case C154 => 154 + case C155 => 155 + case C156 => 156 + case C157 => 157 + case C158 => 158 + case C159 => 159 + case C160 => 160 + case C161 => 161 + case C162 => 162 + case C163 => 163 + case C164 => 164 + case C165 => 165 + case C166 => 166 + case C167 => 167 + case C168 => 168 + case C169 => 169 + case C170 => 170 + case C171 => 171 + case C172 => 172 + case C173 => 173 + case C174 => 174 + case C175 => 175 + case C176 => 176 + case C177 => 177 + case C178 => 178 + case C179 => 179 + case C180 => 180 + case C181 => 181 + case C182 => 182 + case C183 => 183 + case C184 => 184 + case C185 => 185 + case C186 => 186 + case C187 => 187 + case C188 => 188 + case C189 => 189 + case C190 => 190 + case C191 => 191 + case C192 => 192 + case C193 => 193 + case C194 => 194 + case C195 => 195 + case C196 => 196 + case C197 => 197 + case C198 => 198 + case C199 => 199 + case C200 => 200 + case C201 => 201 + case C202 => 202 + case C203 => 203 + case C204 => 204 + case C205 => 205 + case C206 => 206 + case C207 => 207 + case C208 => 208 + case C209 => 209 + case C210 => 210 + case C211 => 211 + case C212 => 212 + case C213 => 213 + case C214 => 214 + case C215 => 215 + case C216 => 216 + case C217 => 217 + case C218 => 218 + case C219 => 219 + case C220 => 220 + case C221 => 221 + case C222 => 222 + case C223 => 223 + case C224 => 224 + case C225 => 225 + case C226 => 226 + case C227 => 227 + case C228 => 228 + case C229 => 229 + case C230 => 230 + case C231 => 231 + case C232 => 232 + case C233 => 233 + case C234 => 234 + case C235 => 235 + case C236 => 236 + case C237 => 237 + case C238 => 238 + case C239 => 239 + case C240 => 240 + case C241 => 241 + case C242 => 242 + case C243 => 243 + case C244 => 244 + case C245 => 245 + case C246 => 246 + case C247 => 247 + case C248 => 248 + case C249 => 249 + case C250 => 250 + case C251 => 251 + case C252 => 252 + case C253 => 253 + case C254 => 254 + case C255 => 255 + case C256 => 256 + case C257 => 257 + case C258 => 258 + case C259 => 259 + case C260 => 260 + case C261 => 261 + case C262 => 262 + case C263 => 263 + case C264 => 264 + case C265 => 265 + case C266 => 266 + case C267 => 267 + case C268 => 268 + case C269 => 269 + case C270 => 270 + case C271 => 271 + case C272 => 272 + case C273 => 273 + case C274 => 274 + case C275 => 275 + case C276 => 276 + case C277 => 277 + case C278 => 278 + case C279 => 279 + case C280 => 280 + case C281 => 281 + case C282 => 282 + case C283 => 283 + case C284 => 284 + case C285 => 285 + case C286 => 286 + case C287 => 287 + case C288 => 288 + case C289 => 289 + case C290 => 290 + case C291 => 291 + case C292 => 292 + case C293 => 293 + case C294 => 294 + case C295 => 295 + case C296 => 296 + case C297 => 297 + case C298 => 298 + case C299 => 299 + case C300 => 300 + case C301 => 301 + case C302 => 302 + case C303 => 303 + case C304 => 304 + case C305 => 305 + case C306 => 306 + case C307 => 307 + case C308 => 308 + case C309 => 309 + case C310 => 310 + case C311 => 311 + case C312 => 312 + case C313 => 313 + case C314 => 314 + case C315 => 315 + case C316 => 316 + case C317 => 317 + case C318 => 318 + case C319 => 319 + case C320 => 320 + case C321 => 321 + case C322 => 322 + case C323 => 323 + case C324 => 324 + case C325 => 325 + case C326 => 326 + case C327 => 327 + case C328 => 328 + case C329 => 329 + case C330 => 330 + case C331 => 331 + case C332 => 332 + case C333 => 333 + case C334 => 334 + case C335 => 335 + case C336 => 336 + case C337 => 337 + case C338 => 338 + case C339 => 339 + case C340 => 340 + case C341 => 341 + case C342 => 342 + case C343 => 343 + case C344 => 344 + case C345 => 345 + case C346 => 346 + case C347 => 347 + case C348 => 348 + case C349 => 349 + case C350 => 350 + case C351 => 351 + case C352 => 352 + case C353 => 353 + case C354 => 354 + case C355 => 355 + case C356 => 356 + case C357 => 357 + case C358 => 358 + case C359 => 359 + case C360 => 360 + case C361 => 361 + case C362 => 362 + case C363 => 363 + case C364 => 364 + case C365 => 365 + case C366 => 366 + case C367 => 367 + case C368 => 368 + case C369 => 369 + case C370 => 370 + case C371 => 371 + case C372 => 372 + case C373 => 373 + case C374 => 374 + case C375 => 375 + case C376 => 376 + case C377 => 377 + case C378 => 378 + case C379 => 379 + case C380 => 380 + case C381 => 381 + case C382 => 382 + case C383 => 383 + case C384 => 384 + case C385 => 385 + case C386 => 386 + case C387 => 387 + case C388 => 388 + case C389 => 389 + case C390 => 390 + case C391 => 391 + case C392 => 392 + case C393 => 393 + case C394 => 394 + case C395 => 395 + case C396 => 396 + case C397 => 397 + case C398 => 398 + case C399 => 399 + case C400 => 400 + } +} diff --git a/test/files/pos/t9239/Declaration.scala b/test/files/pos/t9239/Declaration.scala new file mode 100644 index 0000000000..452dcc1e77 --- /dev/null +++ b/test/files/pos/t9239/Declaration.scala @@ -0,0 +1,3 @@ +class Foo[A] +trait Bar[A] extends Foo[A] +class Baz[A] extends Bar[A] diff --git a/test/files/pos/t9239/Usage.java b/test/files/pos/t9239/Usage.java new file mode 100644 index 0000000000..d1e3fb0c3e --- /dev/null +++ b/test/files/pos/t9239/Usage.java @@ -0,0 +1,15 @@ +/** + * Used to fail with: + * + * Usage.java:5: error: incompatible types: Baz<String> cannot be converted to Foo<String> + * foo(f); + * ^ + */ +public class Usage { + public Usage() { + Baz<String> f = null; + foo(f); + } + + public void foo(Foo<String> f) { }; +} diff --git a/test/files/pos/t9285.flags b/test/files/pos/t9285.flags new file mode 100644 index 0000000000..85d8eb2ba2 --- /dev/null +++ b/test/files/pos/t9285.flags @@ -0,0 +1 @@ +-Xfatal-warnings diff --git a/test/files/pos/t9285.scala b/test/files/pos/t9285.scala new file mode 100644 index 0000000000..b7146cdf1c --- /dev/null +++ b/test/files/pos/t9285.scala @@ -0,0 +1 @@ +case class C(placeholder: Unit) diff --git a/test/files/pos/t9321.scala b/test/files/pos/t9321.scala new file mode 100644 index 0000000000..ed3a816656 --- /dev/null +++ b/test/files/pos/t9321.scala @@ -0,0 +1,10 @@ +object p { + trait A { + private[p] val qualifiedPrivateMember = 1 + } + + def useQualifiedPrivate(b: Mix) = + b.qualifiedPrivateMember // allowed +} + +trait Mix extends p.A diff --git a/src/intellij/test/files/pos/virtpatmat_exhaust_big.scala b/test/files/pos/virtpatmat_exhaust_big.scala index 41aef3226e..9850933540 100644 --- a/src/intellij/test/files/pos/virtpatmat_exhaust_big.scala +++ b/test/files/pos/virtpatmat_exhaust_big.scala @@ -30,5 +30,4 @@ object Test { Z10 | Z11() | Z12 | Z13() | Z14 | Z15() | Z16 | Z17() | Z18 | Z19() => } -} -- +}
\ No newline at end of file diff --git a/test/files/run/classfile-format-51.scala b/test/files/run/classfile-format-51.scala index 24b1ee8397..7523130afa 100644 --- a/test/files/run/classfile-format-51.scala +++ b/test/files/run/classfile-format-51.scala @@ -12,7 +12,7 @@ import Opcodes._ // it runs a normal compile on the source in the 'code' field that refers to // DynamicInvoker. Any failure will be dumped to std out. // -// By it's nature the test can only work on JDK 7+ because under JDK 6 some of the +// By its nature the test can only work on JDK 7+ because under JDK 6 some of the // classes referred to by DynamicInvoker won't be available and DynamicInvoker won't // verify. So the test includes a version check that short-circuites the whole test // on JDK 6 diff --git a/test/files/run/classfile-format-52.scala b/test/files/run/classfile-format-52.scala index e12c84124c..453f61ac84 100644 --- a/test/files/run/classfile-format-52.scala +++ b/test/files/run/classfile-format-52.scala @@ -11,7 +11,7 @@ import Opcodes._ // HasDefaultMethod. Then it runs a normal compile on Scala source that extends that // interface. Any failure will be dumped to std out. // -// By it's nature the test can only work on JDK 8+ because under JDK 7- the +// By its nature the test can only work on JDK 8+ because under JDK 7- the // interface won't verify. object Test extends DirectTest { override def extraSettings: String = "-optimise -usejavacp -d " + testOutput.path + " -cp " + testOutput.path diff --git a/test/files/run/delambdafy-specialized.check b/test/files/run/delambdafy-specialized.check new file mode 100644 index 0000000000..c6903b9e29 --- /dev/null +++ b/test/files/run/delambdafy-specialized.check @@ -0,0 +1 @@ +scala.runtime.AbstractFunction1$mcII$sp diff --git a/test/files/run/delambdafy-specialized.flags b/test/files/run/delambdafy-specialized.flags new file mode 100644 index 0000000000..48b438ddf8 --- /dev/null +++ b/test/files/run/delambdafy-specialized.flags @@ -0,0 +1 @@ +-Ydelambdafy:method diff --git a/test/files/run/delambdafy-specialized.scala b/test/files/run/delambdafy-specialized.scala new file mode 100644 index 0000000000..634d4e490b --- /dev/null +++ b/test/files/run/delambdafy-specialized.scala @@ -0,0 +1,6 @@ +object Test { + def main(args: Array[String]): Unit = { + val f = (x: Int) => -x + println(f.getClass.getSuperclass.getName) + } +} diff --git a/test/files/run/delambdafy_t6028.check b/test/files/run/delambdafy_t6028.check index 7bd8cd7202..419e7043a3 100644 --- a/test/files/run/delambdafy_t6028.check +++ b/test/files/run/delambdafy_t6028.check @@ -1,35 +1,35 @@ [[syntax trees at end of lambdalift]] // newSource1.scala package <empty> { class T extends Object { - <paramaccessor> private[this] val classParam: Int = _; - def <init>(classParam: Int): T = { + <paramaccessor> private[this] val classParam: String = _; + def <init>(classParam: String): T = { T.super.<init>(); () }; - private[this] val field: Int = 0; - <stable> <accessor> def field(): Int = T.this.field; - def foo(methodParam: Int): Function0 = { - val methodLocal: Int = 0; + private[this] val field: String = ""; + <stable> <accessor> def field(): String = T.this.field; + def foo(methodParam: String): Function0 = { + val methodLocal: String = ""; { (() => T.this.$anonfun$1(methodParam, methodLocal)).$asInstanceOf[Function0]() } }; - def bar(barParam: Int): Object = { + def bar(barParam: String): Object = { @volatile var MethodLocalObject$module: runtime.VolatileObjectRef = scala.runtime.VolatileObjectRef.zero(); T.this.MethodLocalObject$1(barParam, MethodLocalObject$module) }; - def tryy(tryyParam: Int): Function0 = { - var tryyLocal: runtime.IntRef = scala.runtime.IntRef.create(0); + def tryy(tryyParam: String): Function0 = { + var tryyLocal: runtime.ObjectRef = scala.runtime.ObjectRef.create(""); { - (() => T.this.$anonfun$2(tryyParam, tryyLocal)).$asInstanceOf[Function0]() + (new <$anon: Function0>(T.this, tryyParam, tryyLocal): Function0) } }; - final <artifact> private[this] def $anonfun$1(methodParam$1: Int, methodLocal$1: Int): Int = T.this.classParam.+(T.this.field()).+(methodParam$1).+(methodLocal$1); + final <artifact> private[this] def $anonfun$1(methodParam$1: String, methodLocal$1: String): String = T.this.classParam.+(T.this.field()).+(methodParam$1).+(methodLocal$1); abstract trait MethodLocalTrait$1 extends Object { <synthetic> <stable> <artifact> def $outer(): T }; object MethodLocalObject$2 extends Object with T#MethodLocalTrait$1 { - def <init>($outer: T, barParam$1: Int): T#MethodLocalObject$2.type = { + def <init>($outer: T, barParam$1: String): T#MethodLocalObject$2.type = { MethodLocalObject$2.super.<init>(); MethodLocalObject$2.this.$asInstanceOf[T#MethodLocalTrait$1$class]()./*MethodLocalTrait$1$class*/$init$(barParam$1); () @@ -38,19 +38,34 @@ package <empty> { <synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer; <synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer }; - final <stable> private[this] def MethodLocalObject$1(barParam$1: Int, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = { + final <stable> private[this] def MethodLocalObject$1(barParam$1: String, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = { MethodLocalObject$module$1.elem = new T#MethodLocalObject$2.type(T.this, barParam$1); MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type]() }; abstract trait MethodLocalTrait$1$class extends Object with T#MethodLocalTrait$1 { - def /*MethodLocalTrait$1$class*/$init$(barParam$1: Int): Unit = { + def /*MethodLocalTrait$1$class*/$init$(barParam$1: String): Unit = { () }; - scala.this.Predef.print(scala.Int.box(barParam$1)) + scala.this.Predef.print(barParam$1) }; - final <artifact> private[this] def $anonfun$2(tryyParam$1: Int, tryyLocal$1: runtime.IntRef): Unit = try { - tryyLocal$1.elem = tryyParam$1 - } finally () + @SerialVersionUID(value = 0) final <synthetic> class $anonfun$tryy$1 extends scala.runtime.AbstractFunction0$mcV$sp with Serializable { + def <init>($outer: T, tryyParam$1: String, tryyLocal$1: runtime.ObjectRef): <$anon: Function0> = { + $anonfun$tryy$1.super.<init>(); + () + }; + final def apply(): Unit = $anonfun$tryy$1.this.apply$mcV$sp(); + <specialized> def apply$mcV$sp(): Unit = try { + $anonfun$tryy$1.this.tryyLocal$1.elem = $anonfun$tryy$1.this.tryyParam$1 + } finally (); + <synthetic> <paramaccessor> <artifact> private[this] val $outer: T = _; + <synthetic> <stable> <artifact> def $outer(): T = $anonfun$tryy$1.this.$outer; + final <bridge> <artifact> def apply(): Object = { + $anonfun$tryy$1.this.apply(); + scala.runtime.BoxedUnit.UNIT + }; + <synthetic> <paramaccessor> private[this] val tryyParam$1: String = _; + <synthetic> <paramaccessor> private[this] val tryyLocal$1: runtime.ObjectRef = _ + } } } diff --git a/test/files/run/delambdafy_t6028.scala b/test/files/run/delambdafy_t6028.scala index 0b7ef48c3d..ca39195310 100644 --- a/test/files/run/delambdafy_t6028.scala +++ b/test/files/run/delambdafy_t6028.scala @@ -5,11 +5,11 @@ object Test extends DirectTest { override def extraSettings: String = "-usejavacp -Ydelambdafy:method -Xprint:lambdalift -d " + testOutput.path - override def code = """class T(classParam: Int) { - | val field: Int = 0 - | def foo(methodParam: Int) = {val methodLocal = 0 ; () => classParam + field + methodParam + methodLocal } - | def bar(barParam: Int) = { trait MethodLocalTrait { print(barParam) }; object MethodLocalObject extends MethodLocalTrait; MethodLocalObject } - | def tryy(tryyParam: Int) = { var tryyLocal = 0; () => try { tryyLocal = tryyParam } finally () } + override def code = """class T(classParam: String) { + | val field: String = "" + | def foo(methodParam: String) = {val methodLocal = "" ; () => classParam + field + methodParam + methodLocal } + | def bar(barParam: String) = { trait MethodLocalTrait { print(barParam) }; object MethodLocalObject extends MethodLocalTrait; MethodLocalObject } + | def tryy(tryyParam: String) = { var tryyLocal = ""; () => try { tryyLocal = tryyParam } finally () } |} |""".stripMargin.trim diff --git a/test/files/run/delambdafy_t6555.check b/test/files/run/delambdafy_t6555.check index 6b174c0d2a..b6ccebde78 100644 --- a/test/files/run/delambdafy_t6555.check +++ b/test/files/run/delambdafy_t6555.check @@ -5,11 +5,11 @@ package <empty> { Foo.super.<init>(); () }; - private[this] val f: Int => Int = { - final <artifact> def $anonfun(param: Int): Int = param; - ((param: Int) => $anonfun(param)) + private[this] val f: String => String = { + final <artifact> def $anonfun(param: String): String = param; + ((param: String) => $anonfun(param)) }; - <stable> <accessor> def f(): Int => Int = Foo.this.f + <stable> <accessor> def f(): String => String = Foo.this.f } } diff --git a/test/files/run/delambdafy_t6555.scala b/test/files/run/delambdafy_t6555.scala index a1dcfe790c..8d4976e989 100644 --- a/test/files/run/delambdafy_t6555.scala +++ b/test/files/run/delambdafy_t6555.scala @@ -5,7 +5,7 @@ object Test extends DirectTest { override def extraSettings: String = "-usejavacp -Xprint:specialize -Ydelambdafy:method -d " + testOutput.path - override def code = "class Foo { val f = (param: Int) => param } " + override def code = "class Foo { val f = (param: String) => param } " override def show(): Unit = { Console.withErr(System.out) { diff --git a/test/files/run/delambdafy_uncurry_byname_method.check b/test/files/run/delambdafy_uncurry_byname_method.check index cd3edc7d6f..e0f281b1cd 100644 --- a/test/files/run/delambdafy_uncurry_byname_method.check +++ b/test/files/run/delambdafy_uncurry_byname_method.check @@ -5,9 +5,9 @@ package <empty> { Foo.super.<init>(); () }; - def bar(x: () => Int): Int = x.apply(); - def foo(): Int = Foo.this.bar({ - final <artifact> def $anonfun(): Int = 1; + def bar(x: () => String): String = x.apply(); + def foo(): String = Foo.this.bar({ + final <artifact> def $anonfun(): String = ""; (() => $anonfun()) }) } diff --git a/test/files/run/delambdafy_uncurry_byname_method.scala b/test/files/run/delambdafy_uncurry_byname_method.scala index 1adeec8433..0ccc1f2e92 100644 --- a/test/files/run/delambdafy_uncurry_byname_method.scala +++ b/test/files/run/delambdafy_uncurry_byname_method.scala @@ -6,9 +6,9 @@ object Test extends DirectTest { override def extraSettings: String = "-usejavacp -Xprint:uncurry -Ydelambdafy:method -Ystop-after:uncurry -d " + testOutput.path override def code = """class Foo { - | def bar(x: => Int) = x + | def bar(x: => String) = x | - | def foo = bar(1) + | def foo = bar("") |} |""".stripMargin.trim diff --git a/test/files/run/disable-assertions.flags b/test/files/run/disable-assertions.flags new file mode 100644 index 0000000000..afaa521a12 --- /dev/null +++ b/test/files/run/disable-assertions.flags @@ -0,0 +1 @@ +-Xdisable-assertions diff --git a/test/files/run/disable-assertions.scala b/test/files/run/disable-assertions.scala new file mode 100644 index 0000000000..7ec4cfb495 --- /dev/null +++ b/test/files/run/disable-assertions.scala @@ -0,0 +1,14 @@ + +object Elided { + import annotation._, elidable._ + @elidable(INFO) def info(): Boolean = true + @elidable(10000) def f(): Boolean = true + def g(): Boolean = { assert(false); true } +} + +object Test extends App { + import Elided._ + if (info()) println("Bad info.") + if (!f()) println("Elided f.") + if (!g()) println("Elided g?") // assert should be off +} diff --git a/test/files/run/function-null-unbox.scala b/test/files/run/function-null-unbox.scala new file mode 100644 index 0000000000..6c0369fffd --- /dev/null +++ b/test/files/run/function-null-unbox.scala @@ -0,0 +1,8 @@ +object Test { + def main(args: Array[String]): Unit = { + val i2s = (x: Int) => "" + assert(i2s.asInstanceOf[AnyRef => String].apply(null) == "") + val i2i = (x: Int) => x + 1 + assert(i2i.asInstanceOf[AnyRef => Int].apply(null) == 1) + } +} diff --git a/test/files/run/indylambda-boxing/VC.scala b/test/files/run/indylambda-boxing/VC.scala new file mode 100644 index 0000000000..ef867a3658 --- /dev/null +++ b/test/files/run/indylambda-boxing/VC.scala @@ -0,0 +1,2 @@ + +class VC(private val i: Int) extends AnyVal diff --git a/test/files/run/indylambda-boxing/test.scala b/test/files/run/indylambda-boxing/test.scala new file mode 100644 index 0000000000..cc0a460640 --- /dev/null +++ b/test/files/run/indylambda-boxing/test.scala @@ -0,0 +1,29 @@ +class Capture +class Test { + def test1 = (i: Int) => "" + def test2 = (i: VC) => i + def test3 = (i: Int) => i + + def test4 = {val c = new Capture; (i: Int) => {(c, Test.this.toString); 42} } + def test5 = {val c = new Capture; (i: VC) => (c, Test.this.toString) } + def test6 = {val c = new Capture; (i: Int) => (c, Test.this.toString) } + + def test7 = {val vc = new Capture; (i: Int) => vc } + def test8 = {val c = 42; (s: String) => (s, c)} + def test9 = {val c = 42; (s: String) => ()} +} + +object Test { + def main(args: Array[String]): Unit = { + val t = new Test + assert(t.test1.apply(42) == "") + assert(t.test2.apply(new VC(42)) == new VC(42)) + assert(t.test3.apply(-1) == -1) + t.test4.apply(0) + t.test5.apply(new VC(42)) + t.test6.apply(42) + t.test7.apply(0) + t.test8.apply("") + t.test9.apply("") + } +} diff --git a/test/files/run/lambda-serialization-gc.scala b/test/files/run/lambda-serialization-gc.scala new file mode 100644 index 0000000000..8fa0b4b402 --- /dev/null +++ b/test/files/run/lambda-serialization-gc.scala @@ -0,0 +1,40 @@ +import java.io._ + +import java.net.URLClassLoader + +class C { + def serializeDeserialize[T <: AnyRef](obj: T) = { + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray)) + in.readObject.asInstanceOf[T] + } + + serializeDeserialize((c: String) => c.length) +} + +object Test { + def main(args: Array[String]): Unit = { + test() + } + + def test(): Unit = { + val loader = getClass.getClassLoader.asInstanceOf[URLClassLoader] + val loaderCClass = classOf[C] + def deserializedInThrowawayClassloader = { + val throwawayLoader: java.net.URLClassLoader = new java.net.URLClassLoader(loader.getURLs, ClassLoader.getSystemClassLoader) { + val maxMemory = Runtime.getRuntime.maxMemory() + val junk = new Array[Byte]((maxMemory / 2).toInt) + } + val clazz = throwawayLoader.loadClass("C") + assert(clazz != loaderCClass) + clazz.newInstance() + } + (1 to 4) foreach { i => + // This would OOM by the third iteration if we leaked `throwawayLoader` during + // deserialization. + deserializedInThrowawayClassloader + } + } +} diff --git a/test/files/run/lambda-serialization.scala b/test/files/run/lambda-serialization.scala new file mode 100644 index 0000000000..46b26d7c5e --- /dev/null +++ b/test/files/run/lambda-serialization.scala @@ -0,0 +1,35 @@ +import java.io.{ByteArrayInputStream, ObjectInputStream, ObjectOutputStream, ByteArrayOutputStream} + +object Test { + def main(args: Array[String]): Unit = { + roundTrip + } + + def roundTrip(): Unit = { + val c = new Capture("Capture") + val lambda = (p: Param) => ("a", p, c) + val reconstituted1 = serializeDeserialize(lambda).asInstanceOf[Object => Any] + val p = new Param + assert(reconstituted1.apply(p) == ("a", p, c)) + val reconstituted2 = serializeDeserialize(lambda).asInstanceOf[Object => Any] + assert(reconstituted1.getClass == reconstituted2.getClass) + + val reconstituted3 = serializeDeserialize(reconstituted1) + assert(reconstituted3.apply(p) == ("a", p, c)) + + val specializedLambda = (p: Int) => List(p, c).length + assert(serializeDeserialize(specializedLambda).apply(42) == 2) + assert(serializeDeserialize(serializeDeserialize(specializedLambda)).apply(42) == 2) + } + + def serializeDeserialize[T <: AnyRef](obj: T) = { + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray)) + in.readObject.asInstanceOf[T] + } +} + +case class Capture(s: String) extends Serializable +class Param diff --git a/test/files/run/private-inline.flags b/test/files/run/private-inline.flags index 00d3643fd4..c550fdce16 100644 --- a/test/files/run/private-inline.flags +++ b/test/files/run/private-inline.flags @@ -1 +1 @@ --optimise -Yinline-warnings +-optimise -Yinline-warnings -Ybackend:GenASM diff --git a/test/files/run/reify_timeofday.scala b/test/files/run/reify_timeofday.scala index efeb81debf..4950ebfae1 100644 --- a/test/files/run/reify_timeofday.scala +++ b/test/files/run/reify_timeofday.scala @@ -6,7 +6,7 @@ object Test extends App { class DateError extends Exception /** Simulating properties in Scala - * (example 4.2.1 in ScalaReference.pdf) + * (example 4.2.1 in the Scala Language Specification) */ class TimeOfDayVar { private var h, m, s: Int = 0 @@ -39,4 +39,4 @@ object Test extends App { case e: Exception => println("Exception") } }.eval -}
\ No newline at end of file +} diff --git a/test/files/run/repl-javap-lambdas.scala b/test/files/run/repl-javap-lambdas.scala index 15e5bf6877..76a6ec8450 100644 --- a/test/files/run/repl-javap-lambdas.scala +++ b/test/files/run/repl-javap-lambdas.scala @@ -7,8 +7,8 @@ object Test extends JavapTest { def code = """ |object Betty { | List(1,2,3) count (_ % 2 != 0) - | def f = List(1,2,3) filter (_ % 2 != 0) map (_ * 2) - | def g = List(1,2,3) filter (_ % 2 == 0) map (_ * 3) map (_ + 1) + | def f = List(1,2,3) filter ((x: Any) => true) map (x => "m1") + | def g = List(1,2,3) filter ((x: Any) => true) map (x => "m1") map (x => "m2") |} |:javap -fun Betty#g """.stripMargin @@ -16,7 +16,7 @@ object Test extends JavapTest { // three anonfuns of Betty#g override def yah(res: Seq[String]) = { import PartialFunction.{ cond => when } - val r = """\s*private static final .* \$anonfun\$\d+\(.*""".r + val r = """.*final .* .*\$anonfun\$\d+\(.*""".r def filtered = res filter (when(_) { case r(_*) => true }) 3 == filtered.size } diff --git a/test/files/run/repl-serialization.check b/test/files/run/repl-serialization.check new file mode 100644 index 0000000000..eb62729f5c --- /dev/null +++ b/test/files/run/repl-serialization.check @@ -0,0 +1,25 @@ +== evaluating lines +extract: AnyRef => Unit = <function1> + evaluating x +x: Int = 0 +getX: ()Int +defined class U +y: Int = <lazy> + evaluating z + evaluating zz +defined class D +z: Int = 0 +zz: Int = 0 +defined object O +defined class A +defined type alias AA +constructing U +u: U = U +== evaluating lambda + evaluating y + evaluating O + constructing A +== reconstituting into a fresh classloader + evaluating O +== evaluating reconstituted lambda + constructing A diff --git a/test/files/run/repl-serialization.scala b/test/files/run/repl-serialization.scala new file mode 100644 index 0000000000..55b7519631 --- /dev/null +++ b/test/files/run/repl-serialization.scala @@ -0,0 +1,68 @@ +import java.io._ + +import scala.reflect.io.AbstractFile +import scala.tools.nsc.Settings +import scala.tools.nsc.interpreter.IMain +import scala.tools.nsc.util._ +import scala.reflect.internal.util.AbstractFileClassLoader + +object Test { + def main(args: Array[String]) { + run() + } + + def run(): Unit = { + val settings = new Settings() + settings.Yreplclassbased.value = true + settings.usejavacp.value = true + + var imain: IMain = null + object extract extends ((AnyRef) => Unit) with Serializable { + var value: AnyRef = null + + def apply(a: AnyRef) = value = a + } + + val code = + """val x = {println(" evaluating x"); 0 } + |def getX() = x + |class U extends Serializable { println("constructing U"); val x = 0 ; override def toString = "U" } + |lazy val y = {println(" evaluating y"); 0 } + |class D; val z = {println(" evaluating z"); 0}; val zz = {println(" evaluating zz"); 0} + |object O extends Serializable { val apply = {println(" evaluating O"); 0} } + |class A(i: Int) { println(" constructing A") } + |type AA = A + |val u = new U() + |extract(() => new AA(x + getX() + y + z + zz + O.apply + u.x)) + """.stripMargin + + imain = new IMain(settings) + println("== evaluating lines") + imain.directBind("extract", "(AnyRef => Unit)", extract) + code.lines.foreach(imain.interpret) + + val virtualFile: AbstractFile = extract.value.getClass.getClassLoader.asInstanceOf[AbstractFileClassLoader].root + val newLoader = new AbstractFileClassLoader(virtualFile, getClass.getClassLoader) + + def deserializeInNewLoader(string: Array[Byte]): AnyRef = { + val bis = new ByteArrayInputStream(string) + val in = new ObjectInputStream(bis) { + override def resolveClass(desc: ObjectStreamClass) = Class.forName(desc.getName, false, newLoader) + } + in.readObject() + } + def serialize(o: AnyRef): Array[Byte] = { + val bos = new ByteArrayOutputStream() + val out = new ObjectOutputStream(bos) + out.writeObject(o) + out.close() + bos.toByteArray + } + println("== evaluating lambda") + extract.value.asInstanceOf[() => Any].apply() + println("== reconstituting into a fresh classloader") + val reconstituted = deserializeInNewLoader(serialize(extract.value)).asInstanceOf[() => Any] + println("== evaluating reconstituted lambda") + reconstituted.apply() // should not print("evaluating x") a second time + } +} diff --git a/test/files/run/synchronized.check b/test/files/run/synchronized.check index 9add05ea0c..dd9f4ef424 100644 --- a/test/files/run/synchronized.check +++ b/test/files/run/synchronized.check @@ -1,8 +1,3 @@ -#partest !-Ybackend:GenBCode -warning: there were 14 inliner warnings; re-run with -Yinline-warnings for details -#partest -Ybackend:GenBCode -warning: there were 14 inliner warnings; re-run with -Yopt-warnings for details -#partest .|. c1.f1: OK .|. c1.fi: OK .|... c1.fv: OK diff --git a/test/files/run/synchronized.scala b/test/files/run/synchronized.scala index 1f0e32992b..077e9d02e8 100644 --- a/test/files/run/synchronized.scala +++ b/test/files/run/synchronized.scala @@ -1,3 +1,6 @@ +/* + * filter: inliner warnings; re-run with + */ import java.lang.Thread.holdsLock import scala.collection.mutable.StringBuilder diff --git a/test/files/run/t2318.scala b/test/files/run/t2318.scala index b638c433f5..4239c017b8 100644 --- a/test/files/run/t2318.scala +++ b/test/files/run/t2318.scala @@ -11,6 +11,7 @@ object Test { case _: java.io.FilePermission => () case x: java.security.SecurityPermission if x.getName contains ".networkaddress." => () // generality ftw case x: java.util.PropertyPermission if x.getName == "sun.net.inetaddr.ttl" => () + case _: java.lang.reflect.ReflectPermission => () // needed for LambdaMetaFactory case _ => super.checkPermission(perm) } } diff --git a/test/files/run/t3368-b.check b/test/files/run/t3368-b.check new file mode 100644 index 0000000000..4cbe98c577 --- /dev/null +++ b/test/files/run/t3368-b.check @@ -0,0 +1,89 @@ +[[syntax trees at end of parser]] // newSource1.scala +package <empty> { + abstract trait X extends scala.AnyRef { + def $init$() = { + () + }; + def x = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye")); + $buf.$amp$plus(new _root_.scala.xml.PCData("red & black")); + $buf + } + }; + abstract trait Y extends scala.AnyRef { + def $init$() = { + () + }; + def y = { + { + new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("start")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("world")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("stuff")); + $buf.$amp$plus(new _root_.scala.xml.PCData("red & black")); + $buf + }: _*)) + } + } + }; + abstract trait Z extends scala.AnyRef { + def $init$() = { + () + }; + def d = new _root_.scala.xml.PCData("hello, world"); + def e = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }; + def f = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("x")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + }; + def g = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + }; + def h = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + } + } +} + diff --git a/test/files/run/t3368-b.scala b/test/files/run/t3368-b.scala new file mode 100644 index 0000000000..108cb9a5ee --- /dev/null +++ b/test/files/run/t3368-b.scala @@ -0,0 +1,26 @@ + +import scala.tools.partest.ParserTest + + +object Test extends ParserTest { + + override def code = """ + trait X { + // error: in XML literal: name expected, but char '!' cannot start a name + def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]> + } + trait Y { + def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a> + } + trait Z { + def d = <![CDATA[hello, world]]> + def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced + def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text + def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing + def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo> + } + """ + + // not coalescing + override def extraSettings = s"${super.extraSettings} -Xxml:-coalescing" +} diff --git a/test/files/run/t3368-c.check b/test/files/run/t3368-c.check new file mode 100644 index 0000000000..e0c10cc0dd --- /dev/null +++ b/test/files/run/t3368-c.check @@ -0,0 +1,85 @@ +[[syntax trees at end of parser]] // newSource1.scala +package <empty> { + abstract trait X extends scala.AnyRef { + def $init$() = { + () + }; + def x = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hi & bye")); + $buf.$amp$plus(new _root_.scala.xml.Text("red & black")); + $buf + } + }; + abstract trait Y extends scala.AnyRef { + def $init$() = { + () + }; + def y = { + { + new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("starthi & bye")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("world")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("stuffred & black")); + $buf + }: _*)) + } + } + }; + abstract trait Z extends scala.AnyRef { + def $init$() = { + () + }; + def d = new _root_.scala.xml.Text("hello, world"); + def e = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf + }; + def f = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("xhello, world")); + $buf + }: _*)) + } + }; + def g = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf + }: _*)) + } + }; + def h = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, worldhello, world")); + $buf + }: _*)) + } + } + } +} + diff --git a/test/files/run/t3368-c.scala b/test/files/run/t3368-c.scala new file mode 100644 index 0000000000..5121794463 --- /dev/null +++ b/test/files/run/t3368-c.scala @@ -0,0 +1,26 @@ + +import scala.tools.partest.ParserTest + + +object Test extends ParserTest { + + override def code = """ + trait X { + // error: in XML literal: name expected, but char '!' cannot start a name + def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]> + } + trait Y { + def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a> + } + trait Z { + def d = <![CDATA[hello, world]]> + def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced + def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text + def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing + def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo> + } + """ + + // default coalescing behavior, whatever that is today. + //override def extraSettings = s"${super.extraSettings} -Xxml:coalescing" +} diff --git a/test/files/run/t3368-d.check b/test/files/run/t3368-d.check new file mode 100644 index 0000000000..4cbe98c577 --- /dev/null +++ b/test/files/run/t3368-d.check @@ -0,0 +1,89 @@ +[[syntax trees at end of parser]] // newSource1.scala +package <empty> { + abstract trait X extends scala.AnyRef { + def $init$() = { + () + }; + def x = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye")); + $buf.$amp$plus(new _root_.scala.xml.PCData("red & black")); + $buf + } + }; + abstract trait Y extends scala.AnyRef { + def $init$() = { + () + }; + def y = { + { + new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("start")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("world")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("stuff")); + $buf.$amp$plus(new _root_.scala.xml.PCData("red & black")); + $buf + }: _*)) + } + } + }; + abstract trait Z extends scala.AnyRef { + def $init$() = { + () + }; + def d = new _root_.scala.xml.PCData("hello, world"); + def e = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }; + def f = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("x")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + }; + def g = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + }; + def h = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + } + } +} + diff --git a/test/files/run/t3368-d.scala b/test/files/run/t3368-d.scala new file mode 100644 index 0000000000..5777c1a81e --- /dev/null +++ b/test/files/run/t3368-d.scala @@ -0,0 +1,26 @@ + +import scala.tools.partest.ParserTest + + +object Test extends ParserTest { + + override def code = """ + trait X { + // error: in XML literal: name expected, but char '!' cannot start a name + def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]> + } + trait Y { + def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a> + } + trait Z { + def d = <![CDATA[hello, world]]> + def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced + def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text + def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing + def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo> + } + """ + + // default under 2.12 is not coalescing + override def extraSettings = s"${super.extraSettings} -Xsource:212" +} diff --git a/test/files/run/t3368.check b/test/files/run/t3368.check new file mode 100644 index 0000000000..e0c10cc0dd --- /dev/null +++ b/test/files/run/t3368.check @@ -0,0 +1,85 @@ +[[syntax trees at end of parser]] // newSource1.scala +package <empty> { + abstract trait X extends scala.AnyRef { + def $init$() = { + () + }; + def x = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hi & bye")); + $buf.$amp$plus(new _root_.scala.xml.Text("red & black")); + $buf + } + }; + abstract trait Y extends scala.AnyRef { + def $init$() = { + () + }; + def y = { + { + new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("starthi & bye")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("world")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("stuffred & black")); + $buf + }: _*)) + } + } + }; + abstract trait Z extends scala.AnyRef { + def $init$() = { + () + }; + def d = new _root_.scala.xml.Text("hello, world"); + def e = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf + }; + def f = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("xhello, world")); + $buf + }: _*)) + } + }; + def g = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf + }: _*)) + } + }; + def h = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, worldhello, world")); + $buf + }: _*)) + } + } + } +} + diff --git a/test/files/run/t3368.scala b/test/files/run/t3368.scala new file mode 100644 index 0000000000..284fed0784 --- /dev/null +++ b/test/files/run/t3368.scala @@ -0,0 +1,26 @@ + +import scala.tools.partest.ParserTest + + +object Test extends ParserTest { + + override def code = """ + trait X { + // error: in XML literal: name expected, but char '!' cannot start a name + def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]> + } + trait Y { + def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a> + } + trait Z { + def d = <![CDATA[hello, world]]> + def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced + def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text + def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing + def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo> + } + """ + + // coalescing + override def extraSettings = s"${super.extraSettings} -Xxml:coalescing" +} diff --git a/test/files/run/t5699.scala b/test/files/run/t5699.scala index ec3b1d26b4..409bcd250c 100755 --- a/test/files/run/t5699.scala +++ b/test/files/run/t5699.scala @@ -1,21 +1,13 @@ -import scala.tools.partest.DirectTest +import scala.tools.partest.ParserTest import scala.reflect.internal.util.BatchSourceFile -object Test extends DirectTest { +object Test extends ParserTest { // Java code override def code = """ |public @interface MyAnnotation { String value(); } """.stripMargin - override def extraSettings: String = "-usejavacp -Ystop-after:typer -Xprint:parser" - - override def show(): Unit = { - // redirect err to out, for logging - val prevErr = System.err - System.setErr(System.out) - compile() - System.setErr(prevErr) - } + override def extraSettings: String = "-usejavacp -Ystop-after:namer -Xprint:parser" override def newSources(sourceCodes: String*) = { assert(sourceCodes.size == 1) diff --git a/test/files/run/t6102.check b/test/files/run/t6102.check index aa3e6cc9e2..07378f5ed4 100644 --- a/test/files/run/t6102.check +++ b/test/files/run/t6102.check @@ -28,5 +28,10 @@ [running phase constopt on t6102.scala] #partest [running phase dce on t6102.scala] +#partest !-Ybackend:GenBCode [running phase jvm on icode] +#partest -Ybackend:GenBCode +[running phase jvm on t6102.scala] +[running phase jvm on t6102.scala] +#partest hello diff --git a/test/files/run/t7407.flags b/test/files/run/t7407.flags index be4ef0798a..ffc65f4b81 100644 --- a/test/files/run/t7407.flags +++ b/test/files/run/t7407.flags @@ -1 +1 @@ --Ynooptimise -Yopt:l:none -Ybackend:GenBCode +-Yopt:l:none -Ybackend:GenBCode diff --git a/test/files/run/t7407b.flags b/test/files/run/t7407b.flags index c8547a27dc..c30091d3de 100644 --- a/test/files/run/t7407b.flags +++ b/test/files/run/t7407b.flags @@ -1 +1 @@ --Ynooptimise -Ybackend:GenBCode +-Ybackend:GenBCode diff --git a/test/files/run/t7741a/GroovyInterface$1Dump.java b/test/files/run/t7741a/GroovyInterface$1Dump.java new file mode 100644 index 0000000000..0c0eab3f1b --- /dev/null +++ b/test/files/run/t7741a/GroovyInterface$1Dump.java @@ -0,0 +1,222 @@ +import java.util.*; +import scala.tools.asm.*; + +// generated with +// git clone alewando/scala_groovy_interop +// SCALA_HOME=... GROOVY_HOME=... ant +// cd /code/scala2 +// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1' +// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1' +public class GroovyInterface$1Dump implements Opcodes { + + public static byte[] dump () throws Exception { + + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(V1_5, ACC_SUPER + ACC_SYNTHETIC, "GroovyInterface$1", null, "java/lang/Object", new String[] {}); + + cw.visitInnerClass("GroovyInterface$1", "GroovyInterface", "1", ACC_SYNTHETIC); + + { + fv = cw.visitField(ACC_STATIC + ACC_SYNTHETIC, "$class$GroovyInterface", "Ljava/lang/Class;", null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$staticClassInfo", "Lorg/codehaus/groovy/reflection/ClassInfo;", null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(ACC_PUBLIC + ACC_STATIC + ACC_TRANSIENT + ACC_SYNTHETIC, "__$stMC", "Z", null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(ACC_PRIVATE + ACC_TRANSIENT + ACC_SYNTHETIC, "metaClass", "Lgroovy/lang/MetaClass;", null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$callSiteArray", "Ljava/lang/ref/SoftReference;", null, null); + fv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); + mv.visitMethodInsn(INVOKESTATIC, "GroovyInterface$1", "$getCallSiteArray", "()[Lorg/codehaus/groovy/runtime/callsite/CallSite;", false); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitVarInsn(ASTORE, 2); + mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(SWAP); + mv.visitFieldInsn(PUTFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;"); + mv.visitVarInsn(ALOAD, 2); + mv.visitInsn(POP); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PROTECTED + ACC_SYNTHETIC, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); + mv.visitLdcInsn(Type.getType("LGroovyInterface$1;")); + Label l0 = new Label(); + mv.visitJumpInsn(IF_ACMPEQ, l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/ScriptBytecodeAdapter", "initMetaClass", "(Ljava/lang/Object;)Lgroovy/lang/MetaClass;", false); + mv.visitInsn(ARETURN); + mv.visitLabel(l0); + mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$staticClassInfo", "Lorg/codehaus/groovy/reflection/ClassInfo;"); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + Label l1 = new Label(); + mv.visitJumpInsn(IFNONNULL, l1); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); + mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/reflection/ClassInfo", "getClassInfo", "(Ljava/lang/Class;)Lorg/codehaus/groovy/reflection/ClassInfo;", false); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 1); + mv.visitFieldInsn(PUTSTATIC, "GroovyInterface$1", "$staticClassInfo", "Lorg/codehaus/groovy/reflection/ClassInfo;"); + mv.visitLabel(l1); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEVIRTUAL, "org/codehaus/groovy/reflection/ClassInfo", "getMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitInsn(ARETURN); + mv.visitMaxs(2, 2); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "getMetaClass", "()Lgroovy/lang/MetaClass;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;"); + mv.visitInsn(DUP); + Label l0 = new Label(); + mv.visitJumpInsn(IFNULL, l0); + mv.visitInsn(ARETURN); + mv.visitLabel(l0); + mv.visitInsn(POP); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitFieldInsn(PUTFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;"); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;"); + mv.visitInsn(ARETURN); + mv.visitMaxs(2, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "setMetaClass", "(Lgroovy/lang/MetaClass;)V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitFieldInsn(PUTFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;"); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 2); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "invokeMethod", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "getMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "invokeMethod", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", true); + mv.visitInsn(ARETURN); + mv.visitMaxs(4, 3); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "getProperty", "(Ljava/lang/String;)Ljava/lang/Object;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "getMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "getProperty", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", true); + mv.visitInsn(ARETURN); + mv.visitMaxs(3, 2); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "setProperty", "(Ljava/lang/String;Ljava/lang/Object;)V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "getMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "setProperty", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", true); + mv.visitInsn(RETURN); + mv.visitMaxs(4, 3); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); + mv.visitCode(); + mv.visitLdcInsn(Type.getType("LGroovyInterface;")); + mv.visitVarInsn(ASTORE, 0); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(PUTSTATIC, "GroovyInterface$1", "$class$GroovyInterface", "Ljava/lang/Class;"); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(POP); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$createCallSiteArray", "()Lorg/codehaus/groovy/runtime/callsite/CallSiteArray;", null, null); + mv.visitCode(); + mv.visitLdcInsn(new Integer(0)); + mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); + mv.visitVarInsn(ASTORE, 0); + mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/callsite/CallSiteArray"); + mv.visitInsn(DUP); + mv.visitLdcInsn(Type.getType("LGroovyInterface$1;")); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/callsite/CallSiteArray", "<init>", "(Ljava/lang/Class;[Ljava/lang/String;)V", false); + mv.visitInsn(ARETURN); + mv.visitMaxs(4, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC + ACC_SYNTHETIC, "$getCallSiteArray", "()[Lorg/codehaus/groovy/runtime/callsite/CallSite;", null, null); + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$callSiteArray", "Ljava/lang/ref/SoftReference;"); + Label l0 = new Label(); + mv.visitJumpInsn(IFNULL, l0); + mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$callSiteArray", "Ljava/lang/ref/SoftReference;"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ref/SoftReference", "get", "()Ljava/lang/Object;", false); + mv.visitTypeInsn(CHECKCAST, "org/codehaus/groovy/runtime/callsite/CallSiteArray"); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 0); + Label l1 = new Label(); + mv.visitJumpInsn(IFNONNULL, l1); + mv.visitLabel(l0); + mv.visitMethodInsn(INVOKESTATIC, "GroovyInterface$1", "$createCallSiteArray", "()Lorg/codehaus/groovy/runtime/callsite/CallSiteArray;", false); + mv.visitVarInsn(ASTORE, 0); + mv.visitTypeInsn(NEW, "java/lang/ref/SoftReference"); + mv.visitInsn(DUP); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/ref/SoftReference", "<init>", "(Ljava/lang/Object;)V", false); + mv.visitFieldInsn(PUTSTATIC, "GroovyInterface$1", "$callSiteArray", "Ljava/lang/ref/SoftReference;"); + mv.visitLabel(l1); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, "org/codehaus/groovy/runtime/callsite/CallSiteArray", "array", "[Lorg/codehaus/groovy/runtime/callsite/CallSite;"); + mv.visitInsn(ARETURN); + mv.visitMaxs(3, 1); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } +} diff --git a/test/files/run/t7741a/GroovyInterfaceDump.java b/test/files/run/t7741a/GroovyInterfaceDump.java new file mode 100644 index 0000000000..87c09e272f --- /dev/null +++ b/test/files/run/t7741a/GroovyInterfaceDump.java @@ -0,0 +1,51 @@ +import java.util.*; +import scala.tools.asm.*; + +// generated with +// git clone alewando/scala_groovy_interop +// SCALA_HOME=... GROOVY_HOME=... ant +// cd /code/scala2 +// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1' +// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1' +public class GroovyInterfaceDump implements Opcodes { + + public static byte[] dump () throws Exception { + + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(V1_5, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, "GroovyInterface", null, "java/lang/Object", null); + + cw.visitInnerClass("GroovyInterface$1", "GroovyInterface", "1", ACC_SYNTHETIC); + + cw.visitInnerClass("GroovyInterface$__clinit__closure1", null, null, 0); + + { + fv = cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "closure", "Ljava/lang/Object;", null, null); + fv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); + mv.visitCode(); + mv.visitTypeInsn(NEW, "GroovyInterface$__clinit__closure1"); + mv.visitInsn(DUP); + mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$class$GroovyInterface", "Ljava/lang/Class;"); + mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$class$GroovyInterface", "Ljava/lang/Class;"); + mv.visitMethodInsn(INVOKESPECIAL, "GroovyInterface$__clinit__closure1", "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V", false); + mv.visitVarInsn(ASTORE, 0); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(PUTSTATIC, "GroovyInterface", "closure", "Ljava/lang/Object;"); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(POP); + mv.visitInsn(RETURN); + mv.visitMaxs(4, 1); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } +} + diff --git a/test/files/run/t7741a/Test.scala b/test/files/run/t7741a/Test.scala new file mode 100644 index 0000000000..cdba1cccf8 --- /dev/null +++ b/test/files/run/t7741a/Test.scala @@ -0,0 +1,47 @@ +import java.io.{ByteArrayInputStream, FileOutputStream, BufferedOutputStream} +import java.util + +import java.io.File + +import scala.tools.partest.DirectTest + +object Test extends DirectTest { + + def code = "" + + override def show(): Unit = { + + val class1: Array[Byte] = GroovyInterfaceDump.dump() + val class2: Array[Byte] = GroovyInterface$1Dump.dump() + def writeFile(contents: Array[Byte], f: java.io.File): Unit = { + val out = new BufferedOutputStream(new FileOutputStream(f)) + try { + out.write(contents) + } finally out.close() + } + + val outdir = testOutput.jfile + + // interface GroovyInterface { + // + // // This is the line that causes scalac to choke. + // // It results in a GroovyInterface$1 class, which is a non-static inner class but its constructor does not + // // include the implicit parameter that is the immediate enclosing instance. + // // See http://jira.codehaus.org/browse/GROOVY-7312 + // // + // // Scalac error: + // // [scalac] error: error while loading 1, class file '..../scala_groovy_interop/classes/com/example/groovy/GroovyInterface$1.class' is broken + // // [scalac] (class java.util.NoSuchElementException/head of empty list) + // final static def closure = { x -> "banana" } + // + // } + writeFile(GroovyInterfaceDump.dump(), new File(outdir, "GroovyInterface.class")) + writeFile(GroovyInterface$1Dump.dump(), new File(outdir, "GroovyInterface$1.class")) + compileCode("object Test { def foo(g: GroovyInterface) = g.toString }") + } + + def compileCode(code: String) = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code) + } +} diff --git a/test/files/run/t7741b.check b/test/files/run/t7741b.check new file mode 100644 index 0000000000..a19e54aa3a --- /dev/null +++ b/test/files/run/t7741b.check @@ -0,0 +1,3 @@ +1. Don't refer to Inner +2. Refering to Inner +pos: NoPosition Class file for HasInner$Inner not found ERROR diff --git a/test/files/run/t7741b/HasInner.java b/test/files/run/t7741b/HasInner.java new file mode 100644 index 0000000000..a1d0d0d81a --- /dev/null +++ b/test/files/run/t7741b/HasInner.java @@ -0,0 +1,3 @@ +class HasInner { + class Inner {} +} diff --git a/test/files/run/t7741b/Test.scala b/test/files/run/t7741b/Test.scala new file mode 100644 index 0000000000..569ae6b679 --- /dev/null +++ b/test/files/run/t7741b/Test.scala @@ -0,0 +1,29 @@ +import java.io.File + +import scala.tools.partest.StoreReporterDirectTest + +object Test extends StoreReporterDirectTest { + + def code = "" + + override def show(): Unit = { + deleteClass("HasInner$Inner") + println("1. Don't refer to Inner") + compileCode("class Test { def test(x: HasInner) = x }") + assert(filteredInfos.isEmpty, filteredInfos) + println("2. Refering to Inner") + compileCode("class Test { def test(x: HasInner#Inner) = x }") + println(filteredInfos.mkString("\n")) + } + + def deleteClass(name: String) { + val classFile = new File(testOutput.path, name + ".class") + assert(classFile.exists) + assert(classFile.delete()) + } + + def compileCode(code: String) = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code) + } +} diff --git a/test/files/run/t7747-repl.check b/test/files/run/t7747-repl.check index 105b238d01..5f436ba6b1 100644 --- a/test/files/run/t7747-repl.check +++ b/test/files/run/t7747-repl.check @@ -112,7 +112,7 @@ scala> 55 ; ((2 + 2)) ; (1, 2, 3) res15: (Int, Int, Int) = (1,2,3) scala> 55 ; (x: Int) => x + 1 ; () => ((5)) -<console>:8: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:9: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 55 ; (x: Int) => x + 1 ;; ^ res16: () => Int = <function0> @@ -258,12 +258,12 @@ class $read extends Serializable { super.<init>; () }; - import $line44.$read.$iw.$iw.BippyBups; - import $line44.$read.$iw.$iw.BippyBups; - import $line45.$read.$iw.$iw.PuppyPups; - import $line45.$read.$iw.$iw.PuppyPups; - import $line46.$read.$iw.$iw.Bingo; - import $line46.$read.$iw.$iw.Bingo; + import $line44.$read.INSTANCE.$iw.$iw.BippyBups; + import $line44.$read.INSTANCE.$iw.$iw.BippyBups; + import $line45.$read.INSTANCE.$iw.$iw.PuppyPups; + import $line45.$read.INSTANCE.$iw.$iw.PuppyPups; + import $line46.$read.INSTANCE.$iw.$iw.Bingo; + import $line46.$read.INSTANCE.$iw.$iw.Bingo; class $iw extends Serializable { def <init>() = { super.<init>; @@ -275,12 +275,35 @@ class $read extends Serializable { }; val $iw = new $iw.<init> } -object $read extends $read { +object $read extends scala.AnyRef { def <init>() = { super.<init>; () - } + }; + val INSTANCE = new $read.<init> } res3: List[Product with Serializable] = List(BippyBups(), PuppyPups(), Bingo()) +scala> case class Sum(exp: String, exp2: String) +defined class Sum + +scala> val a = Sum("A", "B") +a: Sum = Sum(A,B) + +scala> def b(a: Sum): String = a match { case Sum(_, _) => "Found Sum" } +b: (a: Sum)String + +scala> b(a) +res4: String = Found Sum + +scala> :power +** Power User mode enabled - BEEP WHIR GYVE ** +** :phase has been set to 'typer'. ** +** scala.tools.nsc._ has been imported ** +** global._, definitions._ also imported ** +** Try :help, :vals, power.<tab> ** + +scala> intp.lastRequest +res5: $r.intp.Request = Request(line=def $ires3 = intp.global, 1 trees) + scala> :quit diff --git a/test/files/run/t7747-repl.scala b/test/files/run/t7747-repl.scala index 0e64210460..141c2d9844 100644 --- a/test/files/run/t7747-repl.scala +++ b/test/files/run/t7747-repl.scala @@ -65,5 +65,11 @@ object Test extends ReplTest { |case class PuppyPups() |case class Bingo() |List(BippyBups(), PuppyPups(), Bingo()) // show + |case class Sum(exp: String, exp2: String) + |val a = Sum("A", "B") + |def b(a: Sum): String = a match { case Sum(_, _) => "Found Sum" } + |b(a) + |:power + |intp.lastRequest |""".stripMargin } diff --git a/test/files/run/t8601-closure-elim.flags b/test/files/run/t8601-closure-elim.flags index 2b5fd8a7b2..9158076b71 100644 --- a/test/files/run/t8601-closure-elim.flags +++ b/test/files/run/t8601-closure-elim.flags @@ -1 +1 @@ --optimize -Ydelambdafy:inline +-optimize -Ydelambdafy:inline -Ybackend:GenASM diff --git a/test/files/run/t8845.flags b/test/files/run/t8845.flags index aada25f80d..c30091d3de 100644 --- a/test/files/run/t8845.flags +++ b/test/files/run/t8845.flags @@ -1 +1 @@ --Ybackend:GenBCode -Ynooptimize +-Ybackend:GenBCode diff --git a/test/files/run/t8925.flags b/test/files/run/t8925.flags index be4ef0798a..ffc65f4b81 100644 --- a/test/files/run/t8925.flags +++ b/test/files/run/t8925.flags @@ -1 +1 @@ --Ynooptimise -Yopt:l:none -Ybackend:GenBCode +-Yopt:l:none -Ybackend:GenBCode diff --git a/test/files/run/t9097.scala b/test/files/run/t9097.scala index d2bf55fc44..aa2b23bbac 100644 --- a/test/files/run/t9097.scala +++ b/test/files/run/t9097.scala @@ -15,7 +15,7 @@ object Test extends StoreReporterDirectTest { override def code = """package o |package a { | class C { - | def hihi = List(1,2).map(_ * 2) + | def hihi = List(1,2).map(_ => "") | } |} |package object a { diff --git a/test/files/run/t9252.check b/test/files/run/t9252.check new file mode 100644 index 0000000000..b00d748f7f --- /dev/null +++ b/test/files/run/t9252.check @@ -0,0 +1 @@ +class [Lscala.runtime.BoxedUnit; diff --git a/test/files/run/t9252.scala b/test/files/run/t9252.scala new file mode 100644 index 0000000000..da698948e1 --- /dev/null +++ b/test/files/run/t9252.scala @@ -0,0 +1,5 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + println(rootMirror.runtimeClass(typeOf[Array[Unit]])) +}
\ No newline at end of file diff --git a/test/files/run/t9268.check b/test/files/run/t9268.check new file mode 100644 index 0000000000..90ef940eb3 --- /dev/null +++ b/test/files/run/t9268.check @@ -0,0 +1,5 @@ +Compiling Client1 +pos: NoPosition Class Waiter not found - continuing with a stub. WARNING +Compiling Client2 +pos: NoPosition Class Waiter not found - continuing with a stub. WARNING +pos: NoPosition Unable to locate class corresponding to inner class entry for Predicate in owner Waiter ERROR diff --git a/test/files/run/t9268/Java.java b/test/files/run/t9268/Java.java new file mode 100644 index 0000000000..c9a0bec3ff --- /dev/null +++ b/test/files/run/t9268/Java.java @@ -0,0 +1,12 @@ +public class Java { +} + +class Partial { + public <E extends java.lang.Exception> long waitFor(long l, Waiter.Predicate<E> pred) throws E { + return 0L; + } +} + +class Waiter { + interface Predicate<E> {} +} diff --git a/test/files/run/t9268/Test.scala b/test/files/run/t9268/Test.scala new file mode 100644 index 0000000000..813cbe7b60 --- /dev/null +++ b/test/files/run/t9268/Test.scala @@ -0,0 +1,40 @@ +import scala.tools.partest._ +import java.io.File + +object Test extends StoreReporterDirectTest { + def code = ??? + + def compileCode(code: String) = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code) + } + + def client1 = """ + class Client1 { def p(p: Partial) = p.toString } + """ + + def client2 = """ + class Client2 { def p(p: Partial) = p.waitFor() } + """ + + def deleteClass(s: String) = { + val f = new File(testOutput.path, s + ".class") + assert(f.exists) + f.delete() + } + + def show(): Unit = { + deleteClass("Waiter") + deleteClass("Waiter$Predicate") + + // Used to crash in Java Generic Signature parsing + println("Compiling Client1") + compileCode(client1) + println(storeReporter.infos.mkString("\n")) + storeReporter.reset() + println("Compiling Client2") + compileCode(client2) + println(storeReporter.infos.mkString("\n")) + } +} + diff --git a/test/files/run/t9298/Test.java b/test/files/run/t9298/Test.java new file mode 100644 index 0000000000..81f5265985 --- /dev/null +++ b/test/files/run/t9298/Test.java @@ -0,0 +1,7 @@ +public class Test { + public void consume(VC vc) {} + + public static void main(String[] args) { + new Client().test(); + } +} diff --git a/test/files/run/t9298/VC.scala b/test/files/run/t9298/VC.scala new file mode 100644 index 0000000000..916e62dc59 --- /dev/null +++ b/test/files/run/t9298/VC.scala @@ -0,0 +1,5 @@ +class VC(val s: String) extends AnyVal + +class Client { + def test = new Test().consume(new VC("")) +} diff --git a/test/files/run/t9298b/Test.java b/test/files/run/t9298b/Test.java new file mode 100644 index 0000000000..f369b26f36 --- /dev/null +++ b/test/files/run/t9298b/Test.java @@ -0,0 +1,7 @@ +public class Test { + public VC identity(VC vc) { return vc; } + + public static void main(String[] args) { + new Client().test(); + } +} diff --git a/test/files/run/t9298b/VC.scala b/test/files/run/t9298b/VC.scala new file mode 100644 index 0000000000..bb5978b6e4 --- /dev/null +++ b/test/files/run/t9298b/VC.scala @@ -0,0 +1,8 @@ +class VC(val s: Int) extends AnyVal + +class Client { + def test = { + val vc: VC = new Test().identity(new VC(42)) + assert(vc.s == 42) + } +} diff --git a/test/files/run/valueClassSelfType.scala b/test/files/run/valueClassSelfType.scala new file mode 100644 index 0000000000..47a3764b0a --- /dev/null +++ b/test/files/run/valueClassSelfType.scala @@ -0,0 +1,52 @@ +trait T + +class V1(val l: Long) extends AnyVal { self: T => + def foo: V1 = self + def bar: T = self +} + +class V2(val l: Long) extends AnyVal { self => + def foo: V2 = self +} + +class V3(val l: Long) extends AnyVal { self: Long => + def foo: V3 = self + def bar: Long = self +} + +// non-value classes + +class C1(val l: Long) { self: T => + def foo: C1 = self + def bar: T = self +} + +class C2(val l: Long) { self => + def foo: C2 = self +} + +class C3(val l: Long) { self: Long => + def foo: C3 = self + def bar: Long = self +} + +object Test extends App { + // Rejected: superclass V1 is not a subclass of the superclass Object of the mixin trait T + // new V1(1l) with T + + assert(new V2(1l).foo.l == 1l) + + // Rejected: V3 does not conform to its self-type V3 with Long + // new V3(1l) + + val c2 = new C1(2l) with T + assert(c2.foo.l + c2.bar.asInstanceOf[C1].l == 4l) + + assert(new C2(3l).foo.l == 3l) + + // Rejected: C3 does not conform to its self-type C3 with Long + // new C3(4l) + + // Rejected: class Long needs to be a trait to be mixed in + // new C3(4l) with Long +} diff --git a/test/files/scalacheck/redblacktree.scala b/test/files/scalacheck/redblacktree.scala index 871444a4b8..4ded37b35a 100644 --- a/test/files/scalacheck/redblacktree.scala +++ b/test/files/scalacheck/redblacktree.scala @@ -33,7 +33,7 @@ package scala.collection.immutable.redblacktree { def mkTree(level: Int, parentIsBlack: Boolean = false, label: String = ""): Gen[Tree[String, Int]] = if (level == 0) { - value(null) + const(null) } else { for { oddOrEven <- choose(0, 2) diff --git a/test/files/scalap/t8679.check b/test/files/scalap/t8679.check new file mode 100644 index 0000000000..938b76783f --- /dev/null +++ b/test/files/scalap/t8679.check @@ -0,0 +1,3503 @@ +class T8679 extends scala.AnyRef { + def this() = { /* compiled code */ } + def foo1(): scala.Int = { /* compiled code */ } + def foo2(): scala.Int = { /* compiled code */ } + def foo3(): scala.Int = { /* compiled code */ } + def foo4(): scala.Int = { /* compiled code */ } + def foo5(): scala.Int = { /* compiled code */ } + def foo6(): scala.Int = { /* compiled code */ } + def foo7(): scala.Int = { /* compiled code */ } + def foo8(): scala.Int = { /* compiled code */ } + def foo9(): scala.Int = { /* compiled code */ } + def foo10(): scala.Int = { /* compiled code */ } + def foo11(): scala.Int = { /* compiled code */ } + def foo12(): scala.Int = { /* compiled code */ } + def foo13(): scala.Int = { /* compiled code */ } + def foo14(): scala.Int = { /* compiled code */ } + def foo15(): scala.Int = { /* compiled code */ } + def foo16(): scala.Int = { /* compiled code */ } + def foo17(): scala.Int = { /* compiled code */ } + def foo18(): scala.Int = { /* compiled code */ } + def foo19(): scala.Int = { /* compiled code */ } + def foo20(): scala.Int = { /* compiled code */ } + def foo21(): scala.Int = { /* compiled code */ } + def foo22(): scala.Int = { /* compiled code */ } + def foo23(): scala.Int = { /* compiled code */ } + def foo24(): scala.Int = { /* compiled code */ } + def foo25(): scala.Int = { /* compiled code */ } + def foo26(): scala.Int = { /* compiled code */ } + def foo27(): scala.Int = { /* compiled code */ } + def foo28(): scala.Int = { /* compiled code */ } + def foo29(): scala.Int = { /* compiled code */ } + def foo30(): scala.Int = { /* compiled code */ } + def foo31(): scala.Int = { /* compiled code */ } + def foo32(): scala.Int = { /* compiled code */ } + def foo33(): scala.Int = { /* compiled code */ } + def foo34(): scala.Int = { /* compiled code */ } + def foo35(): scala.Int = { /* compiled code */ } + def foo36(): scala.Int = { /* compiled code */ } + def foo37(): scala.Int = { /* compiled code */ } + def foo38(): scala.Int = { /* compiled code */ } + def foo39(): scala.Int = { /* compiled code */ } + def foo40(): scala.Int = { /* compiled code */ } + def foo41(): scala.Int = { /* compiled code */ } + def foo42(): scala.Int = { /* compiled code */ } + def foo43(): scala.Int = { /* compiled code */ } + def foo44(): scala.Int = { /* compiled code */ } + def foo45(): scala.Int = { /* compiled code */ } + def foo46(): scala.Int = { /* compiled code */ } + def foo47(): scala.Int = { /* compiled code */ } + def foo48(): scala.Int = { /* compiled code */ } + def foo49(): scala.Int = { /* compiled code */ } + def foo50(): scala.Int = { /* compiled code */ } + def foo51(): scala.Int = { /* compiled code */ } + def foo52(): scala.Int = { /* compiled code */ } + def foo53(): scala.Int = { /* compiled code */ } + def foo54(): scala.Int = { /* compiled code */ } + def foo55(): scala.Int = { /* compiled code */ } + def foo56(): scala.Int = { /* compiled code */ } + def foo57(): scala.Int = { /* compiled code */ } + def foo58(): scala.Int = { /* compiled code */ } + def foo59(): scala.Int = { /* compiled code */ } + def foo60(): scala.Int = { /* compiled code */ } + def foo61(): scala.Int = { /* compiled code */ } + def foo62(): scala.Int = { /* compiled code */ } + def foo63(): scala.Int = { /* compiled code */ } + def foo64(): scala.Int = { /* compiled code */ } + def foo65(): scala.Int = { /* compiled code */ } + def foo66(): scala.Int = { /* compiled code */ } + def foo67(): scala.Int = { /* compiled code */ } + def foo68(): scala.Int = { /* compiled code */ } + def foo69(): scala.Int = { /* compiled code */ } + def foo70(): scala.Int = { /* compiled code */ } + def foo71(): scala.Int = { /* compiled code */ } + def foo72(): scala.Int = { /* compiled code */ } + def foo73(): scala.Int = { /* compiled code */ } + def foo74(): scala.Int = { /* compiled code */ } + def foo75(): scala.Int = { /* compiled code */ } + def foo76(): scala.Int = { /* compiled code */ } + def foo77(): scala.Int = { /* compiled code */ } + def foo78(): scala.Int = { /* compiled code */ } + def foo79(): scala.Int = { /* compiled code */ } + def foo80(): scala.Int = { /* compiled code */ } + def foo81(): scala.Int = { /* compiled code */ } + def foo82(): scala.Int = { /* compiled code */ } + def foo83(): scala.Int = { /* compiled code */ } + def foo84(): scala.Int = { /* compiled code */ } + def foo85(): scala.Int = { /* compiled code */ } + def foo86(): scala.Int = { /* compiled code */ } + def foo87(): scala.Int = { /* compiled code */ } + def foo88(): scala.Int = { /* compiled code */ } + def foo89(): scala.Int = { /* compiled code */ } + def foo90(): scala.Int = { /* compiled code */ } + def foo91(): scala.Int = { /* compiled code */ } + def foo92(): scala.Int = { /* compiled code */ } + def foo93(): scala.Int = { /* compiled code */ } + def foo94(): scala.Int = { /* compiled code */ } + def foo95(): scala.Int = { /* compiled code */ } + def foo96(): scala.Int = { /* compiled code */ } + def foo97(): scala.Int = { /* compiled code */ } + def foo98(): scala.Int = { /* compiled code */ } + def foo99(): scala.Int = { /* compiled code */ } + def foo100(): scala.Int = { /* compiled code */ } + def foo101(): scala.Int = { /* compiled code */ } + def foo102(): scala.Int = { /* compiled code */ } + def foo103(): scala.Int = { /* compiled code */ } + def foo104(): scala.Int = { /* compiled code */ } + def foo105(): scala.Int = { /* compiled code */ } + def foo106(): scala.Int = { /* compiled code */ } + def foo107(): scala.Int = { /* compiled code */ } + def foo108(): scala.Int = { /* compiled code */ } + def foo109(): scala.Int = { /* compiled code */ } + def foo110(): scala.Int = { /* compiled code */ } + def foo111(): scala.Int = { /* compiled code */ } + def foo112(): scala.Int = { /* compiled code */ } + def foo113(): scala.Int = { /* compiled code */ } + def foo114(): scala.Int = { /* compiled code */ } + def foo115(): scala.Int = { /* compiled code */ } + def foo116(): scala.Int = { /* compiled code */ } + def foo117(): scala.Int = { /* compiled code */ } + def foo118(): scala.Int = { /* compiled code */ } + def foo119(): scala.Int = { /* compiled code */ } + def foo120(): scala.Int = { /* compiled code */ } + def foo121(): scala.Int = { /* compiled code */ } + def foo122(): scala.Int = { /* compiled code */ } + def foo123(): scala.Int = { /* compiled code */ } + def foo124(): scala.Int = { /* compiled code */ } + def foo125(): scala.Int = { /* compiled code */ } + def foo126(): scala.Int = { /* compiled code */ } + def foo127(): scala.Int = { /* compiled code */ } + def foo128(): scala.Int = { /* compiled code */ } + def foo129(): scala.Int = { /* compiled code */ } + def foo130(): scala.Int = { /* compiled code */ } + def foo131(): scala.Int = { /* compiled code */ } + def foo132(): scala.Int = { /* compiled code */ } + def foo133(): scala.Int = { /* compiled code */ } + def foo134(): scala.Int = { /* compiled code */ } + def foo135(): scala.Int = { /* compiled code */ } + def foo136(): scala.Int = { /* compiled code */ } + def foo137(): scala.Int = { /* compiled code */ } + def foo138(): scala.Int = { /* compiled code */ } + def foo139(): scala.Int = { /* compiled code */ } + def foo140(): scala.Int = { /* compiled code */ } + def foo141(): scala.Int = { /* compiled code */ } + def foo142(): scala.Int = { /* compiled code */ } + def foo143(): scala.Int = { /* compiled code */ } + def foo144(): scala.Int = { /* compiled code */ } + def foo145(): scala.Int = { /* compiled code */ } + def foo146(): scala.Int = { /* compiled code */ } + def foo147(): scala.Int = { /* compiled code */ } + def foo148(): scala.Int = { /* compiled code */ } + def foo149(): scala.Int = { /* compiled code */ } + def foo150(): scala.Int = { /* compiled code */ } + def foo151(): scala.Int = { /* compiled code */ } + def foo152(): scala.Int = { /* compiled code */ } + def foo153(): scala.Int = { /* compiled code */ } + def foo154(): scala.Int = { /* compiled code */ } + def foo155(): scala.Int = { /* compiled code */ } + def foo156(): scala.Int = { /* compiled code */ } + def foo157(): scala.Int = { /* compiled code */ } + def foo158(): scala.Int = { /* compiled code */ } + def foo159(): scala.Int = { /* compiled code */ } + def foo160(): scala.Int = { /* compiled code */ } + def foo161(): scala.Int = { /* compiled code */ } + def foo162(): scala.Int = { /* compiled code */ } + def foo163(): scala.Int = { /* compiled code */ } + def foo164(): scala.Int = { /* compiled code */ } + def foo165(): scala.Int = { /* compiled code */ } + def foo166(): scala.Int = { /* compiled code */ } + def foo167(): scala.Int = { /* compiled code */ } + def foo168(): scala.Int = { /* compiled code */ } + def foo169(): scala.Int = { /* compiled code */ } + def foo170(): scala.Int = { /* compiled code */ } + def foo171(): scala.Int = { /* compiled code */ } + def foo172(): scala.Int = { /* compiled code */ } + def foo173(): scala.Int = { /* compiled code */ } + def foo174(): scala.Int = { /* compiled code */ } + def foo175(): scala.Int = { /* compiled code */ } + def foo176(): scala.Int = { /* compiled code */ } + def foo177(): scala.Int = { /* compiled code */ } + def foo178(): scala.Int = { /* compiled code */ } + def foo179(): scala.Int = { /* compiled code */ } + def foo180(): scala.Int = { /* compiled code */ } + def foo181(): scala.Int = { /* compiled code */ } + def foo182(): scala.Int = { /* compiled code */ } + def foo183(): scala.Int = { /* compiled code */ } + def foo184(): scala.Int = { /* compiled code */ } + def foo185(): scala.Int = { /* compiled code */ } + def foo186(): scala.Int = { /* compiled code */ } + def foo187(): scala.Int = { /* compiled code */ } + def foo188(): scala.Int = { /* compiled code */ } + def foo189(): scala.Int = { /* compiled code */ } + def foo190(): scala.Int = { /* compiled code */ } + def foo191(): scala.Int = { /* compiled code */ } + def foo192(): scala.Int = { /* compiled code */ } + def foo193(): scala.Int = { /* compiled code */ } + def foo194(): scala.Int = { /* compiled code */ } + def foo195(): scala.Int = { /* compiled code */ } + def foo196(): scala.Int = { /* compiled code */ } + def foo197(): scala.Int = { /* compiled code */ } + def foo198(): scala.Int = { /* compiled code */ } + def foo199(): scala.Int = { /* compiled code */ } + def foo200(): scala.Int = { /* compiled code */ } + def foo201(): scala.Int = { /* compiled code */ } + def foo202(): scala.Int = { /* compiled code */ } + def foo203(): scala.Int = { /* compiled code */ } + def foo204(): scala.Int = { /* compiled code */ } + def foo205(): scala.Int = { /* compiled code */ } + def foo206(): scala.Int = { /* compiled code */ } + def foo207(): scala.Int = { /* compiled code */ } + def foo208(): scala.Int = { /* compiled code */ } + def foo209(): scala.Int = { /* compiled code */ } + def foo210(): scala.Int = { /* compiled code */ } + def foo211(): scala.Int = { /* compiled code */ } + def foo212(): scala.Int = { /* compiled code */ } + def foo213(): scala.Int = { /* compiled code */ } + def foo214(): scala.Int = { /* compiled code */ } + def foo215(): scala.Int = { /* compiled code */ } + def foo216(): scala.Int = { /* compiled code */ } + def foo217(): scala.Int = { /* compiled code */ } + def foo218(): scala.Int = { /* compiled code */ } + def foo219(): scala.Int = { /* compiled code */ } + def foo220(): scala.Int = { /* compiled code */ } + def foo221(): scala.Int = { /* compiled code */ } + def foo222(): scala.Int = { /* compiled code */ } + def foo223(): scala.Int = { /* compiled code */ } + def foo224(): scala.Int = { /* compiled code */ } + def foo225(): scala.Int = { /* compiled code */ } + def foo226(): scala.Int = { /* compiled code */ } + def foo227(): scala.Int = { /* compiled code */ } + def foo228(): scala.Int = { /* compiled code */ } + def foo229(): scala.Int = { /* compiled code */ } + def foo230(): scala.Int = { /* compiled code */ } + def foo231(): scala.Int = { /* compiled code */ } + def foo232(): scala.Int = { /* compiled code */ } + def foo233(): scala.Int = { /* compiled code */ } + def foo234(): scala.Int = { /* compiled code */ } + def foo235(): scala.Int = { /* compiled code */ } + def foo236(): scala.Int = { /* compiled code */ } + def foo237(): scala.Int = { /* compiled code */ } + def foo238(): scala.Int = { /* compiled code */ } + def foo239(): scala.Int = { /* compiled code */ } + def foo240(): scala.Int = { /* compiled code */ } + def foo241(): scala.Int = { /* compiled code */ } + def foo242(): scala.Int = { /* compiled code */ } + def foo243(): scala.Int = { /* compiled code */ } + def foo244(): scala.Int = { /* compiled code */ } + def foo245(): scala.Int = { /* compiled code */ } + def foo246(): scala.Int = { /* compiled code */ } + def foo247(): scala.Int = { /* compiled code */ } + def foo248(): scala.Int = { /* compiled code */ } + def foo249(): scala.Int = { /* compiled code */ } + def foo250(): scala.Int = { /* compiled code */ } + def foo251(): scala.Int = { /* compiled code */ } + def foo252(): scala.Int = { /* compiled code */ } + def foo253(): scala.Int = { /* compiled code */ } + def foo254(): scala.Int = { /* compiled code */ } + def foo255(): scala.Int = { /* compiled code */ } + def foo256(): scala.Int = { /* compiled code */ } + def foo257(): scala.Int = { /* compiled code */ } + def foo258(): scala.Int = { /* compiled code */ } + def foo259(): scala.Int = { /* compiled code */ } + def foo260(): scala.Int = { /* compiled code */ } + def foo261(): scala.Int = { /* compiled code */ } + def foo262(): scala.Int = { /* compiled code */ } + def foo263(): scala.Int = { /* compiled code */ } + def foo264(): scala.Int = { /* compiled code */ } + def foo265(): scala.Int = { /* compiled code */ } + def foo266(): scala.Int = { /* compiled code */ } + def foo267(): scala.Int = { /* compiled code */ } + def foo268(): scala.Int = { /* compiled code */ } + def foo269(): scala.Int = { /* compiled code */ } + def foo270(): scala.Int = { /* compiled code */ } + def foo271(): scala.Int = { /* compiled code */ } + def foo272(): scala.Int = { /* compiled code */ } + def foo273(): scala.Int = { /* compiled code */ } + def foo274(): scala.Int = { /* compiled code */ } + def foo275(): scala.Int = { /* compiled code */ } + def foo276(): scala.Int = { /* compiled code */ } + def foo277(): scala.Int = { /* compiled code */ } + def foo278(): scala.Int = { /* compiled code */ } + def foo279(): scala.Int = { /* compiled code */ } + def foo280(): scala.Int = { /* compiled code */ } + def foo281(): scala.Int = { /* compiled code */ } + def foo282(): scala.Int = { /* compiled code */ } + def foo283(): scala.Int = { /* compiled code */ } + def foo284(): scala.Int = { /* compiled code */ } + def foo285(): scala.Int = { /* compiled code */ } + def foo286(): scala.Int = { /* compiled code */ } + def foo287(): scala.Int = { /* compiled code */ } + def foo288(): scala.Int = { /* compiled code */ } + def foo289(): scala.Int = { /* compiled code */ } + def foo290(): scala.Int = { /* compiled code */ } + def foo291(): scala.Int = { /* compiled code */ } + def foo292(): scala.Int = { /* compiled code */ } + def foo293(): scala.Int = { /* compiled code */ } + def foo294(): scala.Int = { /* compiled code */ } + def foo295(): scala.Int = { /* compiled code */ } + def foo296(): scala.Int = { /* compiled code */ } + def foo297(): scala.Int = { /* compiled code */ } + def foo298(): scala.Int = { /* compiled code */ } + def foo299(): scala.Int = { /* compiled code */ } + def foo300(): scala.Int = { /* compiled code */ } + def foo301(): scala.Int = { /* compiled code */ } + def foo302(): scala.Int = { /* compiled code */ } + def foo303(): scala.Int = { /* compiled code */ } + def foo304(): scala.Int = { /* compiled code */ } + def foo305(): scala.Int = { /* compiled code */ } + def foo306(): scala.Int = { /* compiled code */ } + def foo307(): scala.Int = { /* compiled code */ } + def foo308(): scala.Int = { /* compiled code */ } + def foo309(): scala.Int = { /* compiled code */ } + def foo310(): scala.Int = { /* compiled code */ } + def foo311(): scala.Int = { /* compiled code */ } + def foo312(): scala.Int = { /* compiled code */ } + def foo313(): scala.Int = { /* compiled code */ } + def foo314(): scala.Int = { /* compiled code */ } + def foo315(): scala.Int = { /* compiled code */ } + def foo316(): scala.Int = { /* compiled code */ } + def foo317(): scala.Int = { /* compiled code */ } + def foo318(): scala.Int = { /* compiled code */ } + def foo319(): scala.Int = { /* compiled code */ } + def foo320(): scala.Int = { /* compiled code */ } + def foo321(): scala.Int = { /* compiled code */ } + def foo322(): scala.Int = { /* compiled code */ } + def foo323(): scala.Int = { /* compiled code */ } + def foo324(): scala.Int = { /* compiled code */ } + def foo325(): scala.Int = { /* compiled code */ } + def foo326(): scala.Int = { /* compiled code */ } + def foo327(): scala.Int = { /* compiled code */ } + def foo328(): scala.Int = { /* compiled code */ } + def foo329(): scala.Int = { /* compiled code */ } + def foo330(): scala.Int = { /* compiled code */ } + def foo331(): scala.Int = { /* compiled code */ } + def foo332(): scala.Int = { /* compiled code */ } + def foo333(): scala.Int = { /* compiled code */ } + def foo334(): scala.Int = { /* compiled code */ } + def foo335(): scala.Int = { /* compiled code */ } + def foo336(): scala.Int = { /* compiled code */ } + def foo337(): scala.Int = { /* compiled code */ } + def foo338(): scala.Int = { /* compiled code */ } + def foo339(): scala.Int = { /* compiled code */ } + def foo340(): scala.Int = { /* compiled code */ } + def foo341(): scala.Int = { /* compiled code */ } + def foo342(): scala.Int = { /* compiled code */ } + def foo343(): scala.Int = { /* compiled code */ } + def foo344(): scala.Int = { /* compiled code */ } + def foo345(): scala.Int = { /* compiled code */ } + def foo346(): scala.Int = { /* compiled code */ } + def foo347(): scala.Int = { /* compiled code */ } + def foo348(): scala.Int = { /* compiled code */ } + def foo349(): scala.Int = { /* compiled code */ } + def foo350(): scala.Int = { /* compiled code */ } + def foo351(): scala.Int = { /* compiled code */ } + def foo352(): scala.Int = { /* compiled code */ } + def foo353(): scala.Int = { /* compiled code */ } + def foo354(): scala.Int = { /* compiled code */ } + def foo355(): scala.Int = { /* compiled code */ } + def foo356(): scala.Int = { /* compiled code */ } + def foo357(): scala.Int = { /* compiled code */ } + def foo358(): scala.Int = { /* compiled code */ } + def foo359(): scala.Int = { /* compiled code */ } + def foo360(): scala.Int = { /* compiled code */ } + def foo361(): scala.Int = { /* compiled code */ } + def foo362(): scala.Int = { /* compiled code */ } + def foo363(): scala.Int = { /* compiled code */ } + def foo364(): scala.Int = { /* compiled code */ } + def foo365(): scala.Int = { /* compiled code */ } + def foo366(): scala.Int = { /* compiled code */ } + def foo367(): scala.Int = { /* compiled code */ } + def foo368(): scala.Int = { /* compiled code */ } + def foo369(): scala.Int = { /* compiled code */ } + def foo370(): scala.Int = { /* compiled code */ } + def foo371(): scala.Int = { /* compiled code */ } + def foo372(): scala.Int = { /* compiled code */ } + def foo373(): scala.Int = { /* compiled code */ } + def foo374(): scala.Int = { /* compiled code */ } + def foo375(): scala.Int = { /* compiled code */ } + def foo376(): scala.Int = { /* compiled code */ } + def foo377(): scala.Int = { /* compiled code */ } + def foo378(): scala.Int = { /* compiled code */ } + def foo379(): scala.Int = { /* compiled code */ } + def foo380(): scala.Int = { /* compiled code */ } + def foo381(): scala.Int = { /* compiled code */ } + def foo382(): scala.Int = { /* compiled code */ } + def foo383(): scala.Int = { /* compiled code */ } + def foo384(): scala.Int = { /* compiled code */ } + def foo385(): scala.Int = { /* compiled code */ } + def foo386(): scala.Int = { /* compiled code */ } + def foo387(): scala.Int = { /* compiled code */ } + def foo388(): scala.Int = { /* compiled code */ } + def foo389(): scala.Int = { /* compiled code */ } + def foo390(): scala.Int = { /* compiled code */ } + def foo391(): scala.Int = { /* compiled code */ } + def foo392(): scala.Int = { /* compiled code */ } + def foo393(): scala.Int = { /* compiled code */ } + def foo394(): scala.Int = { /* compiled code */ } + def foo395(): scala.Int = { /* compiled code */ } + def foo396(): scala.Int = { /* compiled code */ } + def foo397(): scala.Int = { /* compiled code */ } + def foo398(): scala.Int = { /* compiled code */ } + def foo399(): scala.Int = { /* compiled code */ } + def foo400(): scala.Int = { /* compiled code */ } + def foo401(): scala.Int = { /* compiled code */ } + def foo402(): scala.Int = { /* compiled code */ } + def foo403(): scala.Int = { /* compiled code */ } + def foo404(): scala.Int = { /* compiled code */ } + def foo405(): scala.Int = { /* compiled code */ } + def foo406(): scala.Int = { /* compiled code */ } + def foo407(): scala.Int = { /* compiled code */ } + def foo408(): scala.Int = { /* compiled code */ } + def foo409(): scala.Int = { /* compiled code */ } + def foo410(): scala.Int = { /* compiled code */ } + def foo411(): scala.Int = { /* compiled code */ } + def foo412(): scala.Int = { /* compiled code */ } + def foo413(): scala.Int = { /* compiled code */ } + def foo414(): scala.Int = { /* compiled code */ } + def foo415(): scala.Int = { /* compiled code */ } + def foo416(): scala.Int = { /* compiled code */ } + def foo417(): scala.Int = { /* compiled code */ } + def foo418(): scala.Int = { /* compiled code */ } + def foo419(): scala.Int = { /* compiled code */ } + def foo420(): scala.Int = { /* compiled code */ } + def foo421(): scala.Int = { /* compiled code */ } + def foo422(): scala.Int = { /* compiled code */ } + def foo423(): scala.Int = { /* compiled code */ } + def foo424(): scala.Int = { /* compiled code */ } + def foo425(): scala.Int = { /* compiled code */ } + def foo426(): scala.Int = { /* compiled code */ } + def foo427(): scala.Int = { /* compiled code */ } + def foo428(): scala.Int = { /* compiled code */ } + def foo429(): scala.Int = { /* compiled code */ } + def foo430(): scala.Int = { /* compiled code */ } + def foo431(): scala.Int = { /* compiled code */ } + def foo432(): scala.Int = { /* compiled code */ } + def foo433(): scala.Int = { /* compiled code */ } + def foo434(): scala.Int = { /* compiled code */ } + def foo435(): scala.Int = { /* compiled code */ } + def foo436(): scala.Int = { /* compiled code */ } + def foo437(): scala.Int = { /* compiled code */ } + def foo438(): scala.Int = { /* compiled code */ } + def foo439(): scala.Int = { /* compiled code */ } + def foo440(): scala.Int = { /* compiled code */ } + def foo441(): scala.Int = { /* compiled code */ } + def foo442(): scala.Int = { /* compiled code */ } + def foo443(): scala.Int = { /* compiled code */ } + def foo444(): scala.Int = { /* compiled code */ } + def foo445(): scala.Int = { /* compiled code */ } + def foo446(): scala.Int = { /* compiled code */ } + def foo447(): scala.Int = { /* compiled code */ } + def foo448(): scala.Int = { /* compiled code */ } + def foo449(): scala.Int = { /* compiled code */ } + def foo450(): scala.Int = { /* compiled code */ } + def foo451(): scala.Int = { /* compiled code */ } + def foo452(): scala.Int = { /* compiled code */ } + def foo453(): scala.Int = { /* compiled code */ } + def foo454(): scala.Int = { /* compiled code */ } + def foo455(): scala.Int = { /* compiled code */ } + def foo456(): scala.Int = { /* compiled code */ } + def foo457(): scala.Int = { /* compiled code */ } + def foo458(): scala.Int = { /* compiled code */ } + def foo459(): scala.Int = { /* compiled code */ } + def foo460(): scala.Int = { /* compiled code */ } + def foo461(): scala.Int = { /* compiled code */ } + def foo462(): scala.Int = { /* compiled code */ } + def foo463(): scala.Int = { /* compiled code */ } + def foo464(): scala.Int = { /* compiled code */ } + def foo465(): scala.Int = { /* compiled code */ } + def foo466(): scala.Int = { /* compiled code */ } + def foo467(): scala.Int = { /* compiled code */ } + def foo468(): scala.Int = { /* compiled code */ } + def foo469(): scala.Int = { /* compiled code */ } + def foo470(): scala.Int = { /* compiled code */ } + def foo471(): scala.Int = { /* compiled code */ } + def foo472(): scala.Int = { /* compiled code */ } + def foo473(): scala.Int = { /* compiled code */ } + def foo474(): scala.Int = { /* compiled code */ } + def foo475(): scala.Int = { /* compiled code */ } + def foo476(): scala.Int = { /* compiled code */ } + def foo477(): scala.Int = { /* compiled code */ } + def foo478(): scala.Int = { /* compiled code */ } + def foo479(): scala.Int = { /* compiled code */ } + def foo480(): scala.Int = { /* compiled code */ } + def foo481(): scala.Int = { /* compiled code */ } + def foo482(): scala.Int = { /* compiled code */ } + def foo483(): scala.Int = { /* compiled code */ } + def foo484(): scala.Int = { /* compiled code */ } + def foo485(): scala.Int = { /* compiled code */ } + def foo486(): scala.Int = { /* compiled code */ } + def foo487(): scala.Int = { /* compiled code */ } + def foo488(): scala.Int = { /* compiled code */ } + def foo489(): scala.Int = { /* compiled code */ } + def foo490(): scala.Int = { /* compiled code */ } + def foo491(): scala.Int = { /* compiled code */ } + def foo492(): scala.Int = { /* compiled code */ } + def foo493(): scala.Int = { /* compiled code */ } + def foo494(): scala.Int = { /* compiled code */ } + def foo495(): scala.Int = { /* compiled code */ } + def foo496(): scala.Int = { /* compiled code */ } + def foo497(): scala.Int = { /* compiled code */ } + def foo498(): scala.Int = { /* compiled code */ } + def foo499(): scala.Int = { /* compiled code */ } + def foo500(): scala.Int = { /* compiled code */ } + def foo501(): scala.Int = { /* compiled code */ } + def foo502(): scala.Int = { /* compiled code */ } + def foo503(): scala.Int = { /* compiled code */ } + def foo504(): scala.Int = { /* compiled code */ } + def foo505(): scala.Int = { /* compiled code */ } + def foo506(): scala.Int = { /* compiled code */ } + def foo507(): scala.Int = { /* compiled code */ } + def foo508(): scala.Int = { /* compiled code */ } + def foo509(): scala.Int = { /* compiled code */ } + def foo510(): scala.Int = { /* compiled code */ } + def foo511(): scala.Int = { /* compiled code */ } + def foo512(): scala.Int = { /* compiled code */ } + def foo513(): scala.Int = { /* compiled code */ } + def foo514(): scala.Int = { /* compiled code */ } + def foo515(): scala.Int = { /* compiled code */ } + def foo516(): scala.Int = { /* compiled code */ } + def foo517(): scala.Int = { /* compiled code */ } + def foo518(): scala.Int = { /* compiled code */ } + def foo519(): scala.Int = { /* compiled code */ } + def foo520(): scala.Int = { /* compiled code */ } + def foo521(): scala.Int = { /* compiled code */ } + def foo522(): scala.Int = { /* compiled code */ } + def foo523(): scala.Int = { /* compiled code */ } + def foo524(): scala.Int = { /* compiled code */ } + def foo525(): scala.Int = { /* compiled code */ } + def foo526(): scala.Int = { /* compiled code */ } + def foo527(): scala.Int = { /* compiled code */ } + def foo528(): scala.Int = { /* compiled code */ } + def foo529(): scala.Int = { /* compiled code */ } + def foo530(): scala.Int = { /* compiled code */ } + def foo531(): scala.Int = { /* compiled code */ } + def foo532(): scala.Int = { /* compiled code */ } + def foo533(): scala.Int = { /* compiled code */ } + def foo534(): scala.Int = { /* compiled code */ } + def foo535(): scala.Int = { /* compiled code */ } + def foo536(): scala.Int = { /* compiled code */ } + def foo537(): scala.Int = { /* compiled code */ } + def foo538(): scala.Int = { /* compiled code */ } + def foo539(): scala.Int = { /* compiled code */ } + def foo540(): scala.Int = { /* compiled code */ } + def foo541(): scala.Int = { /* compiled code */ } + def foo542(): scala.Int = { /* compiled code */ } + def foo543(): scala.Int = { /* compiled code */ } + def foo544(): scala.Int = { /* compiled code */ } + def foo545(): scala.Int = { /* compiled code */ } + def foo546(): scala.Int = { /* compiled code */ } + def foo547(): scala.Int = { /* compiled code */ } + def foo548(): scala.Int = { /* compiled code */ } + def foo549(): scala.Int = { /* compiled code */ } + def foo550(): scala.Int = { /* compiled code */ } + def foo551(): scala.Int = { /* compiled code */ } + def foo552(): scala.Int = { /* compiled code */ } + def foo553(): scala.Int = { /* compiled code */ } + def foo554(): scala.Int = { /* compiled code */ } + def foo555(): scala.Int = { /* compiled code */ } + def foo556(): scala.Int = { /* compiled code */ } + def foo557(): scala.Int = { /* compiled code */ } + def foo558(): scala.Int = { /* compiled code */ } + def foo559(): scala.Int = { /* compiled code */ } + def foo560(): scala.Int = { /* compiled code */ } + def foo561(): scala.Int = { /* compiled code */ } + def foo562(): scala.Int = { /* compiled code */ } + def foo563(): scala.Int = { /* compiled code */ } + def foo564(): scala.Int = { /* compiled code */ } + def foo565(): scala.Int = { /* compiled code */ } + def foo566(): scala.Int = { /* compiled code */ } + def foo567(): scala.Int = { /* compiled code */ } + def foo568(): scala.Int = { /* compiled code */ } + def foo569(): scala.Int = { /* compiled code */ } + def foo570(): scala.Int = { /* compiled code */ } + def foo571(): scala.Int = { /* compiled code */ } + def foo572(): scala.Int = { /* compiled code */ } + def foo573(): scala.Int = { /* compiled code */ } + def foo574(): scala.Int = { /* compiled code */ } + def foo575(): scala.Int = { /* compiled code */ } + def foo576(): scala.Int = { /* compiled code */ } + def foo577(): scala.Int = { /* compiled code */ } + def foo578(): scala.Int = { /* compiled code */ } + def foo579(): scala.Int = { /* compiled code */ } + def foo580(): scala.Int = { /* compiled code */ } + def foo581(): scala.Int = { /* compiled code */ } + def foo582(): scala.Int = { /* compiled code */ } + def foo583(): scala.Int = { /* compiled code */ } + def foo584(): scala.Int = { /* compiled code */ } + def foo585(): scala.Int = { /* compiled code */ } + def foo586(): scala.Int = { /* compiled code */ } + def foo587(): scala.Int = { /* compiled code */ } + def foo588(): scala.Int = { /* compiled code */ } + def foo589(): scala.Int = { /* compiled code */ } + def foo590(): scala.Int = { /* compiled code */ } + def foo591(): scala.Int = { /* compiled code */ } + def foo592(): scala.Int = { /* compiled code */ } + def foo593(): scala.Int = { /* compiled code */ } + def foo594(): scala.Int = { /* compiled code */ } + def foo595(): scala.Int = { /* compiled code */ } + def foo596(): scala.Int = { /* compiled code */ } + def foo597(): scala.Int = { /* compiled code */ } + def foo598(): scala.Int = { /* compiled code */ } + def foo599(): scala.Int = { /* compiled code */ } + def foo600(): scala.Int = { /* compiled code */ } + def foo601(): scala.Int = { /* compiled code */ } + def foo602(): scala.Int = { /* compiled code */ } + def foo603(): scala.Int = { /* compiled code */ } + def foo604(): scala.Int = { /* compiled code */ } + def foo605(): scala.Int = { /* compiled code */ } + def foo606(): scala.Int = { /* compiled code */ } + def foo607(): scala.Int = { /* compiled code */ } + def foo608(): scala.Int = { /* compiled code */ } + def foo609(): scala.Int = { /* compiled code */ } + def foo610(): scala.Int = { /* compiled code */ } + def foo611(): scala.Int = { /* compiled code */ } + def foo612(): scala.Int = { /* compiled code */ } + def foo613(): scala.Int = { /* compiled code */ } + def foo614(): scala.Int = { /* compiled code */ } + def foo615(): scala.Int = { /* compiled code */ } + def foo616(): scala.Int = { /* compiled code */ } + def foo617(): scala.Int = { /* compiled code */ } + def foo618(): scala.Int = { /* compiled code */ } + def foo619(): scala.Int = { /* compiled code */ } + def foo620(): scala.Int = { /* compiled code */ } + def foo621(): scala.Int = { /* compiled code */ } + def foo622(): scala.Int = { /* compiled code */ } + def foo623(): scala.Int = { /* compiled code */ } + def foo624(): scala.Int = { /* compiled code */ } + def foo625(): scala.Int = { /* compiled code */ } + def foo626(): scala.Int = { /* compiled code */ } + def foo627(): scala.Int = { /* compiled code */ } + def foo628(): scala.Int = { /* compiled code */ } + def foo629(): scala.Int = { /* compiled code */ } + def foo630(): scala.Int = { /* compiled code */ } + def foo631(): scala.Int = { /* compiled code */ } + def foo632(): scala.Int = { /* compiled code */ } + def foo633(): scala.Int = { /* compiled code */ } + def foo634(): scala.Int = { /* compiled code */ } + def foo635(): scala.Int = { /* compiled code */ } + def foo636(): scala.Int = { /* compiled code */ } + def foo637(): scala.Int = { /* compiled code */ } + def foo638(): scala.Int = { /* compiled code */ } + def foo639(): scala.Int = { /* compiled code */ } + def foo640(): scala.Int = { /* compiled code */ } + def foo641(): scala.Int = { /* compiled code */ } + def foo642(): scala.Int = { /* compiled code */ } + def foo643(): scala.Int = { /* compiled code */ } + def foo644(): scala.Int = { /* compiled code */ } + def foo645(): scala.Int = { /* compiled code */ } + def foo646(): scala.Int = { /* compiled code */ } + def foo647(): scala.Int = { /* compiled code */ } + def foo648(): scala.Int = { /* compiled code */ } + def foo649(): scala.Int = { /* compiled code */ } + def foo650(): scala.Int = { /* compiled code */ } + def foo651(): scala.Int = { /* compiled code */ } + def foo652(): scala.Int = { /* compiled code */ } + def foo653(): scala.Int = { /* compiled code */ } + def foo654(): scala.Int = { /* compiled code */ } + def foo655(): scala.Int = { /* compiled code */ } + def foo656(): scala.Int = { /* compiled code */ } + def foo657(): scala.Int = { /* compiled code */ } + def foo658(): scala.Int = { /* compiled code */ } + def foo659(): scala.Int = { /* compiled code */ } + def foo660(): scala.Int = { /* compiled code */ } + def foo661(): scala.Int = { /* compiled code */ } + def foo662(): scala.Int = { /* compiled code */ } + def foo663(): scala.Int = { /* compiled code */ } + def foo664(): scala.Int = { /* compiled code */ } + def foo665(): scala.Int = { /* compiled code */ } + def foo666(): scala.Int = { /* compiled code */ } + def foo667(): scala.Int = { /* compiled code */ } + def foo668(): scala.Int = { /* compiled code */ } + def foo669(): scala.Int = { /* compiled code */ } + def foo670(): scala.Int = { /* compiled code */ } + def foo671(): scala.Int = { /* compiled code */ } + def foo672(): scala.Int = { /* compiled code */ } + def foo673(): scala.Int = { /* compiled code */ } + def foo674(): scala.Int = { /* compiled code */ } + def foo675(): scala.Int = { /* compiled code */ } + def foo676(): scala.Int = { /* compiled code */ } + def foo677(): scala.Int = { /* compiled code */ } + def foo678(): scala.Int = { /* compiled code */ } + def foo679(): scala.Int = { /* compiled code */ } + def foo680(): scala.Int = { /* compiled code */ } + def foo681(): scala.Int = { /* compiled code */ } + def foo682(): scala.Int = { /* compiled code */ } + def foo683(): scala.Int = { /* compiled code */ } + def foo684(): scala.Int = { /* compiled code */ } + def foo685(): scala.Int = { /* compiled code */ } + def foo686(): scala.Int = { /* compiled code */ } + def foo687(): scala.Int = { /* compiled code */ } + def foo688(): scala.Int = { /* compiled code */ } + def foo689(): scala.Int = { /* compiled code */ } + def foo690(): scala.Int = { /* compiled code */ } + def foo691(): scala.Int = { /* compiled code */ } + def foo692(): scala.Int = { /* compiled code */ } + def foo693(): scala.Int = { /* compiled code */ } + def foo694(): scala.Int = { /* compiled code */ } + def foo695(): scala.Int = { /* compiled code */ } + def foo696(): scala.Int = { /* compiled code */ } + def foo697(): scala.Int = { /* compiled code */ } + def foo698(): scala.Int = { /* compiled code */ } + def foo699(): scala.Int = { /* compiled code */ } + def foo700(): scala.Int = { /* compiled code */ } + def foo701(): scala.Int = { /* compiled code */ } + def foo702(): scala.Int = { /* compiled code */ } + def foo703(): scala.Int = { /* compiled code */ } + def foo704(): scala.Int = { /* compiled code */ } + def foo705(): scala.Int = { /* compiled code */ } + def foo706(): scala.Int = { /* compiled code */ } + def foo707(): scala.Int = { /* compiled code */ } + def foo708(): scala.Int = { /* compiled code */ } + def foo709(): scala.Int = { /* compiled code */ } + def foo710(): scala.Int = { /* compiled code */ } + def foo711(): scala.Int = { /* compiled code */ } + def foo712(): scala.Int = { /* compiled code */ } + def foo713(): scala.Int = { /* compiled code */ } + def foo714(): scala.Int = { /* compiled code */ } + def foo715(): scala.Int = { /* compiled code */ } + def foo716(): scala.Int = { /* compiled code */ } + def foo717(): scala.Int = { /* compiled code */ } + def foo718(): scala.Int = { /* compiled code */ } + def foo719(): scala.Int = { /* compiled code */ } + def foo720(): scala.Int = { /* compiled code */ } + def foo721(): scala.Int = { /* compiled code */ } + def foo722(): scala.Int = { /* compiled code */ } + def foo723(): scala.Int = { /* compiled code */ } + def foo724(): scala.Int = { /* compiled code */ } + def foo725(): scala.Int = { /* compiled code */ } + def foo726(): scala.Int = { /* compiled code */ } + def foo727(): scala.Int = { /* compiled code */ } + def foo728(): scala.Int = { /* compiled code */ } + def foo729(): scala.Int = { /* compiled code */ } + def foo730(): scala.Int = { /* compiled code */ } + def foo731(): scala.Int = { /* compiled code */ } + def foo732(): scala.Int = { /* compiled code */ } + def foo733(): scala.Int = { /* compiled code */ } + def foo734(): scala.Int = { /* compiled code */ } + def foo735(): scala.Int = { /* compiled code */ } + def foo736(): scala.Int = { /* compiled code */ } + def foo737(): scala.Int = { /* compiled code */ } + def foo738(): scala.Int = { /* compiled code */ } + def foo739(): scala.Int = { /* compiled code */ } + def foo740(): scala.Int = { /* compiled code */ } + def foo741(): scala.Int = { /* compiled code */ } + def foo742(): scala.Int = { /* compiled code */ } + def foo743(): scala.Int = { /* compiled code */ } + def foo744(): scala.Int = { /* compiled code */ } + def foo745(): scala.Int = { /* compiled code */ } + def foo746(): scala.Int = { /* compiled code */ } + def foo747(): scala.Int = { /* compiled code */ } + def foo748(): scala.Int = { /* compiled code */ } + def foo749(): scala.Int = { /* compiled code */ } + def foo750(): scala.Int = { /* compiled code */ } + def foo751(): scala.Int = { /* compiled code */ } + def foo752(): scala.Int = { /* compiled code */ } + def foo753(): scala.Int = { /* compiled code */ } + def foo754(): scala.Int = { /* compiled code */ } + def foo755(): scala.Int = { /* compiled code */ } + def foo756(): scala.Int = { /* compiled code */ } + def foo757(): scala.Int = { /* compiled code */ } + def foo758(): scala.Int = { /* compiled code */ } + def foo759(): scala.Int = { /* compiled code */ } + def foo760(): scala.Int = { /* compiled code */ } + def foo761(): scala.Int = { /* compiled code */ } + def foo762(): scala.Int = { /* compiled code */ } + def foo763(): scala.Int = { /* compiled code */ } + def foo764(): scala.Int = { /* compiled code */ } + def foo765(): scala.Int = { /* compiled code */ } + def foo766(): scala.Int = { /* compiled code */ } + def foo767(): scala.Int = { /* compiled code */ } + def foo768(): scala.Int = { /* compiled code */ } + def foo769(): scala.Int = { /* compiled code */ } + def foo770(): scala.Int = { /* compiled code */ } + def foo771(): scala.Int = { /* compiled code */ } + def foo772(): scala.Int = { /* compiled code */ } + def foo773(): scala.Int = { /* compiled code */ } + def foo774(): scala.Int = { /* compiled code */ } + def foo775(): scala.Int = { /* compiled code */ } + def foo776(): scala.Int = { /* compiled code */ } + def foo777(): scala.Int = { /* compiled code */ } + def foo778(): scala.Int = { /* compiled code */ } + def foo779(): scala.Int = { /* compiled code */ } + def foo780(): scala.Int = { /* compiled code */ } + def foo781(): scala.Int = { /* compiled code */ } + def foo782(): scala.Int = { /* compiled code */ } + def foo783(): scala.Int = { /* compiled code */ } + def foo784(): scala.Int = { /* compiled code */ } + def foo785(): scala.Int = { /* compiled code */ } + def foo786(): scala.Int = { /* compiled code */ } + def foo787(): scala.Int = { /* compiled code */ } + def foo788(): scala.Int = { /* compiled code */ } + def foo789(): scala.Int = { /* compiled code */ } + def foo790(): scala.Int = { /* compiled code */ } + def foo791(): scala.Int = { /* compiled code */ } + def foo792(): scala.Int = { /* compiled code */ } + def foo793(): scala.Int = { /* compiled code */ } + def foo794(): scala.Int = { /* compiled code */ } + def foo795(): scala.Int = { /* compiled code */ } + def foo796(): scala.Int = { /* compiled code */ } + def foo797(): scala.Int = { /* compiled code */ } + def foo798(): scala.Int = { /* compiled code */ } + def foo799(): scala.Int = { /* compiled code */ } + def foo800(): scala.Int = { /* compiled code */ } + def foo801(): scala.Int = { /* compiled code */ } + def foo802(): scala.Int = { /* compiled code */ } + def foo803(): scala.Int = { /* compiled code */ } + def foo804(): scala.Int = { /* compiled code */ } + def foo805(): scala.Int = { /* compiled code */ } + def foo806(): scala.Int = { /* compiled code */ } + def foo807(): scala.Int = { /* compiled code */ } + def foo808(): scala.Int = { /* compiled code */ } + def foo809(): scala.Int = { /* compiled code */ } + def foo810(): scala.Int = { /* compiled code */ } + def foo811(): scala.Int = { /* compiled code */ } + def foo812(): scala.Int = { /* compiled code */ } + def foo813(): scala.Int = { /* compiled code */ } + def foo814(): scala.Int = { /* compiled code */ } + def foo815(): scala.Int = { /* compiled code */ } + def foo816(): scala.Int = { /* compiled code */ } + def foo817(): scala.Int = { /* compiled code */ } + def foo818(): scala.Int = { /* compiled code */ } + def foo819(): scala.Int = { /* compiled code */ } + def foo820(): scala.Int = { /* compiled code */ } + def foo821(): scala.Int = { /* compiled code */ } + def foo822(): scala.Int = { /* compiled code */ } + def foo823(): scala.Int = { /* compiled code */ } + def foo824(): scala.Int = { /* compiled code */ } + def foo825(): scala.Int = { /* compiled code */ } + def foo826(): scala.Int = { /* compiled code */ } + def foo827(): scala.Int = { /* compiled code */ } + def foo828(): scala.Int = { /* compiled code */ } + def foo829(): scala.Int = { /* compiled code */ } + def foo830(): scala.Int = { /* compiled code */ } + def foo831(): scala.Int = { /* compiled code */ } + def foo832(): scala.Int = { /* compiled code */ } + def foo833(): scala.Int = { /* compiled code */ } + def foo834(): scala.Int = { /* compiled code */ } + def foo835(): scala.Int = { /* compiled code */ } + def foo836(): scala.Int = { /* compiled code */ } + def foo837(): scala.Int = { /* compiled code */ } + def foo838(): scala.Int = { /* compiled code */ } + def foo839(): scala.Int = { /* compiled code */ } + def foo840(): scala.Int = { /* compiled code */ } + def foo841(): scala.Int = { /* compiled code */ } + def foo842(): scala.Int = { /* compiled code */ } + def foo843(): scala.Int = { /* compiled code */ } + def foo844(): scala.Int = { /* compiled code */ } + def foo845(): scala.Int = { /* compiled code */ } + def foo846(): scala.Int = { /* compiled code */ } + def foo847(): scala.Int = { /* compiled code */ } + def foo848(): scala.Int = { /* compiled code */ } + def foo849(): scala.Int = { /* compiled code */ } + def foo850(): scala.Int = { /* compiled code */ } + def foo851(): scala.Int = { /* compiled code */ } + def foo852(): scala.Int = { /* compiled code */ } + def foo853(): scala.Int = { /* compiled code */ } + def foo854(): scala.Int = { /* compiled code */ } + def foo855(): scala.Int = { /* compiled code */ } + def foo856(): scala.Int = { /* compiled code */ } + def foo857(): scala.Int = { /* compiled code */ } + def foo858(): scala.Int = { /* compiled code */ } + def foo859(): scala.Int = { /* compiled code */ } + def foo860(): scala.Int = { /* compiled code */ } + def foo861(): scala.Int = { /* compiled code */ } + def foo862(): scala.Int = { /* compiled code */ } + def foo863(): scala.Int = { /* compiled code */ } + def foo864(): scala.Int = { /* compiled code */ } + def foo865(): scala.Int = { /* compiled code */ } + def foo866(): scala.Int = { /* compiled code */ } + def foo867(): scala.Int = { /* compiled code */ } + def foo868(): scala.Int = { /* compiled code */ } + def foo869(): scala.Int = { /* compiled code */ } + def foo870(): scala.Int = { /* compiled code */ } + def foo871(): scala.Int = { /* compiled code */ } + def foo872(): scala.Int = { /* compiled code */ } + def foo873(): scala.Int = { /* compiled code */ } + def foo874(): scala.Int = { /* compiled code */ } + def foo875(): scala.Int = { /* compiled code */ } + def foo876(): scala.Int = { /* compiled code */ } + def foo877(): scala.Int = { /* compiled code */ } + def foo878(): scala.Int = { /* compiled code */ } + def foo879(): scala.Int = { /* compiled code */ } + def foo880(): scala.Int = { /* compiled code */ } + def foo881(): scala.Int = { /* compiled code */ } + def foo882(): scala.Int = { /* compiled code */ } + def foo883(): scala.Int = { /* compiled code */ } + def foo884(): scala.Int = { /* compiled code */ } + def foo885(): scala.Int = { /* compiled code */ } + def foo886(): scala.Int = { /* compiled code */ } + def foo887(): scala.Int = { /* compiled code */ } + def foo888(): scala.Int = { /* compiled code */ } + def foo889(): scala.Int = { /* compiled code */ } + def foo890(): scala.Int = { /* compiled code */ } + def foo891(): scala.Int = { /* compiled code */ } + def foo892(): scala.Int = { /* compiled code */ } + def foo893(): scala.Int = { /* compiled code */ } + def foo894(): scala.Int = { /* compiled code */ } + def foo895(): scala.Int = { /* compiled code */ } + def foo896(): scala.Int = { /* compiled code */ } + def foo897(): scala.Int = { /* compiled code */ } + def foo898(): scala.Int = { /* compiled code */ } + def foo899(): scala.Int = { /* compiled code */ } + def foo900(): scala.Int = { /* compiled code */ } + def foo901(): scala.Int = { /* compiled code */ } + def foo902(): scala.Int = { /* compiled code */ } + def foo903(): scala.Int = { /* compiled code */ } + def foo904(): scala.Int = { /* compiled code */ } + def foo905(): scala.Int = { /* compiled code */ } + def foo906(): scala.Int = { /* compiled code */ } + def foo907(): scala.Int = { /* compiled code */ } + def foo908(): scala.Int = { /* compiled code */ } + def foo909(): scala.Int = { /* compiled code */ } + def foo910(): scala.Int = { /* compiled code */ } + def foo911(): scala.Int = { /* compiled code */ } + def foo912(): scala.Int = { /* compiled code */ } + def foo913(): scala.Int = { /* compiled code */ } + def foo914(): scala.Int = { /* compiled code */ } + def foo915(): scala.Int = { /* compiled code */ } + def foo916(): scala.Int = { /* compiled code */ } + def foo917(): scala.Int = { /* compiled code */ } + def foo918(): scala.Int = { /* compiled code */ } + def foo919(): scala.Int = { /* compiled code */ } + def foo920(): scala.Int = { /* compiled code */ } + def foo921(): scala.Int = { /* compiled code */ } + def foo922(): scala.Int = { /* compiled code */ } + def foo923(): scala.Int = { /* compiled code */ } + def foo924(): scala.Int = { /* compiled code */ } + def foo925(): scala.Int = { /* compiled code */ } + def foo926(): scala.Int = { /* compiled code */ } + def foo927(): scala.Int = { /* compiled code */ } + def foo928(): scala.Int = { /* compiled code */ } + def foo929(): scala.Int = { /* compiled code */ } + def foo930(): scala.Int = { /* compiled code */ } + def foo931(): scala.Int = { /* compiled code */ } + def foo932(): scala.Int = { /* compiled code */ } + def foo933(): scala.Int = { /* compiled code */ } + def foo934(): scala.Int = { /* compiled code */ } + def foo935(): scala.Int = { /* compiled code */ } + def foo936(): scala.Int = { /* compiled code */ } + def foo937(): scala.Int = { /* compiled code */ } + def foo938(): scala.Int = { /* compiled code */ } + def foo939(): scala.Int = { /* compiled code */ } + def foo940(): scala.Int = { /* compiled code */ } + def foo941(): scala.Int = { /* compiled code */ } + def foo942(): scala.Int = { /* compiled code */ } + def foo943(): scala.Int = { /* compiled code */ } + def foo944(): scala.Int = { /* compiled code */ } + def foo945(): scala.Int = { /* compiled code */ } + def foo946(): scala.Int = { /* compiled code */ } + def foo947(): scala.Int = { /* compiled code */ } + def foo948(): scala.Int = { /* compiled code */ } + def foo949(): scala.Int = { /* compiled code */ } + def foo950(): scala.Int = { /* compiled code */ } + def foo951(): scala.Int = { /* compiled code */ } + def foo952(): scala.Int = { /* compiled code */ } + def foo953(): scala.Int = { /* compiled code */ } + def foo954(): scala.Int = { /* compiled code */ } + def foo955(): scala.Int = { /* compiled code */ } + def foo956(): scala.Int = { /* compiled code */ } + def foo957(): scala.Int = { /* compiled code */ } + def foo958(): scala.Int = { /* compiled code */ } + def foo959(): scala.Int = { /* compiled code */ } + def foo960(): scala.Int = { /* compiled code */ } + def foo961(): scala.Int = { /* compiled code */ } + def foo962(): scala.Int = { /* compiled code */ } + def foo963(): scala.Int = { /* compiled code */ } + def foo964(): scala.Int = { /* compiled code */ } + def foo965(): scala.Int = { /* compiled code */ } + def foo966(): scala.Int = { /* compiled code */ } + def foo967(): scala.Int = { /* compiled code */ } + def foo968(): scala.Int = { /* compiled code */ } + def foo969(): scala.Int = { /* compiled code */ } + def foo970(): scala.Int = { /* compiled code */ } + def foo971(): scala.Int = { /* compiled code */ } + def foo972(): scala.Int = { /* compiled code */ } + def foo973(): scala.Int = { /* compiled code */ } + def foo974(): scala.Int = { /* compiled code */ } + def foo975(): scala.Int = { /* compiled code */ } + def foo976(): scala.Int = { /* compiled code */ } + def foo977(): scala.Int = { /* compiled code */ } + def foo978(): scala.Int = { /* compiled code */ } + def foo979(): scala.Int = { /* compiled code */ } + def foo980(): scala.Int = { /* compiled code */ } + def foo981(): scala.Int = { /* compiled code */ } + def foo982(): scala.Int = { /* compiled code */ } + def foo983(): scala.Int = { /* compiled code */ } + def foo984(): scala.Int = { /* compiled code */ } + def foo985(): scala.Int = { /* compiled code */ } + def foo986(): scala.Int = { /* compiled code */ } + def foo987(): scala.Int = { /* compiled code */ } + def foo988(): scala.Int = { /* compiled code */ } + def foo989(): scala.Int = { /* compiled code */ } + def foo990(): scala.Int = { /* compiled code */ } + def foo991(): scala.Int = { /* compiled code */ } + def foo992(): scala.Int = { /* compiled code */ } + def foo993(): scala.Int = { /* compiled code */ } + def foo994(): scala.Int = { /* compiled code */ } + def foo995(): scala.Int = { /* compiled code */ } + def foo996(): scala.Int = { /* compiled code */ } + def foo997(): scala.Int = { /* compiled code */ } + def foo998(): scala.Int = { /* compiled code */ } + def foo999(): scala.Int = { /* compiled code */ } + def foo1000(): scala.Int = { /* compiled code */ } + def foo1001(): scala.Int = { /* compiled code */ } + def foo1002(): scala.Int = { /* compiled code */ } + def foo1003(): scala.Int = { /* compiled code */ } + def foo1004(): scala.Int = { /* compiled code */ } + def foo1005(): scala.Int = { /* compiled code */ } + def foo1006(): scala.Int = { /* compiled code */ } + def foo1007(): scala.Int = { /* compiled code */ } + def foo1008(): scala.Int = { /* compiled code */ } + def foo1009(): scala.Int = { /* compiled code */ } + def foo1010(): scala.Int = { /* compiled code */ } + def foo1011(): scala.Int = { /* compiled code */ } + def foo1012(): scala.Int = { /* compiled code */ } + def foo1013(): scala.Int = { /* compiled code */ } + def foo1014(): scala.Int = { /* compiled code */ } + def foo1015(): scala.Int = { /* compiled code */ } + def foo1016(): scala.Int = { /* compiled code */ } + def foo1017(): scala.Int = { /* compiled code */ } + def foo1018(): scala.Int = { /* compiled code */ } + def foo1019(): scala.Int = { /* compiled code */ } + def foo1020(): scala.Int = { /* compiled code */ } + def foo1021(): scala.Int = { /* compiled code */ } + def foo1022(): scala.Int = { /* compiled code */ } + def foo1023(): scala.Int = { /* compiled code */ } + def foo1024(): scala.Int = { /* compiled code */ } + def foo1025(): scala.Int = { /* compiled code */ } + def foo1026(): scala.Int = { /* compiled code */ } + def foo1027(): scala.Int = { /* compiled code */ } + def foo1028(): scala.Int = { /* compiled code */ } + def foo1029(): scala.Int = { /* compiled code */ } + def foo1030(): scala.Int = { /* compiled code */ } + def foo1031(): scala.Int = { /* compiled code */ } + def foo1032(): scala.Int = { /* compiled code */ } + def foo1033(): scala.Int = { /* compiled code */ } + def foo1034(): scala.Int = { /* compiled code */ } + def foo1035(): scala.Int = { /* compiled code */ } + def foo1036(): scala.Int = { /* compiled code */ } + def foo1037(): scala.Int = { /* compiled code */ } + def foo1038(): scala.Int = { /* compiled code */ } + def foo1039(): scala.Int = { /* compiled code */ } + def foo1040(): scala.Int = { /* compiled code */ } + def foo1041(): scala.Int = { /* compiled code */ } + def foo1042(): scala.Int = { /* compiled code */ } + def foo1043(): scala.Int = { /* compiled code */ } + def foo1044(): scala.Int = { /* compiled code */ } + def foo1045(): scala.Int = { /* compiled code */ } + def foo1046(): scala.Int = { /* compiled code */ } + def foo1047(): scala.Int = { /* compiled code */ } + def foo1048(): scala.Int = { /* compiled code */ } + def foo1049(): scala.Int = { /* compiled code */ } + def foo1050(): scala.Int = { /* compiled code */ } + def foo1051(): scala.Int = { /* compiled code */ } + def foo1052(): scala.Int = { /* compiled code */ } + def foo1053(): scala.Int = { /* compiled code */ } + def foo1054(): scala.Int = { /* compiled code */ } + def foo1055(): scala.Int = { /* compiled code */ } + def foo1056(): scala.Int = { /* compiled code */ } + def foo1057(): scala.Int = { /* compiled code */ } + def foo1058(): scala.Int = { /* compiled code */ } + def foo1059(): scala.Int = { /* compiled code */ } + def foo1060(): scala.Int = { /* compiled code */ } + def foo1061(): scala.Int = { /* compiled code */ } + def foo1062(): scala.Int = { /* compiled code */ } + def foo1063(): scala.Int = { /* compiled code */ } + def foo1064(): scala.Int = { /* compiled code */ } + def foo1065(): scala.Int = { /* compiled code */ } + def foo1066(): scala.Int = { /* compiled code */ } + def foo1067(): scala.Int = { /* compiled code */ } + def foo1068(): scala.Int = { /* compiled code */ } + def foo1069(): scala.Int = { /* compiled code */ } + def foo1070(): scala.Int = { /* compiled code */ } + def foo1071(): scala.Int = { /* compiled code */ } + def foo1072(): scala.Int = { /* compiled code */ } + def foo1073(): scala.Int = { /* compiled code */ } + def foo1074(): scala.Int = { /* compiled code */ } + def foo1075(): scala.Int = { /* compiled code */ } + def foo1076(): scala.Int = { /* compiled code */ } + def foo1077(): scala.Int = { /* compiled code */ } + def foo1078(): scala.Int = { /* compiled code */ } + def foo1079(): scala.Int = { /* compiled code */ } + def foo1080(): scala.Int = { /* compiled code */ } + def foo1081(): scala.Int = { /* compiled code */ } + def foo1082(): scala.Int = { /* compiled code */ } + def foo1083(): scala.Int = { /* compiled code */ } + def foo1084(): scala.Int = { /* compiled code */ } + def foo1085(): scala.Int = { /* compiled code */ } + def foo1086(): scala.Int = { /* compiled code */ } + def foo1087(): scala.Int = { /* compiled code */ } + def foo1088(): scala.Int = { /* compiled code */ } + def foo1089(): scala.Int = { /* compiled code */ } + def foo1090(): scala.Int = { /* compiled code */ } + def foo1091(): scala.Int = { /* compiled code */ } + def foo1092(): scala.Int = { /* compiled code */ } + def foo1093(): scala.Int = { /* compiled code */ } + def foo1094(): scala.Int = { /* compiled code */ } + def foo1095(): scala.Int = { /* compiled code */ } + def foo1096(): scala.Int = { /* compiled code */ } + def foo1097(): scala.Int = { /* compiled code */ } + def foo1098(): scala.Int = { /* compiled code */ } + def foo1099(): scala.Int = { /* compiled code */ } + def foo1100(): scala.Int = { /* compiled code */ } + def foo1101(): scala.Int = { /* compiled code */ } + def foo1102(): scala.Int = { /* compiled code */ } + def foo1103(): scala.Int = { /* compiled code */ } + def foo1104(): scala.Int = { /* compiled code */ } + def foo1105(): scala.Int = { /* compiled code */ } + def foo1106(): scala.Int = { /* compiled code */ } + def foo1107(): scala.Int = { /* compiled code */ } + def foo1108(): scala.Int = { /* compiled code */ } + def foo1109(): scala.Int = { /* compiled code */ } + def foo1110(): scala.Int = { /* compiled code */ } + def foo1111(): scala.Int = { /* compiled code */ } + def foo1112(): scala.Int = { /* compiled code */ } + def foo1113(): scala.Int = { /* compiled code */ } + def foo1114(): scala.Int = { /* compiled code */ } + def foo1115(): scala.Int = { /* compiled code */ } + def foo1116(): scala.Int = { /* compiled code */ } + def foo1117(): scala.Int = { /* compiled code */ } + def foo1118(): scala.Int = { /* compiled code */ } + def foo1119(): scala.Int = { /* compiled code */ } + def foo1120(): scala.Int = { /* compiled code */ } + def foo1121(): scala.Int = { /* compiled code */ } + def foo1122(): scala.Int = { /* compiled code */ } + def foo1123(): scala.Int = { /* compiled code */ } + def foo1124(): scala.Int = { /* compiled code */ } + def foo1125(): scala.Int = { /* compiled code */ } + def foo1126(): scala.Int = { /* compiled code */ } + def foo1127(): scala.Int = { /* compiled code */ } + def foo1128(): scala.Int = { /* compiled code */ } + def foo1129(): scala.Int = { /* compiled code */ } + def foo1130(): scala.Int = { /* compiled code */ } + def foo1131(): scala.Int = { /* compiled code */ } + def foo1132(): scala.Int = { /* compiled code */ } + def foo1133(): scala.Int = { /* compiled code */ } + def foo1134(): scala.Int = { /* compiled code */ } + def foo1135(): scala.Int = { /* compiled code */ } + def foo1136(): scala.Int = { /* compiled code */ } + def foo1137(): scala.Int = { /* compiled code */ } + def foo1138(): scala.Int = { /* compiled code */ } + def foo1139(): scala.Int = { /* compiled code */ } + def foo1140(): scala.Int = { /* compiled code */ } + def foo1141(): scala.Int = { /* compiled code */ } + def foo1142(): scala.Int = { /* compiled code */ } + def foo1143(): scala.Int = { /* compiled code */ } + def foo1144(): scala.Int = { /* compiled code */ } + def foo1145(): scala.Int = { /* compiled code */ } + def foo1146(): scala.Int = { /* compiled code */ } + def foo1147(): scala.Int = { /* compiled code */ } + def foo1148(): scala.Int = { /* compiled code */ } + def foo1149(): scala.Int = { /* compiled code */ } + def foo1150(): scala.Int = { /* compiled code */ } + def foo1151(): scala.Int = { /* compiled code */ } + def foo1152(): scala.Int = { /* compiled code */ } + def foo1153(): scala.Int = { /* compiled code */ } + def foo1154(): scala.Int = { /* compiled code */ } + def foo1155(): scala.Int = { /* compiled code */ } + def foo1156(): scala.Int = { /* compiled code */ } + def foo1157(): scala.Int = { /* compiled code */ } + def foo1158(): scala.Int = { /* compiled code */ } + def foo1159(): scala.Int = { /* compiled code */ } + def foo1160(): scala.Int = { /* compiled code */ } + def foo1161(): scala.Int = { /* compiled code */ } + def foo1162(): scala.Int = { /* compiled code */ } + def foo1163(): scala.Int = { /* compiled code */ } + def foo1164(): scala.Int = { /* compiled code */ } + def foo1165(): scala.Int = { /* compiled code */ } + def foo1166(): scala.Int = { /* compiled code */ } + def foo1167(): scala.Int = { /* compiled code */ } + def foo1168(): scala.Int = { /* compiled code */ } + def foo1169(): scala.Int = { /* compiled code */ } + def foo1170(): scala.Int = { /* compiled code */ } + def foo1171(): scala.Int = { /* compiled code */ } + def foo1172(): scala.Int = { /* compiled code */ } + def foo1173(): scala.Int = { /* compiled code */ } + def foo1174(): scala.Int = { /* compiled code */ } + def foo1175(): scala.Int = { /* compiled code */ } + def foo1176(): scala.Int = { /* compiled code */ } + def foo1177(): scala.Int = { /* compiled code */ } + def foo1178(): scala.Int = { /* compiled code */ } + def foo1179(): scala.Int = { /* compiled code */ } + def foo1180(): scala.Int = { /* compiled code */ } + def foo1181(): scala.Int = { /* compiled code */ } + def foo1182(): scala.Int = { /* compiled code */ } + def foo1183(): scala.Int = { /* compiled code */ } + def foo1184(): scala.Int = { /* compiled code */ } + def foo1185(): scala.Int = { /* compiled code */ } + def foo1186(): scala.Int = { /* compiled code */ } + def foo1187(): scala.Int = { /* compiled code */ } + def foo1188(): scala.Int = { /* compiled code */ } + def foo1189(): scala.Int = { /* compiled code */ } + def foo1190(): scala.Int = { /* compiled code */ } + def foo1191(): scala.Int = { /* compiled code */ } + def foo1192(): scala.Int = { /* compiled code */ } + def foo1193(): scala.Int = { /* compiled code */ } + def foo1194(): scala.Int = { /* compiled code */ } + def foo1195(): scala.Int = { /* compiled code */ } + def foo1196(): scala.Int = { /* compiled code */ } + def foo1197(): scala.Int = { /* compiled code */ } + def foo1198(): scala.Int = { /* compiled code */ } + def foo1199(): scala.Int = { /* compiled code */ } + def foo1200(): scala.Int = { /* compiled code */ } + def foo1201(): scala.Int = { /* compiled code */ } + def foo1202(): scala.Int = { /* compiled code */ } + def foo1203(): scala.Int = { /* compiled code */ } + def foo1204(): scala.Int = { /* compiled code */ } + def foo1205(): scala.Int = { /* compiled code */ } + def foo1206(): scala.Int = { /* compiled code */ } + def foo1207(): scala.Int = { /* compiled code */ } + def foo1208(): scala.Int = { /* compiled code */ } + def foo1209(): scala.Int = { /* compiled code */ } + def foo1210(): scala.Int = { /* compiled code */ } + def foo1211(): scala.Int = { /* compiled code */ } + def foo1212(): scala.Int = { /* compiled code */ } + def foo1213(): scala.Int = { /* compiled code */ } + def foo1214(): scala.Int = { /* compiled code */ } + def foo1215(): scala.Int = { /* compiled code */ } + def foo1216(): scala.Int = { /* compiled code */ } + def foo1217(): scala.Int = { /* compiled code */ } + def foo1218(): scala.Int = { /* compiled code */ } + def foo1219(): scala.Int = { /* compiled code */ } + def foo1220(): scala.Int = { /* compiled code */ } + def foo1221(): scala.Int = { /* compiled code */ } + def foo1222(): scala.Int = { /* compiled code */ } + def foo1223(): scala.Int = { /* compiled code */ } + def foo1224(): scala.Int = { /* compiled code */ } + def foo1225(): scala.Int = { /* compiled code */ } + def foo1226(): scala.Int = { /* compiled code */ } + def foo1227(): scala.Int = { /* compiled code */ } + def foo1228(): scala.Int = { /* compiled code */ } + def foo1229(): scala.Int = { /* compiled code */ } + def foo1230(): scala.Int = { /* compiled code */ } + def foo1231(): scala.Int = { /* compiled code */ } + def foo1232(): scala.Int = { /* compiled code */ } + def foo1233(): scala.Int = { /* compiled code */ } + def foo1234(): scala.Int = { /* compiled code */ } + def foo1235(): scala.Int = { /* compiled code */ } + def foo1236(): scala.Int = { /* compiled code */ } + def foo1237(): scala.Int = { /* compiled code */ } + def foo1238(): scala.Int = { /* compiled code */ } + def foo1239(): scala.Int = { /* compiled code */ } + def foo1240(): scala.Int = { /* compiled code */ } + def foo1241(): scala.Int = { /* compiled code */ } + def foo1242(): scala.Int = { /* compiled code */ } + def foo1243(): scala.Int = { /* compiled code */ } + def foo1244(): scala.Int = { /* compiled code */ } + def foo1245(): scala.Int = { /* compiled code */ } + def foo1246(): scala.Int = { /* compiled code */ } + def foo1247(): scala.Int = { /* compiled code */ } + def foo1248(): scala.Int = { /* compiled code */ } + def foo1249(): scala.Int = { /* compiled code */ } + def foo1250(): scala.Int = { /* compiled code */ } + def foo1251(): scala.Int = { /* compiled code */ } + def foo1252(): scala.Int = { /* compiled code */ } + def foo1253(): scala.Int = { /* compiled code */ } + def foo1254(): scala.Int = { /* compiled code */ } + def foo1255(): scala.Int = { /* compiled code */ } + def foo1256(): scala.Int = { /* compiled code */ } + def foo1257(): scala.Int = { /* compiled code */ } + def foo1258(): scala.Int = { /* compiled code */ } + def foo1259(): scala.Int = { /* compiled code */ } + def foo1260(): scala.Int = { /* compiled code */ } + def foo1261(): scala.Int = { /* compiled code */ } + def foo1262(): scala.Int = { /* compiled code */ } + def foo1263(): scala.Int = { /* compiled code */ } + def foo1264(): scala.Int = { /* compiled code */ } + def foo1265(): scala.Int = { /* compiled code */ } + def foo1266(): scala.Int = { /* compiled code */ } + def foo1267(): scala.Int = { /* compiled code */ } + def foo1268(): scala.Int = { /* compiled code */ } + def foo1269(): scala.Int = { /* compiled code */ } + def foo1270(): scala.Int = { /* compiled code */ } + def foo1271(): scala.Int = { /* compiled code */ } + def foo1272(): scala.Int = { /* compiled code */ } + def foo1273(): scala.Int = { /* compiled code */ } + def foo1274(): scala.Int = { /* compiled code */ } + def foo1275(): scala.Int = { /* compiled code */ } + def foo1276(): scala.Int = { /* compiled code */ } + def foo1277(): scala.Int = { /* compiled code */ } + def foo1278(): scala.Int = { /* compiled code */ } + def foo1279(): scala.Int = { /* compiled code */ } + def foo1280(): scala.Int = { /* compiled code */ } + def foo1281(): scala.Int = { /* compiled code */ } + def foo1282(): scala.Int = { /* compiled code */ } + def foo1283(): scala.Int = { /* compiled code */ } + def foo1284(): scala.Int = { /* compiled code */ } + def foo1285(): scala.Int = { /* compiled code */ } + def foo1286(): scala.Int = { /* compiled code */ } + def foo1287(): scala.Int = { /* compiled code */ } + def foo1288(): scala.Int = { /* compiled code */ } + def foo1289(): scala.Int = { /* compiled code */ } + def foo1290(): scala.Int = { /* compiled code */ } + def foo1291(): scala.Int = { /* compiled code */ } + def foo1292(): scala.Int = { /* compiled code */ } + def foo1293(): scala.Int = { /* compiled code */ } + def foo1294(): scala.Int = { /* compiled code */ } + def foo1295(): scala.Int = { /* compiled code */ } + def foo1296(): scala.Int = { /* compiled code */ } + def foo1297(): scala.Int = { /* compiled code */ } + def foo1298(): scala.Int = { /* compiled code */ } + def foo1299(): scala.Int = { /* compiled code */ } + def foo1300(): scala.Int = { /* compiled code */ } + def foo1301(): scala.Int = { /* compiled code */ } + def foo1302(): scala.Int = { /* compiled code */ } + def foo1303(): scala.Int = { /* compiled code */ } + def foo1304(): scala.Int = { /* compiled code */ } + def foo1305(): scala.Int = { /* compiled code */ } + def foo1306(): scala.Int = { /* compiled code */ } + def foo1307(): scala.Int = { /* compiled code */ } + def foo1308(): scala.Int = { /* compiled code */ } + def foo1309(): scala.Int = { /* compiled code */ } + def foo1310(): scala.Int = { /* compiled code */ } + def foo1311(): scala.Int = { /* compiled code */ } + def foo1312(): scala.Int = { /* compiled code */ } + def foo1313(): scala.Int = { /* compiled code */ } + def foo1314(): scala.Int = { /* compiled code */ } + def foo1315(): scala.Int = { /* compiled code */ } + def foo1316(): scala.Int = { /* compiled code */ } + def foo1317(): scala.Int = { /* compiled code */ } + def foo1318(): scala.Int = { /* compiled code */ } + def foo1319(): scala.Int = { /* compiled code */ } + def foo1320(): scala.Int = { /* compiled code */ } + def foo1321(): scala.Int = { /* compiled code */ } + def foo1322(): scala.Int = { /* compiled code */ } + def foo1323(): scala.Int = { /* compiled code */ } + def foo1324(): scala.Int = { /* compiled code */ } + def foo1325(): scala.Int = { /* compiled code */ } + def foo1326(): scala.Int = { /* compiled code */ } + def foo1327(): scala.Int = { /* compiled code */ } + def foo1328(): scala.Int = { /* compiled code */ } + def foo1329(): scala.Int = { /* compiled code */ } + def foo1330(): scala.Int = { /* compiled code */ } + def foo1331(): scala.Int = { /* compiled code */ } + def foo1332(): scala.Int = { /* compiled code */ } + def foo1333(): scala.Int = { /* compiled code */ } + def foo1334(): scala.Int = { /* compiled code */ } + def foo1335(): scala.Int = { /* compiled code */ } + def foo1336(): scala.Int = { /* compiled code */ } + def foo1337(): scala.Int = { /* compiled code */ } + def foo1338(): scala.Int = { /* compiled code */ } + def foo1339(): scala.Int = { /* compiled code */ } + def foo1340(): scala.Int = { /* compiled code */ } + def foo1341(): scala.Int = { /* compiled code */ } + def foo1342(): scala.Int = { /* compiled code */ } + def foo1343(): scala.Int = { /* compiled code */ } + def foo1344(): scala.Int = { /* compiled code */ } + def foo1345(): scala.Int = { /* compiled code */ } + def foo1346(): scala.Int = { /* compiled code */ } + def foo1347(): scala.Int = { /* compiled code */ } + def foo1348(): scala.Int = { /* compiled code */ } + def foo1349(): scala.Int = { /* compiled code */ } + def foo1350(): scala.Int = { /* compiled code */ } + def foo1351(): scala.Int = { /* compiled code */ } + def foo1352(): scala.Int = { /* compiled code */ } + def foo1353(): scala.Int = { /* compiled code */ } + def foo1354(): scala.Int = { /* compiled code */ } + def foo1355(): scala.Int = { /* compiled code */ } + def foo1356(): scala.Int = { /* compiled code */ } + def foo1357(): scala.Int = { /* compiled code */ } + def foo1358(): scala.Int = { /* compiled code */ } + def foo1359(): scala.Int = { /* compiled code */ } + def foo1360(): scala.Int = { /* compiled code */ } + def foo1361(): scala.Int = { /* compiled code */ } + def foo1362(): scala.Int = { /* compiled code */ } + def foo1363(): scala.Int = { /* compiled code */ } + def foo1364(): scala.Int = { /* compiled code */ } + def foo1365(): scala.Int = { /* compiled code */ } + def foo1366(): scala.Int = { /* compiled code */ } + def foo1367(): scala.Int = { /* compiled code */ } + def foo1368(): scala.Int = { /* compiled code */ } + def foo1369(): scala.Int = { /* compiled code */ } + def foo1370(): scala.Int = { /* compiled code */ } + def foo1371(): scala.Int = { /* compiled code */ } + def foo1372(): scala.Int = { /* compiled code */ } + def foo1373(): scala.Int = { /* compiled code */ } + def foo1374(): scala.Int = { /* compiled code */ } + def foo1375(): scala.Int = { /* compiled code */ } + def foo1376(): scala.Int = { /* compiled code */ } + def foo1377(): scala.Int = { /* compiled code */ } + def foo1378(): scala.Int = { /* compiled code */ } + def foo1379(): scala.Int = { /* compiled code */ } + def foo1380(): scala.Int = { /* compiled code */ } + def foo1381(): scala.Int = { /* compiled code */ } + def foo1382(): scala.Int = { /* compiled code */ } + def foo1383(): scala.Int = { /* compiled code */ } + def foo1384(): scala.Int = { /* compiled code */ } + def foo1385(): scala.Int = { /* compiled code */ } + def foo1386(): scala.Int = { /* compiled code */ } + def foo1387(): scala.Int = { /* compiled code */ } + def foo1388(): scala.Int = { /* compiled code */ } + def foo1389(): scala.Int = { /* compiled code */ } + def foo1390(): scala.Int = { /* compiled code */ } + def foo1391(): scala.Int = { /* compiled code */ } + def foo1392(): scala.Int = { /* compiled code */ } + def foo1393(): scala.Int = { /* compiled code */ } + def foo1394(): scala.Int = { /* compiled code */ } + def foo1395(): scala.Int = { /* compiled code */ } + def foo1396(): scala.Int = { /* compiled code */ } + def foo1397(): scala.Int = { /* compiled code */ } + def foo1398(): scala.Int = { /* compiled code */ } + def foo1399(): scala.Int = { /* compiled code */ } + def foo1400(): scala.Int = { /* compiled code */ } + def foo1401(): scala.Int = { /* compiled code */ } + def foo1402(): scala.Int = { /* compiled code */ } + def foo1403(): scala.Int = { /* compiled code */ } + def foo1404(): scala.Int = { /* compiled code */ } + def foo1405(): scala.Int = { /* compiled code */ } + def foo1406(): scala.Int = { /* compiled code */ } + def foo1407(): scala.Int = { /* compiled code */ } + def foo1408(): scala.Int = { /* compiled code */ } + def foo1409(): scala.Int = { /* compiled code */ } + def foo1410(): scala.Int = { /* compiled code */ } + def foo1411(): scala.Int = { /* compiled code */ } + def foo1412(): scala.Int = { /* compiled code */ } + def foo1413(): scala.Int = { /* compiled code */ } + def foo1414(): scala.Int = { /* compiled code */ } + def foo1415(): scala.Int = { /* compiled code */ } + def foo1416(): scala.Int = { /* compiled code */ } + def foo1417(): scala.Int = { /* compiled code */ } + def foo1418(): scala.Int = { /* compiled code */ } + def foo1419(): scala.Int = { /* compiled code */ } + def foo1420(): scala.Int = { /* compiled code */ } + def foo1421(): scala.Int = { /* compiled code */ } + def foo1422(): scala.Int = { /* compiled code */ } + def foo1423(): scala.Int = { /* compiled code */ } + def foo1424(): scala.Int = { /* compiled code */ } + def foo1425(): scala.Int = { /* compiled code */ } + def foo1426(): scala.Int = { /* compiled code */ } + def foo1427(): scala.Int = { /* compiled code */ } + def foo1428(): scala.Int = { /* compiled code */ } + def foo1429(): scala.Int = { /* compiled code */ } + def foo1430(): scala.Int = { /* compiled code */ } + def foo1431(): scala.Int = { /* compiled code */ } + def foo1432(): scala.Int = { /* compiled code */ } + def foo1433(): scala.Int = { /* compiled code */ } + def foo1434(): scala.Int = { /* compiled code */ } + def foo1435(): scala.Int = { /* compiled code */ } + def foo1436(): scala.Int = { /* compiled code */ } + def foo1437(): scala.Int = { /* compiled code */ } + def foo1438(): scala.Int = { /* compiled code */ } + def foo1439(): scala.Int = { /* compiled code */ } + def foo1440(): scala.Int = { /* compiled code */ } + def foo1441(): scala.Int = { /* compiled code */ } + def foo1442(): scala.Int = { /* compiled code */ } + def foo1443(): scala.Int = { /* compiled code */ } + def foo1444(): scala.Int = { /* compiled code */ } + def foo1445(): scala.Int = { /* compiled code */ } + def foo1446(): scala.Int = { /* compiled code */ } + def foo1447(): scala.Int = { /* compiled code */ } + def foo1448(): scala.Int = { /* compiled code */ } + def foo1449(): scala.Int = { /* compiled code */ } + def foo1450(): scala.Int = { /* compiled code */ } + def foo1451(): scala.Int = { /* compiled code */ } + def foo1452(): scala.Int = { /* compiled code */ } + def foo1453(): scala.Int = { /* compiled code */ } + def foo1454(): scala.Int = { /* compiled code */ } + def foo1455(): scala.Int = { /* compiled code */ } + def foo1456(): scala.Int = { /* compiled code */ } + def foo1457(): scala.Int = { /* compiled code */ } + def foo1458(): scala.Int = { /* compiled code */ } + def foo1459(): scala.Int = { /* compiled code */ } + def foo1460(): scala.Int = { /* compiled code */ } + def foo1461(): scala.Int = { /* compiled code */ } + def foo1462(): scala.Int = { /* compiled code */ } + def foo1463(): scala.Int = { /* compiled code */ } + def foo1464(): scala.Int = { /* compiled code */ } + def foo1465(): scala.Int = { /* compiled code */ } + def foo1466(): scala.Int = { /* compiled code */ } + def foo1467(): scala.Int = { /* compiled code */ } + def foo1468(): scala.Int = { /* compiled code */ } + def foo1469(): scala.Int = { /* compiled code */ } + def foo1470(): scala.Int = { /* compiled code */ } + def foo1471(): scala.Int = { /* compiled code */ } + def foo1472(): scala.Int = { /* compiled code */ } + def foo1473(): scala.Int = { /* compiled code */ } + def foo1474(): scala.Int = { /* compiled code */ } + def foo1475(): scala.Int = { /* compiled code */ } + def foo1476(): scala.Int = { /* compiled code */ } + def foo1477(): scala.Int = { /* compiled code */ } + def foo1478(): scala.Int = { /* compiled code */ } + def foo1479(): scala.Int = { /* compiled code */ } + def foo1480(): scala.Int = { /* compiled code */ } + def foo1481(): scala.Int = { /* compiled code */ } + def foo1482(): scala.Int = { /* compiled code */ } + def foo1483(): scala.Int = { /* compiled code */ } + def foo1484(): scala.Int = { /* compiled code */ } + def foo1485(): scala.Int = { /* compiled code */ } + def foo1486(): scala.Int = { /* compiled code */ } + def foo1487(): scala.Int = { /* compiled code */ } + def foo1488(): scala.Int = { /* compiled code */ } + def foo1489(): scala.Int = { /* compiled code */ } + def foo1490(): scala.Int = { /* compiled code */ } + def foo1491(): scala.Int = { /* compiled code */ } + def foo1492(): scala.Int = { /* compiled code */ } + def foo1493(): scala.Int = { /* compiled code */ } + def foo1494(): scala.Int = { /* compiled code */ } + def foo1495(): scala.Int = { /* compiled code */ } + def foo1496(): scala.Int = { /* compiled code */ } + def foo1497(): scala.Int = { /* compiled code */ } + def foo1498(): scala.Int = { /* compiled code */ } + def foo1499(): scala.Int = { /* compiled code */ } + def foo1500(): scala.Int = { /* compiled code */ } + def foo1501(): scala.Int = { /* compiled code */ } + def foo1502(): scala.Int = { /* compiled code */ } + def foo1503(): scala.Int = { /* compiled code */ } + def foo1504(): scala.Int = { /* compiled code */ } + def foo1505(): scala.Int = { /* compiled code */ } + def foo1506(): scala.Int = { /* compiled code */ } + def foo1507(): scala.Int = { /* compiled code */ } + def foo1508(): scala.Int = { /* compiled code */ } + def foo1509(): scala.Int = { /* compiled code */ } + def foo1510(): scala.Int = { /* compiled code */ } + def foo1511(): scala.Int = { /* compiled code */ } + def foo1512(): scala.Int = { /* compiled code */ } + def foo1513(): scala.Int = { /* compiled code */ } + def foo1514(): scala.Int = { /* compiled code */ } + def foo1515(): scala.Int = { /* compiled code */ } + def foo1516(): scala.Int = { /* compiled code */ } + def foo1517(): scala.Int = { /* compiled code */ } + def foo1518(): scala.Int = { /* compiled code */ } + def foo1519(): scala.Int = { /* compiled code */ } + def foo1520(): scala.Int = { /* compiled code */ } + def foo1521(): scala.Int = { /* compiled code */ } + def foo1522(): scala.Int = { /* compiled code */ } + def foo1523(): scala.Int = { /* compiled code */ } + def foo1524(): scala.Int = { /* compiled code */ } + def foo1525(): scala.Int = { /* compiled code */ } + def foo1526(): scala.Int = { /* compiled code */ } + def foo1527(): scala.Int = { /* compiled code */ } + def foo1528(): scala.Int = { /* compiled code */ } + def foo1529(): scala.Int = { /* compiled code */ } + def foo1530(): scala.Int = { /* compiled code */ } + def foo1531(): scala.Int = { /* compiled code */ } + def foo1532(): scala.Int = { /* compiled code */ } + def foo1533(): scala.Int = { /* compiled code */ } + def foo1534(): scala.Int = { /* compiled code */ } + def foo1535(): scala.Int = { /* compiled code */ } + def foo1536(): scala.Int = { /* compiled code */ } + def foo1537(): scala.Int = { /* compiled code */ } + def foo1538(): scala.Int = { /* compiled code */ } + def foo1539(): scala.Int = { /* compiled code */ } + def foo1540(): scala.Int = { /* compiled code */ } + def foo1541(): scala.Int = { /* compiled code */ } + def foo1542(): scala.Int = { /* compiled code */ } + def foo1543(): scala.Int = { /* compiled code */ } + def foo1544(): scala.Int = { /* compiled code */ } + def foo1545(): scala.Int = { /* compiled code */ } + def foo1546(): scala.Int = { /* compiled code */ } + def foo1547(): scala.Int = { /* compiled code */ } + def foo1548(): scala.Int = { /* compiled code */ } + def foo1549(): scala.Int = { /* compiled code */ } + def foo1550(): scala.Int = { /* compiled code */ } + def foo1551(): scala.Int = { /* compiled code */ } + def foo1552(): scala.Int = { /* compiled code */ } + def foo1553(): scala.Int = { /* compiled code */ } + def foo1554(): scala.Int = { /* compiled code */ } + def foo1555(): scala.Int = { /* compiled code */ } + def foo1556(): scala.Int = { /* compiled code */ } + def foo1557(): scala.Int = { /* compiled code */ } + def foo1558(): scala.Int = { /* compiled code */ } + def foo1559(): scala.Int = { /* compiled code */ } + def foo1560(): scala.Int = { /* compiled code */ } + def foo1561(): scala.Int = { /* compiled code */ } + def foo1562(): scala.Int = { /* compiled code */ } + def foo1563(): scala.Int = { /* compiled code */ } + def foo1564(): scala.Int = { /* compiled code */ } + def foo1565(): scala.Int = { /* compiled code */ } + def foo1566(): scala.Int = { /* compiled code */ } + def foo1567(): scala.Int = { /* compiled code */ } + def foo1568(): scala.Int = { /* compiled code */ } + def foo1569(): scala.Int = { /* compiled code */ } + def foo1570(): scala.Int = { /* compiled code */ } + def foo1571(): scala.Int = { /* compiled code */ } + def foo1572(): scala.Int = { /* compiled code */ } + def foo1573(): scala.Int = { /* compiled code */ } + def foo1574(): scala.Int = { /* compiled code */ } + def foo1575(): scala.Int = { /* compiled code */ } + def foo1576(): scala.Int = { /* compiled code */ } + def foo1577(): scala.Int = { /* compiled code */ } + def foo1578(): scala.Int = { /* compiled code */ } + def foo1579(): scala.Int = { /* compiled code */ } + def foo1580(): scala.Int = { /* compiled code */ } + def foo1581(): scala.Int = { /* compiled code */ } + def foo1582(): scala.Int = { /* compiled code */ } + def foo1583(): scala.Int = { /* compiled code */ } + def foo1584(): scala.Int = { /* compiled code */ } + def foo1585(): scala.Int = { /* compiled code */ } + def foo1586(): scala.Int = { /* compiled code */ } + def foo1587(): scala.Int = { /* compiled code */ } + def foo1588(): scala.Int = { /* compiled code */ } + def foo1589(): scala.Int = { /* compiled code */ } + def foo1590(): scala.Int = { /* compiled code */ } + def foo1591(): scala.Int = { /* compiled code */ } + def foo1592(): scala.Int = { /* compiled code */ } + def foo1593(): scala.Int = { /* compiled code */ } + def foo1594(): scala.Int = { /* compiled code */ } + def foo1595(): scala.Int = { /* compiled code */ } + def foo1596(): scala.Int = { /* compiled code */ } + def foo1597(): scala.Int = { /* compiled code */ } + def foo1598(): scala.Int = { /* compiled code */ } + def foo1599(): scala.Int = { /* compiled code */ } + def foo1600(): scala.Int = { /* compiled code */ } + def foo1601(): scala.Int = { /* compiled code */ } + def foo1602(): scala.Int = { /* compiled code */ } + def foo1603(): scala.Int = { /* compiled code */ } + def foo1604(): scala.Int = { /* compiled code */ } + def foo1605(): scala.Int = { /* compiled code */ } + def foo1606(): scala.Int = { /* compiled code */ } + def foo1607(): scala.Int = { /* compiled code */ } + def foo1608(): scala.Int = { /* compiled code */ } + def foo1609(): scala.Int = { /* compiled code */ } + def foo1610(): scala.Int = { /* compiled code */ } + def foo1611(): scala.Int = { /* compiled code */ } + def foo1612(): scala.Int = { /* compiled code */ } + def foo1613(): scala.Int = { /* compiled code */ } + def foo1614(): scala.Int = { /* compiled code */ } + def foo1615(): scala.Int = { /* compiled code */ } + def foo1616(): scala.Int = { /* compiled code */ } + def foo1617(): scala.Int = { /* compiled code */ } + def foo1618(): scala.Int = { /* compiled code */ } + def foo1619(): scala.Int = { /* compiled code */ } + def foo1620(): scala.Int = { /* compiled code */ } + def foo1621(): scala.Int = { /* compiled code */ } + def foo1622(): scala.Int = { /* compiled code */ } + def foo1623(): scala.Int = { /* compiled code */ } + def foo1624(): scala.Int = { /* compiled code */ } + def foo1625(): scala.Int = { /* compiled code */ } + def foo1626(): scala.Int = { /* compiled code */ } + def foo1627(): scala.Int = { /* compiled code */ } + def foo1628(): scala.Int = { /* compiled code */ } + def foo1629(): scala.Int = { /* compiled code */ } + def foo1630(): scala.Int = { /* compiled code */ } + def foo1631(): scala.Int = { /* compiled code */ } + def foo1632(): scala.Int = { /* compiled code */ } + def foo1633(): scala.Int = { /* compiled code */ } + def foo1634(): scala.Int = { /* compiled code */ } + def foo1635(): scala.Int = { /* compiled code */ } + def foo1636(): scala.Int = { /* compiled code */ } + def foo1637(): scala.Int = { /* compiled code */ } + def foo1638(): scala.Int = { /* compiled code */ } + def foo1639(): scala.Int = { /* compiled code */ } + def foo1640(): scala.Int = { /* compiled code */ } + def foo1641(): scala.Int = { /* compiled code */ } + def foo1642(): scala.Int = { /* compiled code */ } + def foo1643(): scala.Int = { /* compiled code */ } + def foo1644(): scala.Int = { /* compiled code */ } + def foo1645(): scala.Int = { /* compiled code */ } + def foo1646(): scala.Int = { /* compiled code */ } + def foo1647(): scala.Int = { /* compiled code */ } + def foo1648(): scala.Int = { /* compiled code */ } + def foo1649(): scala.Int = { /* compiled code */ } + def foo1650(): scala.Int = { /* compiled code */ } + def foo1651(): scala.Int = { /* compiled code */ } + def foo1652(): scala.Int = { /* compiled code */ } + def foo1653(): scala.Int = { /* compiled code */ } + def foo1654(): scala.Int = { /* compiled code */ } + def foo1655(): scala.Int = { /* compiled code */ } + def foo1656(): scala.Int = { /* compiled code */ } + def foo1657(): scala.Int = { /* compiled code */ } + def foo1658(): scala.Int = { /* compiled code */ } + def foo1659(): scala.Int = { /* compiled code */ } + def foo1660(): scala.Int = { /* compiled code */ } + def foo1661(): scala.Int = { /* compiled code */ } + def foo1662(): scala.Int = { /* compiled code */ } + def foo1663(): scala.Int = { /* compiled code */ } + def foo1664(): scala.Int = { /* compiled code */ } + def foo1665(): scala.Int = { /* compiled code */ } + def foo1666(): scala.Int = { /* compiled code */ } + def foo1667(): scala.Int = { /* compiled code */ } + def foo1668(): scala.Int = { /* compiled code */ } + def foo1669(): scala.Int = { /* compiled code */ } + def foo1670(): scala.Int = { /* compiled code */ } + def foo1671(): scala.Int = { /* compiled code */ } + def foo1672(): scala.Int = { /* compiled code */ } + def foo1673(): scala.Int = { /* compiled code */ } + def foo1674(): scala.Int = { /* compiled code */ } + def foo1675(): scala.Int = { /* compiled code */ } + def foo1676(): scala.Int = { /* compiled code */ } + def foo1677(): scala.Int = { /* compiled code */ } + def foo1678(): scala.Int = { /* compiled code */ } + def foo1679(): scala.Int = { /* compiled code */ } + def foo1680(): scala.Int = { /* compiled code */ } + def foo1681(): scala.Int = { /* compiled code */ } + def foo1682(): scala.Int = { /* compiled code */ } + def foo1683(): scala.Int = { /* compiled code */ } + def foo1684(): scala.Int = { /* compiled code */ } + def foo1685(): scala.Int = { /* compiled code */ } + def foo1686(): scala.Int = { /* compiled code */ } + def foo1687(): scala.Int = { /* compiled code */ } + def foo1688(): scala.Int = { /* compiled code */ } + def foo1689(): scala.Int = { /* compiled code */ } + def foo1690(): scala.Int = { /* compiled code */ } + def foo1691(): scala.Int = { /* compiled code */ } + def foo1692(): scala.Int = { /* compiled code */ } + def foo1693(): scala.Int = { /* compiled code */ } + def foo1694(): scala.Int = { /* compiled code */ } + def foo1695(): scala.Int = { /* compiled code */ } + def foo1696(): scala.Int = { /* compiled code */ } + def foo1697(): scala.Int = { /* compiled code */ } + def foo1698(): scala.Int = { /* compiled code */ } + def foo1699(): scala.Int = { /* compiled code */ } + def foo1700(): scala.Int = { /* compiled code */ } + def foo1701(): scala.Int = { /* compiled code */ } + def foo1702(): scala.Int = { /* compiled code */ } + def foo1703(): scala.Int = { /* compiled code */ } + def foo1704(): scala.Int = { /* compiled code */ } + def foo1705(): scala.Int = { /* compiled code */ } + def foo1706(): scala.Int = { /* compiled code */ } + def foo1707(): scala.Int = { /* compiled code */ } + def foo1708(): scala.Int = { /* compiled code */ } + def foo1709(): scala.Int = { /* compiled code */ } + def foo1710(): scala.Int = { /* compiled code */ } + def foo1711(): scala.Int = { /* compiled code */ } + def foo1712(): scala.Int = { /* compiled code */ } + def foo1713(): scala.Int = { /* compiled code */ } + def foo1714(): scala.Int = { /* compiled code */ } + def foo1715(): scala.Int = { /* compiled code */ } + def foo1716(): scala.Int = { /* compiled code */ } + def foo1717(): scala.Int = { /* compiled code */ } + def foo1718(): scala.Int = { /* compiled code */ } + def foo1719(): scala.Int = { /* compiled code */ } + def foo1720(): scala.Int = { /* compiled code */ } + def foo1721(): scala.Int = { /* compiled code */ } + def foo1722(): scala.Int = { /* compiled code */ } + def foo1723(): scala.Int = { /* compiled code */ } + def foo1724(): scala.Int = { /* compiled code */ } + def foo1725(): scala.Int = { /* compiled code */ } + def foo1726(): scala.Int = { /* compiled code */ } + def foo1727(): scala.Int = { /* compiled code */ } + def foo1728(): scala.Int = { /* compiled code */ } + def foo1729(): scala.Int = { /* compiled code */ } + def foo1730(): scala.Int = { /* compiled code */ } + def foo1731(): scala.Int = { /* compiled code */ } + def foo1732(): scala.Int = { /* compiled code */ } + def foo1733(): scala.Int = { /* compiled code */ } + def foo1734(): scala.Int = { /* compiled code */ } + def foo1735(): scala.Int = { /* compiled code */ } + def foo1736(): scala.Int = { /* compiled code */ } + def foo1737(): scala.Int = { /* compiled code */ } + def foo1738(): scala.Int = { /* compiled code */ } + def foo1739(): scala.Int = { /* compiled code */ } + def foo1740(): scala.Int = { /* compiled code */ } + def foo1741(): scala.Int = { /* compiled code */ } + def foo1742(): scala.Int = { /* compiled code */ } + def foo1743(): scala.Int = { /* compiled code */ } + def foo1744(): scala.Int = { /* compiled code */ } + def foo1745(): scala.Int = { /* compiled code */ } + def foo1746(): scala.Int = { /* compiled code */ } + def foo1747(): scala.Int = { /* compiled code */ } + def foo1748(): scala.Int = { /* compiled code */ } + def foo1749(): scala.Int = { /* compiled code */ } + def foo1750(): scala.Int = { /* compiled code */ } + def foo1751(): scala.Int = { /* compiled code */ } + def foo1752(): scala.Int = { /* compiled code */ } + def foo1753(): scala.Int = { /* compiled code */ } + def foo1754(): scala.Int = { /* compiled code */ } + def foo1755(): scala.Int = { /* compiled code */ } + def foo1756(): scala.Int = { /* compiled code */ } + def foo1757(): scala.Int = { /* compiled code */ } + def foo1758(): scala.Int = { /* compiled code */ } + def foo1759(): scala.Int = { /* compiled code */ } + def foo1760(): scala.Int = { /* compiled code */ } + def foo1761(): scala.Int = { /* compiled code */ } + def foo1762(): scala.Int = { /* compiled code */ } + def foo1763(): scala.Int = { /* compiled code */ } + def foo1764(): scala.Int = { /* compiled code */ } + def foo1765(): scala.Int = { /* compiled code */ } + def foo1766(): scala.Int = { /* compiled code */ } + def foo1767(): scala.Int = { /* compiled code */ } + def foo1768(): scala.Int = { /* compiled code */ } + def foo1769(): scala.Int = { /* compiled code */ } + def foo1770(): scala.Int = { /* compiled code */ } + def foo1771(): scala.Int = { /* compiled code */ } + def foo1772(): scala.Int = { /* compiled code */ } + def foo1773(): scala.Int = { /* compiled code */ } + def foo1774(): scala.Int = { /* compiled code */ } + def foo1775(): scala.Int = { /* compiled code */ } + def foo1776(): scala.Int = { /* compiled code */ } + def foo1777(): scala.Int = { /* compiled code */ } + def foo1778(): scala.Int = { /* compiled code */ } + def foo1779(): scala.Int = { /* compiled code */ } + def foo1780(): scala.Int = { /* compiled code */ } + def foo1781(): scala.Int = { /* compiled code */ } + def foo1782(): scala.Int = { /* compiled code */ } + def foo1783(): scala.Int = { /* compiled code */ } + def foo1784(): scala.Int = { /* compiled code */ } + def foo1785(): scala.Int = { /* compiled code */ } + def foo1786(): scala.Int = { /* compiled code */ } + def foo1787(): scala.Int = { /* compiled code */ } + def foo1788(): scala.Int = { /* compiled code */ } + def foo1789(): scala.Int = { /* compiled code */ } + def foo1790(): scala.Int = { /* compiled code */ } + def foo1791(): scala.Int = { /* compiled code */ } + def foo1792(): scala.Int = { /* compiled code */ } + def foo1793(): scala.Int = { /* compiled code */ } + def foo1794(): scala.Int = { /* compiled code */ } + def foo1795(): scala.Int = { /* compiled code */ } + def foo1796(): scala.Int = { /* compiled code */ } + def foo1797(): scala.Int = { /* compiled code */ } + def foo1798(): scala.Int = { /* compiled code */ } + def foo1799(): scala.Int = { /* compiled code */ } + def foo1800(): scala.Int = { /* compiled code */ } + def foo1801(): scala.Int = { /* compiled code */ } + def foo1802(): scala.Int = { /* compiled code */ } + def foo1803(): scala.Int = { /* compiled code */ } + def foo1804(): scala.Int = { /* compiled code */ } + def foo1805(): scala.Int = { /* compiled code */ } + def foo1806(): scala.Int = { /* compiled code */ } + def foo1807(): scala.Int = { /* compiled code */ } + def foo1808(): scala.Int = { /* compiled code */ } + def foo1809(): scala.Int = { /* compiled code */ } + def foo1810(): scala.Int = { /* compiled code */ } + def foo1811(): scala.Int = { /* compiled code */ } + def foo1812(): scala.Int = { /* compiled code */ } + def foo1813(): scala.Int = { /* compiled code */ } + def foo1814(): scala.Int = { /* compiled code */ } + def foo1815(): scala.Int = { /* compiled code */ } + def foo1816(): scala.Int = { /* compiled code */ } + def foo1817(): scala.Int = { /* compiled code */ } + def foo1818(): scala.Int = { /* compiled code */ } + def foo1819(): scala.Int = { /* compiled code */ } + def foo1820(): scala.Int = { /* compiled code */ } + def foo1821(): scala.Int = { /* compiled code */ } + def foo1822(): scala.Int = { /* compiled code */ } + def foo1823(): scala.Int = { /* compiled code */ } + def foo1824(): scala.Int = { /* compiled code */ } + def foo1825(): scala.Int = { /* compiled code */ } + def foo1826(): scala.Int = { /* compiled code */ } + def foo1827(): scala.Int = { /* compiled code */ } + def foo1828(): scala.Int = { /* compiled code */ } + def foo1829(): scala.Int = { /* compiled code */ } + def foo1830(): scala.Int = { /* compiled code */ } + def foo1831(): scala.Int = { /* compiled code */ } + def foo1832(): scala.Int = { /* compiled code */ } + def foo1833(): scala.Int = { /* compiled code */ } + def foo1834(): scala.Int = { /* compiled code */ } + def foo1835(): scala.Int = { /* compiled code */ } + def foo1836(): scala.Int = { /* compiled code */ } + def foo1837(): scala.Int = { /* compiled code */ } + def foo1838(): scala.Int = { /* compiled code */ } + def foo1839(): scala.Int = { /* compiled code */ } + def foo1840(): scala.Int = { /* compiled code */ } + def foo1841(): scala.Int = { /* compiled code */ } + def foo1842(): scala.Int = { /* compiled code */ } + def foo1843(): scala.Int = { /* compiled code */ } + def foo1844(): scala.Int = { /* compiled code */ } + def foo1845(): scala.Int = { /* compiled code */ } + def foo1846(): scala.Int = { /* compiled code */ } + def foo1847(): scala.Int = { /* compiled code */ } + def foo1848(): scala.Int = { /* compiled code */ } + def foo1849(): scala.Int = { /* compiled code */ } + def foo1850(): scala.Int = { /* compiled code */ } + def foo1851(): scala.Int = { /* compiled code */ } + def foo1852(): scala.Int = { /* compiled code */ } + def foo1853(): scala.Int = { /* compiled code */ } + def foo1854(): scala.Int = { /* compiled code */ } + def foo1855(): scala.Int = { /* compiled code */ } + def foo1856(): scala.Int = { /* compiled code */ } + def foo1857(): scala.Int = { /* compiled code */ } + def foo1858(): scala.Int = { /* compiled code */ } + def foo1859(): scala.Int = { /* compiled code */ } + def foo1860(): scala.Int = { /* compiled code */ } + def foo1861(): scala.Int = { /* compiled code */ } + def foo1862(): scala.Int = { /* compiled code */ } + def foo1863(): scala.Int = { /* compiled code */ } + def foo1864(): scala.Int = { /* compiled code */ } + def foo1865(): scala.Int = { /* compiled code */ } + def foo1866(): scala.Int = { /* compiled code */ } + def foo1867(): scala.Int = { /* compiled code */ } + def foo1868(): scala.Int = { /* compiled code */ } + def foo1869(): scala.Int = { /* compiled code */ } + def foo1870(): scala.Int = { /* compiled code */ } + def foo1871(): scala.Int = { /* compiled code */ } + def foo1872(): scala.Int = { /* compiled code */ } + def foo1873(): scala.Int = { /* compiled code */ } + def foo1874(): scala.Int = { /* compiled code */ } + def foo1875(): scala.Int = { /* compiled code */ } + def foo1876(): scala.Int = { /* compiled code */ } + def foo1877(): scala.Int = { /* compiled code */ } + def foo1878(): scala.Int = { /* compiled code */ } + def foo1879(): scala.Int = { /* compiled code */ } + def foo1880(): scala.Int = { /* compiled code */ } + def foo1881(): scala.Int = { /* compiled code */ } + def foo1882(): scala.Int = { /* compiled code */ } + def foo1883(): scala.Int = { /* compiled code */ } + def foo1884(): scala.Int = { /* compiled code */ } + def foo1885(): scala.Int = { /* compiled code */ } + def foo1886(): scala.Int = { /* compiled code */ } + def foo1887(): scala.Int = { /* compiled code */ } + def foo1888(): scala.Int = { /* compiled code */ } + def foo1889(): scala.Int = { /* compiled code */ } + def foo1890(): scala.Int = { /* compiled code */ } + def foo1891(): scala.Int = { /* compiled code */ } + def foo1892(): scala.Int = { /* compiled code */ } + def foo1893(): scala.Int = { /* compiled code */ } + def foo1894(): scala.Int = { /* compiled code */ } + def foo1895(): scala.Int = { /* compiled code */ } + def foo1896(): scala.Int = { /* compiled code */ } + def foo1897(): scala.Int = { /* compiled code */ } + def foo1898(): scala.Int = { /* compiled code */ } + def foo1899(): scala.Int = { /* compiled code */ } + def foo1900(): scala.Int = { /* compiled code */ } + def foo1901(): scala.Int = { /* compiled code */ } + def foo1902(): scala.Int = { /* compiled code */ } + def foo1903(): scala.Int = { /* compiled code */ } + def foo1904(): scala.Int = { /* compiled code */ } + def foo1905(): scala.Int = { /* compiled code */ } + def foo1906(): scala.Int = { /* compiled code */ } + def foo1907(): scala.Int = { /* compiled code */ } + def foo1908(): scala.Int = { /* compiled code */ } + def foo1909(): scala.Int = { /* compiled code */ } + def foo1910(): scala.Int = { /* compiled code */ } + def foo1911(): scala.Int = { /* compiled code */ } + def foo1912(): scala.Int = { /* compiled code */ } + def foo1913(): scala.Int = { /* compiled code */ } + def foo1914(): scala.Int = { /* compiled code */ } + def foo1915(): scala.Int = { /* compiled code */ } + def foo1916(): scala.Int = { /* compiled code */ } + def foo1917(): scala.Int = { /* compiled code */ } + def foo1918(): scala.Int = { /* compiled code */ } + def foo1919(): scala.Int = { /* compiled code */ } + def foo1920(): scala.Int = { /* compiled code */ } + def foo1921(): scala.Int = { /* compiled code */ } + def foo1922(): scala.Int = { /* compiled code */ } + def foo1923(): scala.Int = { /* compiled code */ } + def foo1924(): scala.Int = { /* compiled code */ } + def foo1925(): scala.Int = { /* compiled code */ } + def foo1926(): scala.Int = { /* compiled code */ } + def foo1927(): scala.Int = { /* compiled code */ } + def foo1928(): scala.Int = { /* compiled code */ } + def foo1929(): scala.Int = { /* compiled code */ } + def foo1930(): scala.Int = { /* compiled code */ } + def foo1931(): scala.Int = { /* compiled code */ } + def foo1932(): scala.Int = { /* compiled code */ } + def foo1933(): scala.Int = { /* compiled code */ } + def foo1934(): scala.Int = { /* compiled code */ } + def foo1935(): scala.Int = { /* compiled code */ } + def foo1936(): scala.Int = { /* compiled code */ } + def foo1937(): scala.Int = { /* compiled code */ } + def foo1938(): scala.Int = { /* compiled code */ } + def foo1939(): scala.Int = { /* compiled code */ } + def foo1940(): scala.Int = { /* compiled code */ } + def foo1941(): scala.Int = { /* compiled code */ } + def foo1942(): scala.Int = { /* compiled code */ } + def foo1943(): scala.Int = { /* compiled code */ } + def foo1944(): scala.Int = { /* compiled code */ } + def foo1945(): scala.Int = { /* compiled code */ } + def foo1946(): scala.Int = { /* compiled code */ } + def foo1947(): scala.Int = { /* compiled code */ } + def foo1948(): scala.Int = { /* compiled code */ } + def foo1949(): scala.Int = { /* compiled code */ } + def foo1950(): scala.Int = { /* compiled code */ } + def foo1951(): scala.Int = { /* compiled code */ } + def foo1952(): scala.Int = { /* compiled code */ } + def foo1953(): scala.Int = { /* compiled code */ } + def foo1954(): scala.Int = { /* compiled code */ } + def foo1955(): scala.Int = { /* compiled code */ } + def foo1956(): scala.Int = { /* compiled code */ } + def foo1957(): scala.Int = { /* compiled code */ } + def foo1958(): scala.Int = { /* compiled code */ } + def foo1959(): scala.Int = { /* compiled code */ } + def foo1960(): scala.Int = { /* compiled code */ } + def foo1961(): scala.Int = { /* compiled code */ } + def foo1962(): scala.Int = { /* compiled code */ } + def foo1963(): scala.Int = { /* compiled code */ } + def foo1964(): scala.Int = { /* compiled code */ } + def foo1965(): scala.Int = { /* compiled code */ } + def foo1966(): scala.Int = { /* compiled code */ } + def foo1967(): scala.Int = { /* compiled code */ } + def foo1968(): scala.Int = { /* compiled code */ } + def foo1969(): scala.Int = { /* compiled code */ } + def foo1970(): scala.Int = { /* compiled code */ } + def foo1971(): scala.Int = { /* compiled code */ } + def foo1972(): scala.Int = { /* compiled code */ } + def foo1973(): scala.Int = { /* compiled code */ } + def foo1974(): scala.Int = { /* compiled code */ } + def foo1975(): scala.Int = { /* compiled code */ } + def foo1976(): scala.Int = { /* compiled code */ } + def foo1977(): scala.Int = { /* compiled code */ } + def foo1978(): scala.Int = { /* compiled code */ } + def foo1979(): scala.Int = { /* compiled code */ } + def foo1980(): scala.Int = { /* compiled code */ } + def foo1981(): scala.Int = { /* compiled code */ } + def foo1982(): scala.Int = { /* compiled code */ } + def foo1983(): scala.Int = { /* compiled code */ } + def foo1984(): scala.Int = { /* compiled code */ } + def foo1985(): scala.Int = { /* compiled code */ } + def foo1986(): scala.Int = { /* compiled code */ } + def foo1987(): scala.Int = { /* compiled code */ } + def foo1988(): scala.Int = { /* compiled code */ } + def foo1989(): scala.Int = { /* compiled code */ } + def foo1990(): scala.Int = { /* compiled code */ } + def foo1991(): scala.Int = { /* compiled code */ } + def foo1992(): scala.Int = { /* compiled code */ } + def foo1993(): scala.Int = { /* compiled code */ } + def foo1994(): scala.Int = { /* compiled code */ } + def foo1995(): scala.Int = { /* compiled code */ } + def foo1996(): scala.Int = { /* compiled code */ } + def foo1997(): scala.Int = { /* compiled code */ } + def foo1998(): scala.Int = { /* compiled code */ } + def foo1999(): scala.Int = { /* compiled code */ } + def foo2000(): scala.Int = { /* compiled code */ } + def foo2001(): scala.Int = { /* compiled code */ } + def foo2002(): scala.Int = { /* compiled code */ } + def foo2003(): scala.Int = { /* compiled code */ } + def foo2004(): scala.Int = { /* compiled code */ } + def foo2005(): scala.Int = { /* compiled code */ } + def foo2006(): scala.Int = { /* compiled code */ } + def foo2007(): scala.Int = { /* compiled code */ } + def foo2008(): scala.Int = { /* compiled code */ } + def foo2009(): scala.Int = { /* compiled code */ } + def foo2010(): scala.Int = { /* compiled code */ } + def foo2011(): scala.Int = { /* compiled code */ } + def foo2012(): scala.Int = { /* compiled code */ } + def foo2013(): scala.Int = { /* compiled code */ } + def foo2014(): scala.Int = { /* compiled code */ } + def foo2015(): scala.Int = { /* compiled code */ } + def foo2016(): scala.Int = { /* compiled code */ } + def foo2017(): scala.Int = { /* compiled code */ } + def foo2018(): scala.Int = { /* compiled code */ } + def foo2019(): scala.Int = { /* compiled code */ } + def foo2020(): scala.Int = { /* compiled code */ } + def foo2021(): scala.Int = { /* compiled code */ } + def foo2022(): scala.Int = { /* compiled code */ } + def foo2023(): scala.Int = { /* compiled code */ } + def foo2024(): scala.Int = { /* compiled code */ } + def foo2025(): scala.Int = { /* compiled code */ } + def foo2026(): scala.Int = { /* compiled code */ } + def foo2027(): scala.Int = { /* compiled code */ } + def foo2028(): scala.Int = { /* compiled code */ } + def foo2029(): scala.Int = { /* compiled code */ } + def foo2030(): scala.Int = { /* compiled code */ } + def foo2031(): scala.Int = { /* compiled code */ } + def foo2032(): scala.Int = { /* compiled code */ } + def foo2033(): scala.Int = { /* compiled code */ } + def foo2034(): scala.Int = { /* compiled code */ } + def foo2035(): scala.Int = { /* compiled code */ } + def foo2036(): scala.Int = { /* compiled code */ } + def foo2037(): scala.Int = { /* compiled code */ } + def foo2038(): scala.Int = { /* compiled code */ } + def foo2039(): scala.Int = { /* compiled code */ } + def foo2040(): scala.Int = { /* compiled code */ } + def foo2041(): scala.Int = { /* compiled code */ } + def foo2042(): scala.Int = { /* compiled code */ } + def foo2043(): scala.Int = { /* compiled code */ } + def foo2044(): scala.Int = { /* compiled code */ } + def foo2045(): scala.Int = { /* compiled code */ } + def foo2046(): scala.Int = { /* compiled code */ } + def foo2047(): scala.Int = { /* compiled code */ } + def foo2048(): scala.Int = { /* compiled code */ } + def foo2049(): scala.Int = { /* compiled code */ } + def foo2050(): scala.Int = { /* compiled code */ } + def foo2051(): scala.Int = { /* compiled code */ } + def foo2052(): scala.Int = { /* compiled code */ } + def foo2053(): scala.Int = { /* compiled code */ } + def foo2054(): scala.Int = { /* compiled code */ } + def foo2055(): scala.Int = { /* compiled code */ } + def foo2056(): scala.Int = { /* compiled code */ } + def foo2057(): scala.Int = { /* compiled code */ } + def foo2058(): scala.Int = { /* compiled code */ } + def foo2059(): scala.Int = { /* compiled code */ } + def foo2060(): scala.Int = { /* compiled code */ } + def foo2061(): scala.Int = { /* compiled code */ } + def foo2062(): scala.Int = { /* compiled code */ } + def foo2063(): scala.Int = { /* compiled code */ } + def foo2064(): scala.Int = { /* compiled code */ } + def foo2065(): scala.Int = { /* compiled code */ } + def foo2066(): scala.Int = { /* compiled code */ } + def foo2067(): scala.Int = { /* compiled code */ } + def foo2068(): scala.Int = { /* compiled code */ } + def foo2069(): scala.Int = { /* compiled code */ } + def foo2070(): scala.Int = { /* compiled code */ } + def foo2071(): scala.Int = { /* compiled code */ } + def foo2072(): scala.Int = { /* compiled code */ } + def foo2073(): scala.Int = { /* compiled code */ } + def foo2074(): scala.Int = { /* compiled code */ } + def foo2075(): scala.Int = { /* compiled code */ } + def foo2076(): scala.Int = { /* compiled code */ } + def foo2077(): scala.Int = { /* compiled code */ } + def foo2078(): scala.Int = { /* compiled code */ } + def foo2079(): scala.Int = { /* compiled code */ } + def foo2080(): scala.Int = { /* compiled code */ } + def foo2081(): scala.Int = { /* compiled code */ } + def foo2082(): scala.Int = { /* compiled code */ } + def foo2083(): scala.Int = { /* compiled code */ } + def foo2084(): scala.Int = { /* compiled code */ } + def foo2085(): scala.Int = { /* compiled code */ } + def foo2086(): scala.Int = { /* compiled code */ } + def foo2087(): scala.Int = { /* compiled code */ } + def foo2088(): scala.Int = { /* compiled code */ } + def foo2089(): scala.Int = { /* compiled code */ } + def foo2090(): scala.Int = { /* compiled code */ } + def foo2091(): scala.Int = { /* compiled code */ } + def foo2092(): scala.Int = { /* compiled code */ } + def foo2093(): scala.Int = { /* compiled code */ } + def foo2094(): scala.Int = { /* compiled code */ } + def foo2095(): scala.Int = { /* compiled code */ } + def foo2096(): scala.Int = { /* compiled code */ } + def foo2097(): scala.Int = { /* compiled code */ } + def foo2098(): scala.Int = { /* compiled code */ } + def foo2099(): scala.Int = { /* compiled code */ } + def foo2100(): scala.Int = { /* compiled code */ } + def foo2101(): scala.Int = { /* compiled code */ } + def foo2102(): scala.Int = { /* compiled code */ } + def foo2103(): scala.Int = { /* compiled code */ } + def foo2104(): scala.Int = { /* compiled code */ } + def foo2105(): scala.Int = { /* compiled code */ } + def foo2106(): scala.Int = { /* compiled code */ } + def foo2107(): scala.Int = { /* compiled code */ } + def foo2108(): scala.Int = { /* compiled code */ } + def foo2109(): scala.Int = { /* compiled code */ } + def foo2110(): scala.Int = { /* compiled code */ } + def foo2111(): scala.Int = { /* compiled code */ } + def foo2112(): scala.Int = { /* compiled code */ } + def foo2113(): scala.Int = { /* compiled code */ } + def foo2114(): scala.Int = { /* compiled code */ } + def foo2115(): scala.Int = { /* compiled code */ } + def foo2116(): scala.Int = { /* compiled code */ } + def foo2117(): scala.Int = { /* compiled code */ } + def foo2118(): scala.Int = { /* compiled code */ } + def foo2119(): scala.Int = { /* compiled code */ } + def foo2120(): scala.Int = { /* compiled code */ } + def foo2121(): scala.Int = { /* compiled code */ } + def foo2122(): scala.Int = { /* compiled code */ } + def foo2123(): scala.Int = { /* compiled code */ } + def foo2124(): scala.Int = { /* compiled code */ } + def foo2125(): scala.Int = { /* compiled code */ } + def foo2126(): scala.Int = { /* compiled code */ } + def foo2127(): scala.Int = { /* compiled code */ } + def foo2128(): scala.Int = { /* compiled code */ } + def foo2129(): scala.Int = { /* compiled code */ } + def foo2130(): scala.Int = { /* compiled code */ } + def foo2131(): scala.Int = { /* compiled code */ } + def foo2132(): scala.Int = { /* compiled code */ } + def foo2133(): scala.Int = { /* compiled code */ } + def foo2134(): scala.Int = { /* compiled code */ } + def foo2135(): scala.Int = { /* compiled code */ } + def foo2136(): scala.Int = { /* compiled code */ } + def foo2137(): scala.Int = { /* compiled code */ } + def foo2138(): scala.Int = { /* compiled code */ } + def foo2139(): scala.Int = { /* compiled code */ } + def foo2140(): scala.Int = { /* compiled code */ } + def foo2141(): scala.Int = { /* compiled code */ } + def foo2142(): scala.Int = { /* compiled code */ } + def foo2143(): scala.Int = { /* compiled code */ } + def foo2144(): scala.Int = { /* compiled code */ } + def foo2145(): scala.Int = { /* compiled code */ } + def foo2146(): scala.Int = { /* compiled code */ } + def foo2147(): scala.Int = { /* compiled code */ } + def foo2148(): scala.Int = { /* compiled code */ } + def foo2149(): scala.Int = { /* compiled code */ } + def foo2150(): scala.Int = { /* compiled code */ } + def foo2151(): scala.Int = { /* compiled code */ } + def foo2152(): scala.Int = { /* compiled code */ } + def foo2153(): scala.Int = { /* compiled code */ } + def foo2154(): scala.Int = { /* compiled code */ } + def foo2155(): scala.Int = { /* compiled code */ } + def foo2156(): scala.Int = { /* compiled code */ } + def foo2157(): scala.Int = { /* compiled code */ } + def foo2158(): scala.Int = { /* compiled code */ } + def foo2159(): scala.Int = { /* compiled code */ } + def foo2160(): scala.Int = { /* compiled code */ } + def foo2161(): scala.Int = { /* compiled code */ } + def foo2162(): scala.Int = { /* compiled code */ } + def foo2163(): scala.Int = { /* compiled code */ } + def foo2164(): scala.Int = { /* compiled code */ } + def foo2165(): scala.Int = { /* compiled code */ } + def foo2166(): scala.Int = { /* compiled code */ } + def foo2167(): scala.Int = { /* compiled code */ } + def foo2168(): scala.Int = { /* compiled code */ } + def foo2169(): scala.Int = { /* compiled code */ } + def foo2170(): scala.Int = { /* compiled code */ } + def foo2171(): scala.Int = { /* compiled code */ } + def foo2172(): scala.Int = { /* compiled code */ } + def foo2173(): scala.Int = { /* compiled code */ } + def foo2174(): scala.Int = { /* compiled code */ } + def foo2175(): scala.Int = { /* compiled code */ } + def foo2176(): scala.Int = { /* compiled code */ } + def foo2177(): scala.Int = { /* compiled code */ } + def foo2178(): scala.Int = { /* compiled code */ } + def foo2179(): scala.Int = { /* compiled code */ } + def foo2180(): scala.Int = { /* compiled code */ } + def foo2181(): scala.Int = { /* compiled code */ } + def foo2182(): scala.Int = { /* compiled code */ } + def foo2183(): scala.Int = { /* compiled code */ } + def foo2184(): scala.Int = { /* compiled code */ } + def foo2185(): scala.Int = { /* compiled code */ } + def foo2186(): scala.Int = { /* compiled code */ } + def foo2187(): scala.Int = { /* compiled code */ } + def foo2188(): scala.Int = { /* compiled code */ } + def foo2189(): scala.Int = { /* compiled code */ } + def foo2190(): scala.Int = { /* compiled code */ } + def foo2191(): scala.Int = { /* compiled code */ } + def foo2192(): scala.Int = { /* compiled code */ } + def foo2193(): scala.Int = { /* compiled code */ } + def foo2194(): scala.Int = { /* compiled code */ } + def foo2195(): scala.Int = { /* compiled code */ } + def foo2196(): scala.Int = { /* compiled code */ } + def foo2197(): scala.Int = { /* compiled code */ } + def foo2198(): scala.Int = { /* compiled code */ } + def foo2199(): scala.Int = { /* compiled code */ } + def foo2200(): scala.Int = { /* compiled code */ } + def foo2201(): scala.Int = { /* compiled code */ } + def foo2202(): scala.Int = { /* compiled code */ } + def foo2203(): scala.Int = { /* compiled code */ } + def foo2204(): scala.Int = { /* compiled code */ } + def foo2205(): scala.Int = { /* compiled code */ } + def foo2206(): scala.Int = { /* compiled code */ } + def foo2207(): scala.Int = { /* compiled code */ } + def foo2208(): scala.Int = { /* compiled code */ } + def foo2209(): scala.Int = { /* compiled code */ } + def foo2210(): scala.Int = { /* compiled code */ } + def foo2211(): scala.Int = { /* compiled code */ } + def foo2212(): scala.Int = { /* compiled code */ } + def foo2213(): scala.Int = { /* compiled code */ } + def foo2214(): scala.Int = { /* compiled code */ } + def foo2215(): scala.Int = { /* compiled code */ } + def foo2216(): scala.Int = { /* compiled code */ } + def foo2217(): scala.Int = { /* compiled code */ } + def foo2218(): scala.Int = { /* compiled code */ } + def foo2219(): scala.Int = { /* compiled code */ } + def foo2220(): scala.Int = { /* compiled code */ } + def foo2221(): scala.Int = { /* compiled code */ } + def foo2222(): scala.Int = { /* compiled code */ } + def foo2223(): scala.Int = { /* compiled code */ } + def foo2224(): scala.Int = { /* compiled code */ } + def foo2225(): scala.Int = { /* compiled code */ } + def foo2226(): scala.Int = { /* compiled code */ } + def foo2227(): scala.Int = { /* compiled code */ } + def foo2228(): scala.Int = { /* compiled code */ } + def foo2229(): scala.Int = { /* compiled code */ } + def foo2230(): scala.Int = { /* compiled code */ } + def foo2231(): scala.Int = { /* compiled code */ } + def foo2232(): scala.Int = { /* compiled code */ } + def foo2233(): scala.Int = { /* compiled code */ } + def foo2234(): scala.Int = { /* compiled code */ } + def foo2235(): scala.Int = { /* compiled code */ } + def foo2236(): scala.Int = { /* compiled code */ } + def foo2237(): scala.Int = { /* compiled code */ } + def foo2238(): scala.Int = { /* compiled code */ } + def foo2239(): scala.Int = { /* compiled code */ } + def foo2240(): scala.Int = { /* compiled code */ } + def foo2241(): scala.Int = { /* compiled code */ } + def foo2242(): scala.Int = { /* compiled code */ } + def foo2243(): scala.Int = { /* compiled code */ } + def foo2244(): scala.Int = { /* compiled code */ } + def foo2245(): scala.Int = { /* compiled code */ } + def foo2246(): scala.Int = { /* compiled code */ } + def foo2247(): scala.Int = { /* compiled code */ } + def foo2248(): scala.Int = { /* compiled code */ } + def foo2249(): scala.Int = { /* compiled code */ } + def foo2250(): scala.Int = { /* compiled code */ } + def foo2251(): scala.Int = { /* compiled code */ } + def foo2252(): scala.Int = { /* compiled code */ } + def foo2253(): scala.Int = { /* compiled code */ } + def foo2254(): scala.Int = { /* compiled code */ } + def foo2255(): scala.Int = { /* compiled code */ } + def foo2256(): scala.Int = { /* compiled code */ } + def foo2257(): scala.Int = { /* compiled code */ } + def foo2258(): scala.Int = { /* compiled code */ } + def foo2259(): scala.Int = { /* compiled code */ } + def foo2260(): scala.Int = { /* compiled code */ } + def foo2261(): scala.Int = { /* compiled code */ } + def foo2262(): scala.Int = { /* compiled code */ } + def foo2263(): scala.Int = { /* compiled code */ } + def foo2264(): scala.Int = { /* compiled code */ } + def foo2265(): scala.Int = { /* compiled code */ } + def foo2266(): scala.Int = { /* compiled code */ } + def foo2267(): scala.Int = { /* compiled code */ } + def foo2268(): scala.Int = { /* compiled code */ } + def foo2269(): scala.Int = { /* compiled code */ } + def foo2270(): scala.Int = { /* compiled code */ } + def foo2271(): scala.Int = { /* compiled code */ } + def foo2272(): scala.Int = { /* compiled code */ } + def foo2273(): scala.Int = { /* compiled code */ } + def foo2274(): scala.Int = { /* compiled code */ } + def foo2275(): scala.Int = { /* compiled code */ } + def foo2276(): scala.Int = { /* compiled code */ } + def foo2277(): scala.Int = { /* compiled code */ } + def foo2278(): scala.Int = { /* compiled code */ } + def foo2279(): scala.Int = { /* compiled code */ } + def foo2280(): scala.Int = { /* compiled code */ } + def foo2281(): scala.Int = { /* compiled code */ } + def foo2282(): scala.Int = { /* compiled code */ } + def foo2283(): scala.Int = { /* compiled code */ } + def foo2284(): scala.Int = { /* compiled code */ } + def foo2285(): scala.Int = { /* compiled code */ } + def foo2286(): scala.Int = { /* compiled code */ } + def foo2287(): scala.Int = { /* compiled code */ } + def foo2288(): scala.Int = { /* compiled code */ } + def foo2289(): scala.Int = { /* compiled code */ } + def foo2290(): scala.Int = { /* compiled code */ } + def foo2291(): scala.Int = { /* compiled code */ } + def foo2292(): scala.Int = { /* compiled code */ } + def foo2293(): scala.Int = { /* compiled code */ } + def foo2294(): scala.Int = { /* compiled code */ } + def foo2295(): scala.Int = { /* compiled code */ } + def foo2296(): scala.Int = { /* compiled code */ } + def foo2297(): scala.Int = { /* compiled code */ } + def foo2298(): scala.Int = { /* compiled code */ } + def foo2299(): scala.Int = { /* compiled code */ } + def foo2300(): scala.Int = { /* compiled code */ } + def foo2301(): scala.Int = { /* compiled code */ } + def foo2302(): scala.Int = { /* compiled code */ } + def foo2303(): scala.Int = { /* compiled code */ } + def foo2304(): scala.Int = { /* compiled code */ } + def foo2305(): scala.Int = { /* compiled code */ } + def foo2306(): scala.Int = { /* compiled code */ } + def foo2307(): scala.Int = { /* compiled code */ } + def foo2308(): scala.Int = { /* compiled code */ } + def foo2309(): scala.Int = { /* compiled code */ } + def foo2310(): scala.Int = { /* compiled code */ } + def foo2311(): scala.Int = { /* compiled code */ } + def foo2312(): scala.Int = { /* compiled code */ } + def foo2313(): scala.Int = { /* compiled code */ } + def foo2314(): scala.Int = { /* compiled code */ } + def foo2315(): scala.Int = { /* compiled code */ } + def foo2316(): scala.Int = { /* compiled code */ } + def foo2317(): scala.Int = { /* compiled code */ } + def foo2318(): scala.Int = { /* compiled code */ } + def foo2319(): scala.Int = { /* compiled code */ } + def foo2320(): scala.Int = { /* compiled code */ } + def foo2321(): scala.Int = { /* compiled code */ } + def foo2322(): scala.Int = { /* compiled code */ } + def foo2323(): scala.Int = { /* compiled code */ } + def foo2324(): scala.Int = { /* compiled code */ } + def foo2325(): scala.Int = { /* compiled code */ } + def foo2326(): scala.Int = { /* compiled code */ } + def foo2327(): scala.Int = { /* compiled code */ } + def foo2328(): scala.Int = { /* compiled code */ } + def foo2329(): scala.Int = { /* compiled code */ } + def foo2330(): scala.Int = { /* compiled code */ } + def foo2331(): scala.Int = { /* compiled code */ } + def foo2332(): scala.Int = { /* compiled code */ } + def foo2333(): scala.Int = { /* compiled code */ } + def foo2334(): scala.Int = { /* compiled code */ } + def foo2335(): scala.Int = { /* compiled code */ } + def foo2336(): scala.Int = { /* compiled code */ } + def foo2337(): scala.Int = { /* compiled code */ } + def foo2338(): scala.Int = { /* compiled code */ } + def foo2339(): scala.Int = { /* compiled code */ } + def foo2340(): scala.Int = { /* compiled code */ } + def foo2341(): scala.Int = { /* compiled code */ } + def foo2342(): scala.Int = { /* compiled code */ } + def foo2343(): scala.Int = { /* compiled code */ } + def foo2344(): scala.Int = { /* compiled code */ } + def foo2345(): scala.Int = { /* compiled code */ } + def foo2346(): scala.Int = { /* compiled code */ } + def foo2347(): scala.Int = { /* compiled code */ } + def foo2348(): scala.Int = { /* compiled code */ } + def foo2349(): scala.Int = { /* compiled code */ } + def foo2350(): scala.Int = { /* compiled code */ } + def foo2351(): scala.Int = { /* compiled code */ } + def foo2352(): scala.Int = { /* compiled code */ } + def foo2353(): scala.Int = { /* compiled code */ } + def foo2354(): scala.Int = { /* compiled code */ } + def foo2355(): scala.Int = { /* compiled code */ } + def foo2356(): scala.Int = { /* compiled code */ } + def foo2357(): scala.Int = { /* compiled code */ } + def foo2358(): scala.Int = { /* compiled code */ } + def foo2359(): scala.Int = { /* compiled code */ } + def foo2360(): scala.Int = { /* compiled code */ } + def foo2361(): scala.Int = { /* compiled code */ } + def foo2362(): scala.Int = { /* compiled code */ } + def foo2363(): scala.Int = { /* compiled code */ } + def foo2364(): scala.Int = { /* compiled code */ } + def foo2365(): scala.Int = { /* compiled code */ } + def foo2366(): scala.Int = { /* compiled code */ } + def foo2367(): scala.Int = { /* compiled code */ } + def foo2368(): scala.Int = { /* compiled code */ } + def foo2369(): scala.Int = { /* compiled code */ } + def foo2370(): scala.Int = { /* compiled code */ } + def foo2371(): scala.Int = { /* compiled code */ } + def foo2372(): scala.Int = { /* compiled code */ } + def foo2373(): scala.Int = { /* compiled code */ } + def foo2374(): scala.Int = { /* compiled code */ } + def foo2375(): scala.Int = { /* compiled code */ } + def foo2376(): scala.Int = { /* compiled code */ } + def foo2377(): scala.Int = { /* compiled code */ } + def foo2378(): scala.Int = { /* compiled code */ } + def foo2379(): scala.Int = { /* compiled code */ } + def foo2380(): scala.Int = { /* compiled code */ } + def foo2381(): scala.Int = { /* compiled code */ } + def foo2382(): scala.Int = { /* compiled code */ } + def foo2383(): scala.Int = { /* compiled code */ } + def foo2384(): scala.Int = { /* compiled code */ } + def foo2385(): scala.Int = { /* compiled code */ } + def foo2386(): scala.Int = { /* compiled code */ } + def foo2387(): scala.Int = { /* compiled code */ } + def foo2388(): scala.Int = { /* compiled code */ } + def foo2389(): scala.Int = { /* compiled code */ } + def foo2390(): scala.Int = { /* compiled code */ } + def foo2391(): scala.Int = { /* compiled code */ } + def foo2392(): scala.Int = { /* compiled code */ } + def foo2393(): scala.Int = { /* compiled code */ } + def foo2394(): scala.Int = { /* compiled code */ } + def foo2395(): scala.Int = { /* compiled code */ } + def foo2396(): scala.Int = { /* compiled code */ } + def foo2397(): scala.Int = { /* compiled code */ } + def foo2398(): scala.Int = { /* compiled code */ } + def foo2399(): scala.Int = { /* compiled code */ } + def foo2400(): scala.Int = { /* compiled code */ } + def foo2401(): scala.Int = { /* compiled code */ } + def foo2402(): scala.Int = { /* compiled code */ } + def foo2403(): scala.Int = { /* compiled code */ } + def foo2404(): scala.Int = { /* compiled code */ } + def foo2405(): scala.Int = { /* compiled code */ } + def foo2406(): scala.Int = { /* compiled code */ } + def foo2407(): scala.Int = { /* compiled code */ } + def foo2408(): scala.Int = { /* compiled code */ } + def foo2409(): scala.Int = { /* compiled code */ } + def foo2410(): scala.Int = { /* compiled code */ } + def foo2411(): scala.Int = { /* compiled code */ } + def foo2412(): scala.Int = { /* compiled code */ } + def foo2413(): scala.Int = { /* compiled code */ } + def foo2414(): scala.Int = { /* compiled code */ } + def foo2415(): scala.Int = { /* compiled code */ } + def foo2416(): scala.Int = { /* compiled code */ } + def foo2417(): scala.Int = { /* compiled code */ } + def foo2418(): scala.Int = { /* compiled code */ } + def foo2419(): scala.Int = { /* compiled code */ } + def foo2420(): scala.Int = { /* compiled code */ } + def foo2421(): scala.Int = { /* compiled code */ } + def foo2422(): scala.Int = { /* compiled code */ } + def foo2423(): scala.Int = { /* compiled code */ } + def foo2424(): scala.Int = { /* compiled code */ } + def foo2425(): scala.Int = { /* compiled code */ } + def foo2426(): scala.Int = { /* compiled code */ } + def foo2427(): scala.Int = { /* compiled code */ } + def foo2428(): scala.Int = { /* compiled code */ } + def foo2429(): scala.Int = { /* compiled code */ } + def foo2430(): scala.Int = { /* compiled code */ } + def foo2431(): scala.Int = { /* compiled code */ } + def foo2432(): scala.Int = { /* compiled code */ } + def foo2433(): scala.Int = { /* compiled code */ } + def foo2434(): scala.Int = { /* compiled code */ } + def foo2435(): scala.Int = { /* compiled code */ } + def foo2436(): scala.Int = { /* compiled code */ } + def foo2437(): scala.Int = { /* compiled code */ } + def foo2438(): scala.Int = { /* compiled code */ } + def foo2439(): scala.Int = { /* compiled code */ } + def foo2440(): scala.Int = { /* compiled code */ } + def foo2441(): scala.Int = { /* compiled code */ } + def foo2442(): scala.Int = { /* compiled code */ } + def foo2443(): scala.Int = { /* compiled code */ } + def foo2444(): scala.Int = { /* compiled code */ } + def foo2445(): scala.Int = { /* compiled code */ } + def foo2446(): scala.Int = { /* compiled code */ } + def foo2447(): scala.Int = { /* compiled code */ } + def foo2448(): scala.Int = { /* compiled code */ } + def foo2449(): scala.Int = { /* compiled code */ } + def foo2450(): scala.Int = { /* compiled code */ } + def foo2451(): scala.Int = { /* compiled code */ } + def foo2452(): scala.Int = { /* compiled code */ } + def foo2453(): scala.Int = { /* compiled code */ } + def foo2454(): scala.Int = { /* compiled code */ } + def foo2455(): scala.Int = { /* compiled code */ } + def foo2456(): scala.Int = { /* compiled code */ } + def foo2457(): scala.Int = { /* compiled code */ } + def foo2458(): scala.Int = { /* compiled code */ } + def foo2459(): scala.Int = { /* compiled code */ } + def foo2460(): scala.Int = { /* compiled code */ } + def foo2461(): scala.Int = { /* compiled code */ } + def foo2462(): scala.Int = { /* compiled code */ } + def foo2463(): scala.Int = { /* compiled code */ } + def foo2464(): scala.Int = { /* compiled code */ } + def foo2465(): scala.Int = { /* compiled code */ } + def foo2466(): scala.Int = { /* compiled code */ } + def foo2467(): scala.Int = { /* compiled code */ } + def foo2468(): scala.Int = { /* compiled code */ } + def foo2469(): scala.Int = { /* compiled code */ } + def foo2470(): scala.Int = { /* compiled code */ } + def foo2471(): scala.Int = { /* compiled code */ } + def foo2472(): scala.Int = { /* compiled code */ } + def foo2473(): scala.Int = { /* compiled code */ } + def foo2474(): scala.Int = { /* compiled code */ } + def foo2475(): scala.Int = { /* compiled code */ } + def foo2476(): scala.Int = { /* compiled code */ } + def foo2477(): scala.Int = { /* compiled code */ } + def foo2478(): scala.Int = { /* compiled code */ } + def foo2479(): scala.Int = { /* compiled code */ } + def foo2480(): scala.Int = { /* compiled code */ } + def foo2481(): scala.Int = { /* compiled code */ } + def foo2482(): scala.Int = { /* compiled code */ } + def foo2483(): scala.Int = { /* compiled code */ } + def foo2484(): scala.Int = { /* compiled code */ } + def foo2485(): scala.Int = { /* compiled code */ } + def foo2486(): scala.Int = { /* compiled code */ } + def foo2487(): scala.Int = { /* compiled code */ } + def foo2488(): scala.Int = { /* compiled code */ } + def foo2489(): scala.Int = { /* compiled code */ } + def foo2490(): scala.Int = { /* compiled code */ } + def foo2491(): scala.Int = { /* compiled code */ } + def foo2492(): scala.Int = { /* compiled code */ } + def foo2493(): scala.Int = { /* compiled code */ } + def foo2494(): scala.Int = { /* compiled code */ } + def foo2495(): scala.Int = { /* compiled code */ } + def foo2496(): scala.Int = { /* compiled code */ } + def foo2497(): scala.Int = { /* compiled code */ } + def foo2498(): scala.Int = { /* compiled code */ } + def foo2499(): scala.Int = { /* compiled code */ } + def foo2500(): scala.Int = { /* compiled code */ } + def foo2501(): scala.Int = { /* compiled code */ } + def foo2502(): scala.Int = { /* compiled code */ } + def foo2503(): scala.Int = { /* compiled code */ } + def foo2504(): scala.Int = { /* compiled code */ } + def foo2505(): scala.Int = { /* compiled code */ } + def foo2506(): scala.Int = { /* compiled code */ } + def foo2507(): scala.Int = { /* compiled code */ } + def foo2508(): scala.Int = { /* compiled code */ } + def foo2509(): scala.Int = { /* compiled code */ } + def foo2510(): scala.Int = { /* compiled code */ } + def foo2511(): scala.Int = { /* compiled code */ } + def foo2512(): scala.Int = { /* compiled code */ } + def foo2513(): scala.Int = { /* compiled code */ } + def foo2514(): scala.Int = { /* compiled code */ } + def foo2515(): scala.Int = { /* compiled code */ } + def foo2516(): scala.Int = { /* compiled code */ } + def foo2517(): scala.Int = { /* compiled code */ } + def foo2518(): scala.Int = { /* compiled code */ } + def foo2519(): scala.Int = { /* compiled code */ } + def foo2520(): scala.Int = { /* compiled code */ } + def foo2521(): scala.Int = { /* compiled code */ } + def foo2522(): scala.Int = { /* compiled code */ } + def foo2523(): scala.Int = { /* compiled code */ } + def foo2524(): scala.Int = { /* compiled code */ } + def foo2525(): scala.Int = { /* compiled code */ } + def foo2526(): scala.Int = { /* compiled code */ } + def foo2527(): scala.Int = { /* compiled code */ } + def foo2528(): scala.Int = { /* compiled code */ } + def foo2529(): scala.Int = { /* compiled code */ } + def foo2530(): scala.Int = { /* compiled code */ } + def foo2531(): scala.Int = { /* compiled code */ } + def foo2532(): scala.Int = { /* compiled code */ } + def foo2533(): scala.Int = { /* compiled code */ } + def foo2534(): scala.Int = { /* compiled code */ } + def foo2535(): scala.Int = { /* compiled code */ } + def foo2536(): scala.Int = { /* compiled code */ } + def foo2537(): scala.Int = { /* compiled code */ } + def foo2538(): scala.Int = { /* compiled code */ } + def foo2539(): scala.Int = { /* compiled code */ } + def foo2540(): scala.Int = { /* compiled code */ } + def foo2541(): scala.Int = { /* compiled code */ } + def foo2542(): scala.Int = { /* compiled code */ } + def foo2543(): scala.Int = { /* compiled code */ } + def foo2544(): scala.Int = { /* compiled code */ } + def foo2545(): scala.Int = { /* compiled code */ } + def foo2546(): scala.Int = { /* compiled code */ } + def foo2547(): scala.Int = { /* compiled code */ } + def foo2548(): scala.Int = { /* compiled code */ } + def foo2549(): scala.Int = { /* compiled code */ } + def foo2550(): scala.Int = { /* compiled code */ } + def foo2551(): scala.Int = { /* compiled code */ } + def foo2552(): scala.Int = { /* compiled code */ } + def foo2553(): scala.Int = { /* compiled code */ } + def foo2554(): scala.Int = { /* compiled code */ } + def foo2555(): scala.Int = { /* compiled code */ } + def foo2556(): scala.Int = { /* compiled code */ } + def foo2557(): scala.Int = { /* compiled code */ } + def foo2558(): scala.Int = { /* compiled code */ } + def foo2559(): scala.Int = { /* compiled code */ } + def foo2560(): scala.Int = { /* compiled code */ } + def foo2561(): scala.Int = { /* compiled code */ } + def foo2562(): scala.Int = { /* compiled code */ } + def foo2563(): scala.Int = { /* compiled code */ } + def foo2564(): scala.Int = { /* compiled code */ } + def foo2565(): scala.Int = { /* compiled code */ } + def foo2566(): scala.Int = { /* compiled code */ } + def foo2567(): scala.Int = { /* compiled code */ } + def foo2568(): scala.Int = { /* compiled code */ } + def foo2569(): scala.Int = { /* compiled code */ } + def foo2570(): scala.Int = { /* compiled code */ } + def foo2571(): scala.Int = { /* compiled code */ } + def foo2572(): scala.Int = { /* compiled code */ } + def foo2573(): scala.Int = { /* compiled code */ } + def foo2574(): scala.Int = { /* compiled code */ } + def foo2575(): scala.Int = { /* compiled code */ } + def foo2576(): scala.Int = { /* compiled code */ } + def foo2577(): scala.Int = { /* compiled code */ } + def foo2578(): scala.Int = { /* compiled code */ } + def foo2579(): scala.Int = { /* compiled code */ } + def foo2580(): scala.Int = { /* compiled code */ } + def foo2581(): scala.Int = { /* compiled code */ } + def foo2582(): scala.Int = { /* compiled code */ } + def foo2583(): scala.Int = { /* compiled code */ } + def foo2584(): scala.Int = { /* compiled code */ } + def foo2585(): scala.Int = { /* compiled code */ } + def foo2586(): scala.Int = { /* compiled code */ } + def foo2587(): scala.Int = { /* compiled code */ } + def foo2588(): scala.Int = { /* compiled code */ } + def foo2589(): scala.Int = { /* compiled code */ } + def foo2590(): scala.Int = { /* compiled code */ } + def foo2591(): scala.Int = { /* compiled code */ } + def foo2592(): scala.Int = { /* compiled code */ } + def foo2593(): scala.Int = { /* compiled code */ } + def foo2594(): scala.Int = { /* compiled code */ } + def foo2595(): scala.Int = { /* compiled code */ } + def foo2596(): scala.Int = { /* compiled code */ } + def foo2597(): scala.Int = { /* compiled code */ } + def foo2598(): scala.Int = { /* compiled code */ } + def foo2599(): scala.Int = { /* compiled code */ } + def foo2600(): scala.Int = { /* compiled code */ } + def foo2601(): scala.Int = { /* compiled code */ } + def foo2602(): scala.Int = { /* compiled code */ } + def foo2603(): scala.Int = { /* compiled code */ } + def foo2604(): scala.Int = { /* compiled code */ } + def foo2605(): scala.Int = { /* compiled code */ } + def foo2606(): scala.Int = { /* compiled code */ } + def foo2607(): scala.Int = { /* compiled code */ } + def foo2608(): scala.Int = { /* compiled code */ } + def foo2609(): scala.Int = { /* compiled code */ } + def foo2610(): scala.Int = { /* compiled code */ } + def foo2611(): scala.Int = { /* compiled code */ } + def foo2612(): scala.Int = { /* compiled code */ } + def foo2613(): scala.Int = { /* compiled code */ } + def foo2614(): scala.Int = { /* compiled code */ } + def foo2615(): scala.Int = { /* compiled code */ } + def foo2616(): scala.Int = { /* compiled code */ } + def foo2617(): scala.Int = { /* compiled code */ } + def foo2618(): scala.Int = { /* compiled code */ } + def foo2619(): scala.Int = { /* compiled code */ } + def foo2620(): scala.Int = { /* compiled code */ } + def foo2621(): scala.Int = { /* compiled code */ } + def foo2622(): scala.Int = { /* compiled code */ } + def foo2623(): scala.Int = { /* compiled code */ } + def foo2624(): scala.Int = { /* compiled code */ } + def foo2625(): scala.Int = { /* compiled code */ } + def foo2626(): scala.Int = { /* compiled code */ } + def foo2627(): scala.Int = { /* compiled code */ } + def foo2628(): scala.Int = { /* compiled code */ } + def foo2629(): scala.Int = { /* compiled code */ } + def foo2630(): scala.Int = { /* compiled code */ } + def foo2631(): scala.Int = { /* compiled code */ } + def foo2632(): scala.Int = { /* compiled code */ } + def foo2633(): scala.Int = { /* compiled code */ } + def foo2634(): scala.Int = { /* compiled code */ } + def foo2635(): scala.Int = { /* compiled code */ } + def foo2636(): scala.Int = { /* compiled code */ } + def foo2637(): scala.Int = { /* compiled code */ } + def foo2638(): scala.Int = { /* compiled code */ } + def foo2639(): scala.Int = { /* compiled code */ } + def foo2640(): scala.Int = { /* compiled code */ } + def foo2641(): scala.Int = { /* compiled code */ } + def foo2642(): scala.Int = { /* compiled code */ } + def foo2643(): scala.Int = { /* compiled code */ } + def foo2644(): scala.Int = { /* compiled code */ } + def foo2645(): scala.Int = { /* compiled code */ } + def foo2646(): scala.Int = { /* compiled code */ } + def foo2647(): scala.Int = { /* compiled code */ } + def foo2648(): scala.Int = { /* compiled code */ } + def foo2649(): scala.Int = { /* compiled code */ } + def foo2650(): scala.Int = { /* compiled code */ } + def foo2651(): scala.Int = { /* compiled code */ } + def foo2652(): scala.Int = { /* compiled code */ } + def foo2653(): scala.Int = { /* compiled code */ } + def foo2654(): scala.Int = { /* compiled code */ } + def foo2655(): scala.Int = { /* compiled code */ } + def foo2656(): scala.Int = { /* compiled code */ } + def foo2657(): scala.Int = { /* compiled code */ } + def foo2658(): scala.Int = { /* compiled code */ } + def foo2659(): scala.Int = { /* compiled code */ } + def foo2660(): scala.Int = { /* compiled code */ } + def foo2661(): scala.Int = { /* compiled code */ } + def foo2662(): scala.Int = { /* compiled code */ } + def foo2663(): scala.Int = { /* compiled code */ } + def foo2664(): scala.Int = { /* compiled code */ } + def foo2665(): scala.Int = { /* compiled code */ } + def foo2666(): scala.Int = { /* compiled code */ } + def foo2667(): scala.Int = { /* compiled code */ } + def foo2668(): scala.Int = { /* compiled code */ } + def foo2669(): scala.Int = { /* compiled code */ } + def foo2670(): scala.Int = { /* compiled code */ } + def foo2671(): scala.Int = { /* compiled code */ } + def foo2672(): scala.Int = { /* compiled code */ } + def foo2673(): scala.Int = { /* compiled code */ } + def foo2674(): scala.Int = { /* compiled code */ } + def foo2675(): scala.Int = { /* compiled code */ } + def foo2676(): scala.Int = { /* compiled code */ } + def foo2677(): scala.Int = { /* compiled code */ } + def foo2678(): scala.Int = { /* compiled code */ } + def foo2679(): scala.Int = { /* compiled code */ } + def foo2680(): scala.Int = { /* compiled code */ } + def foo2681(): scala.Int = { /* compiled code */ } + def foo2682(): scala.Int = { /* compiled code */ } + def foo2683(): scala.Int = { /* compiled code */ } + def foo2684(): scala.Int = { /* compiled code */ } + def foo2685(): scala.Int = { /* compiled code */ } + def foo2686(): scala.Int = { /* compiled code */ } + def foo2687(): scala.Int = { /* compiled code */ } + def foo2688(): scala.Int = { /* compiled code */ } + def foo2689(): scala.Int = { /* compiled code */ } + def foo2690(): scala.Int = { /* compiled code */ } + def foo2691(): scala.Int = { /* compiled code */ } + def foo2692(): scala.Int = { /* compiled code */ } + def foo2693(): scala.Int = { /* compiled code */ } + def foo2694(): scala.Int = { /* compiled code */ } + def foo2695(): scala.Int = { /* compiled code */ } + def foo2696(): scala.Int = { /* compiled code */ } + def foo2697(): scala.Int = { /* compiled code */ } + def foo2698(): scala.Int = { /* compiled code */ } + def foo2699(): scala.Int = { /* compiled code */ } + def foo2700(): scala.Int = { /* compiled code */ } + def foo2701(): scala.Int = { /* compiled code */ } + def foo2702(): scala.Int = { /* compiled code */ } + def foo2703(): scala.Int = { /* compiled code */ } + def foo2704(): scala.Int = { /* compiled code */ } + def foo2705(): scala.Int = { /* compiled code */ } + def foo2706(): scala.Int = { /* compiled code */ } + def foo2707(): scala.Int = { /* compiled code */ } + def foo2708(): scala.Int = { /* compiled code */ } + def foo2709(): scala.Int = { /* compiled code */ } + def foo2710(): scala.Int = { /* compiled code */ } + def foo2711(): scala.Int = { /* compiled code */ } + def foo2712(): scala.Int = { /* compiled code */ } + def foo2713(): scala.Int = { /* compiled code */ } + def foo2714(): scala.Int = { /* compiled code */ } + def foo2715(): scala.Int = { /* compiled code */ } + def foo2716(): scala.Int = { /* compiled code */ } + def foo2717(): scala.Int = { /* compiled code */ } + def foo2718(): scala.Int = { /* compiled code */ } + def foo2719(): scala.Int = { /* compiled code */ } + def foo2720(): scala.Int = { /* compiled code */ } + def foo2721(): scala.Int = { /* compiled code */ } + def foo2722(): scala.Int = { /* compiled code */ } + def foo2723(): scala.Int = { /* compiled code */ } + def foo2724(): scala.Int = { /* compiled code */ } + def foo2725(): scala.Int = { /* compiled code */ } + def foo2726(): scala.Int = { /* compiled code */ } + def foo2727(): scala.Int = { /* compiled code */ } + def foo2728(): scala.Int = { /* compiled code */ } + def foo2729(): scala.Int = { /* compiled code */ } + def foo2730(): scala.Int = { /* compiled code */ } + def foo2731(): scala.Int = { /* compiled code */ } + def foo2732(): scala.Int = { /* compiled code */ } + def foo2733(): scala.Int = { /* compiled code */ } + def foo2734(): scala.Int = { /* compiled code */ } + def foo2735(): scala.Int = { /* compiled code */ } + def foo2736(): scala.Int = { /* compiled code */ } + def foo2737(): scala.Int = { /* compiled code */ } + def foo2738(): scala.Int = { /* compiled code */ } + def foo2739(): scala.Int = { /* compiled code */ } + def foo2740(): scala.Int = { /* compiled code */ } + def foo2741(): scala.Int = { /* compiled code */ } + def foo2742(): scala.Int = { /* compiled code */ } + def foo2743(): scala.Int = { /* compiled code */ } + def foo2744(): scala.Int = { /* compiled code */ } + def foo2745(): scala.Int = { /* compiled code */ } + def foo2746(): scala.Int = { /* compiled code */ } + def foo2747(): scala.Int = { /* compiled code */ } + def foo2748(): scala.Int = { /* compiled code */ } + def foo2749(): scala.Int = { /* compiled code */ } + def foo2750(): scala.Int = { /* compiled code */ } + def foo2751(): scala.Int = { /* compiled code */ } + def foo2752(): scala.Int = { /* compiled code */ } + def foo2753(): scala.Int = { /* compiled code */ } + def foo2754(): scala.Int = { /* compiled code */ } + def foo2755(): scala.Int = { /* compiled code */ } + def foo2756(): scala.Int = { /* compiled code */ } + def foo2757(): scala.Int = { /* compiled code */ } + def foo2758(): scala.Int = { /* compiled code */ } + def foo2759(): scala.Int = { /* compiled code */ } + def foo2760(): scala.Int = { /* compiled code */ } + def foo2761(): scala.Int = { /* compiled code */ } + def foo2762(): scala.Int = { /* compiled code */ } + def foo2763(): scala.Int = { /* compiled code */ } + def foo2764(): scala.Int = { /* compiled code */ } + def foo2765(): scala.Int = { /* compiled code */ } + def foo2766(): scala.Int = { /* compiled code */ } + def foo2767(): scala.Int = { /* compiled code */ } + def foo2768(): scala.Int = { /* compiled code */ } + def foo2769(): scala.Int = { /* compiled code */ } + def foo2770(): scala.Int = { /* compiled code */ } + def foo2771(): scala.Int = { /* compiled code */ } + def foo2772(): scala.Int = { /* compiled code */ } + def foo2773(): scala.Int = { /* compiled code */ } + def foo2774(): scala.Int = { /* compiled code */ } + def foo2775(): scala.Int = { /* compiled code */ } + def foo2776(): scala.Int = { /* compiled code */ } + def foo2777(): scala.Int = { /* compiled code */ } + def foo2778(): scala.Int = { /* compiled code */ } + def foo2779(): scala.Int = { /* compiled code */ } + def foo2780(): scala.Int = { /* compiled code */ } + def foo2781(): scala.Int = { /* compiled code */ } + def foo2782(): scala.Int = { /* compiled code */ } + def foo2783(): scala.Int = { /* compiled code */ } + def foo2784(): scala.Int = { /* compiled code */ } + def foo2785(): scala.Int = { /* compiled code */ } + def foo2786(): scala.Int = { /* compiled code */ } + def foo2787(): scala.Int = { /* compiled code */ } + def foo2788(): scala.Int = { /* compiled code */ } + def foo2789(): scala.Int = { /* compiled code */ } + def foo2790(): scala.Int = { /* compiled code */ } + def foo2791(): scala.Int = { /* compiled code */ } + def foo2792(): scala.Int = { /* compiled code */ } + def foo2793(): scala.Int = { /* compiled code */ } + def foo2794(): scala.Int = { /* compiled code */ } + def foo2795(): scala.Int = { /* compiled code */ } + def foo2796(): scala.Int = { /* compiled code */ } + def foo2797(): scala.Int = { /* compiled code */ } + def foo2798(): scala.Int = { /* compiled code */ } + def foo2799(): scala.Int = { /* compiled code */ } + def foo2800(): scala.Int = { /* compiled code */ } + def foo2801(): scala.Int = { /* compiled code */ } + def foo2802(): scala.Int = { /* compiled code */ } + def foo2803(): scala.Int = { /* compiled code */ } + def foo2804(): scala.Int = { /* compiled code */ } + def foo2805(): scala.Int = { /* compiled code */ } + def foo2806(): scala.Int = { /* compiled code */ } + def foo2807(): scala.Int = { /* compiled code */ } + def foo2808(): scala.Int = { /* compiled code */ } + def foo2809(): scala.Int = { /* compiled code */ } + def foo2810(): scala.Int = { /* compiled code */ } + def foo2811(): scala.Int = { /* compiled code */ } + def foo2812(): scala.Int = { /* compiled code */ } + def foo2813(): scala.Int = { /* compiled code */ } + def foo2814(): scala.Int = { /* compiled code */ } + def foo2815(): scala.Int = { /* compiled code */ } + def foo2816(): scala.Int = { /* compiled code */ } + def foo2817(): scala.Int = { /* compiled code */ } + def foo2818(): scala.Int = { /* compiled code */ } + def foo2819(): scala.Int = { /* compiled code */ } + def foo2820(): scala.Int = { /* compiled code */ } + def foo2821(): scala.Int = { /* compiled code */ } + def foo2822(): scala.Int = { /* compiled code */ } + def foo2823(): scala.Int = { /* compiled code */ } + def foo2824(): scala.Int = { /* compiled code */ } + def foo2825(): scala.Int = { /* compiled code */ } + def foo2826(): scala.Int = { /* compiled code */ } + def foo2827(): scala.Int = { /* compiled code */ } + def foo2828(): scala.Int = { /* compiled code */ } + def foo2829(): scala.Int = { /* compiled code */ } + def foo2830(): scala.Int = { /* compiled code */ } + def foo2831(): scala.Int = { /* compiled code */ } + def foo2832(): scala.Int = { /* compiled code */ } + def foo2833(): scala.Int = { /* compiled code */ } + def foo2834(): scala.Int = { /* compiled code */ } + def foo2835(): scala.Int = { /* compiled code */ } + def foo2836(): scala.Int = { /* compiled code */ } + def foo2837(): scala.Int = { /* compiled code */ } + def foo2838(): scala.Int = { /* compiled code */ } + def foo2839(): scala.Int = { /* compiled code */ } + def foo2840(): scala.Int = { /* compiled code */ } + def foo2841(): scala.Int = { /* compiled code */ } + def foo2842(): scala.Int = { /* compiled code */ } + def foo2843(): scala.Int = { /* compiled code */ } + def foo2844(): scala.Int = { /* compiled code */ } + def foo2845(): scala.Int = { /* compiled code */ } + def foo2846(): scala.Int = { /* compiled code */ } + def foo2847(): scala.Int = { /* compiled code */ } + def foo2848(): scala.Int = { /* compiled code */ } + def foo2849(): scala.Int = { /* compiled code */ } + def foo2850(): scala.Int = { /* compiled code */ } + def foo2851(): scala.Int = { /* compiled code */ } + def foo2852(): scala.Int = { /* compiled code */ } + def foo2853(): scala.Int = { /* compiled code */ } + def foo2854(): scala.Int = { /* compiled code */ } + def foo2855(): scala.Int = { /* compiled code */ } + def foo2856(): scala.Int = { /* compiled code */ } + def foo2857(): scala.Int = { /* compiled code */ } + def foo2858(): scala.Int = { /* compiled code */ } + def foo2859(): scala.Int = { /* compiled code */ } + def foo2860(): scala.Int = { /* compiled code */ } + def foo2861(): scala.Int = { /* compiled code */ } + def foo2862(): scala.Int = { /* compiled code */ } + def foo2863(): scala.Int = { /* compiled code */ } + def foo2864(): scala.Int = { /* compiled code */ } + def foo2865(): scala.Int = { /* compiled code */ } + def foo2866(): scala.Int = { /* compiled code */ } + def foo2867(): scala.Int = { /* compiled code */ } + def foo2868(): scala.Int = { /* compiled code */ } + def foo2869(): scala.Int = { /* compiled code */ } + def foo2870(): scala.Int = { /* compiled code */ } + def foo2871(): scala.Int = { /* compiled code */ } + def foo2872(): scala.Int = { /* compiled code */ } + def foo2873(): scala.Int = { /* compiled code */ } + def foo2874(): scala.Int = { /* compiled code */ } + def foo2875(): scala.Int = { /* compiled code */ } + def foo2876(): scala.Int = { /* compiled code */ } + def foo2877(): scala.Int = { /* compiled code */ } + def foo2878(): scala.Int = { /* compiled code */ } + def foo2879(): scala.Int = { /* compiled code */ } + def foo2880(): scala.Int = { /* compiled code */ } + def foo2881(): scala.Int = { /* compiled code */ } + def foo2882(): scala.Int = { /* compiled code */ } + def foo2883(): scala.Int = { /* compiled code */ } + def foo2884(): scala.Int = { /* compiled code */ } + def foo2885(): scala.Int = { /* compiled code */ } + def foo2886(): scala.Int = { /* compiled code */ } + def foo2887(): scala.Int = { /* compiled code */ } + def foo2888(): scala.Int = { /* compiled code */ } + def foo2889(): scala.Int = { /* compiled code */ } + def foo2890(): scala.Int = { /* compiled code */ } + def foo2891(): scala.Int = { /* compiled code */ } + def foo2892(): scala.Int = { /* compiled code */ } + def foo2893(): scala.Int = { /* compiled code */ } + def foo2894(): scala.Int = { /* compiled code */ } + def foo2895(): scala.Int = { /* compiled code */ } + def foo2896(): scala.Int = { /* compiled code */ } + def foo2897(): scala.Int = { /* compiled code */ } + def foo2898(): scala.Int = { /* compiled code */ } + def foo2899(): scala.Int = { /* compiled code */ } + def foo2900(): scala.Int = { /* compiled code */ } + def foo2901(): scala.Int = { /* compiled code */ } + def foo2902(): scala.Int = { /* compiled code */ } + def foo2903(): scala.Int = { /* compiled code */ } + def foo2904(): scala.Int = { /* compiled code */ } + def foo2905(): scala.Int = { /* compiled code */ } + def foo2906(): scala.Int = { /* compiled code */ } + def foo2907(): scala.Int = { /* compiled code */ } + def foo2908(): scala.Int = { /* compiled code */ } + def foo2909(): scala.Int = { /* compiled code */ } + def foo2910(): scala.Int = { /* compiled code */ } + def foo2911(): scala.Int = { /* compiled code */ } + def foo2912(): scala.Int = { /* compiled code */ } + def foo2913(): scala.Int = { /* compiled code */ } + def foo2914(): scala.Int = { /* compiled code */ } + def foo2915(): scala.Int = { /* compiled code */ } + def foo2916(): scala.Int = { /* compiled code */ } + def foo2917(): scala.Int = { /* compiled code */ } + def foo2918(): scala.Int = { /* compiled code */ } + def foo2919(): scala.Int = { /* compiled code */ } + def foo2920(): scala.Int = { /* compiled code */ } + def foo2921(): scala.Int = { /* compiled code */ } + def foo2922(): scala.Int = { /* compiled code */ } + def foo2923(): scala.Int = { /* compiled code */ } + def foo2924(): scala.Int = { /* compiled code */ } + def foo2925(): scala.Int = { /* compiled code */ } + def foo2926(): scala.Int = { /* compiled code */ } + def foo2927(): scala.Int = { /* compiled code */ } + def foo2928(): scala.Int = { /* compiled code */ } + def foo2929(): scala.Int = { /* compiled code */ } + def foo2930(): scala.Int = { /* compiled code */ } + def foo2931(): scala.Int = { /* compiled code */ } + def foo2932(): scala.Int = { /* compiled code */ } + def foo2933(): scala.Int = { /* compiled code */ } + def foo2934(): scala.Int = { /* compiled code */ } + def foo2935(): scala.Int = { /* compiled code */ } + def foo2936(): scala.Int = { /* compiled code */ } + def foo2937(): scala.Int = { /* compiled code */ } + def foo2938(): scala.Int = { /* compiled code */ } + def foo2939(): scala.Int = { /* compiled code */ } + def foo2940(): scala.Int = { /* compiled code */ } + def foo2941(): scala.Int = { /* compiled code */ } + def foo2942(): scala.Int = { /* compiled code */ } + def foo2943(): scala.Int = { /* compiled code */ } + def foo2944(): scala.Int = { /* compiled code */ } + def foo2945(): scala.Int = { /* compiled code */ } + def foo2946(): scala.Int = { /* compiled code */ } + def foo2947(): scala.Int = { /* compiled code */ } + def foo2948(): scala.Int = { /* compiled code */ } + def foo2949(): scala.Int = { /* compiled code */ } + def foo2950(): scala.Int = { /* compiled code */ } + def foo2951(): scala.Int = { /* compiled code */ } + def foo2952(): scala.Int = { /* compiled code */ } + def foo2953(): scala.Int = { /* compiled code */ } + def foo2954(): scala.Int = { /* compiled code */ } + def foo2955(): scala.Int = { /* compiled code */ } + def foo2956(): scala.Int = { /* compiled code */ } + def foo2957(): scala.Int = { /* compiled code */ } + def foo2958(): scala.Int = { /* compiled code */ } + def foo2959(): scala.Int = { /* compiled code */ } + def foo2960(): scala.Int = { /* compiled code */ } + def foo2961(): scala.Int = { /* compiled code */ } + def foo2962(): scala.Int = { /* compiled code */ } + def foo2963(): scala.Int = { /* compiled code */ } + def foo2964(): scala.Int = { /* compiled code */ } + def foo2965(): scala.Int = { /* compiled code */ } + def foo2966(): scala.Int = { /* compiled code */ } + def foo2967(): scala.Int = { /* compiled code */ } + def foo2968(): scala.Int = { /* compiled code */ } + def foo2969(): scala.Int = { /* compiled code */ } + def foo2970(): scala.Int = { /* compiled code */ } + def foo2971(): scala.Int = { /* compiled code */ } + def foo2972(): scala.Int = { /* compiled code */ } + def foo2973(): scala.Int = { /* compiled code */ } + def foo2974(): scala.Int = { /* compiled code */ } + def foo2975(): scala.Int = { /* compiled code */ } + def foo2976(): scala.Int = { /* compiled code */ } + def foo2977(): scala.Int = { /* compiled code */ } + def foo2978(): scala.Int = { /* compiled code */ } + def foo2979(): scala.Int = { /* compiled code */ } + def foo2980(): scala.Int = { /* compiled code */ } + def foo2981(): scala.Int = { /* compiled code */ } + def foo2982(): scala.Int = { /* compiled code */ } + def foo2983(): scala.Int = { /* compiled code */ } + def foo2984(): scala.Int = { /* compiled code */ } + def foo2985(): scala.Int = { /* compiled code */ } + def foo2986(): scala.Int = { /* compiled code */ } + def foo2987(): scala.Int = { /* compiled code */ } + def foo2988(): scala.Int = { /* compiled code */ } + def foo2989(): scala.Int = { /* compiled code */ } + def foo2990(): scala.Int = { /* compiled code */ } + def foo2991(): scala.Int = { /* compiled code */ } + def foo2992(): scala.Int = { /* compiled code */ } + def foo2993(): scala.Int = { /* compiled code */ } + def foo2994(): scala.Int = { /* compiled code */ } + def foo2995(): scala.Int = { /* compiled code */ } + def foo2996(): scala.Int = { /* compiled code */ } + def foo2997(): scala.Int = { /* compiled code */ } + def foo2998(): scala.Int = { /* compiled code */ } + def foo2999(): scala.Int = { /* compiled code */ } + def foo3000(): scala.Int = { /* compiled code */ } + def foo3001(): scala.Int = { /* compiled code */ } + def foo3002(): scala.Int = { /* compiled code */ } + def foo3003(): scala.Int = { /* compiled code */ } + def foo3004(): scala.Int = { /* compiled code */ } + def foo3005(): scala.Int = { /* compiled code */ } + def foo3006(): scala.Int = { /* compiled code */ } + def foo3007(): scala.Int = { /* compiled code */ } + def foo3008(): scala.Int = { /* compiled code */ } + def foo3009(): scala.Int = { /* compiled code */ } + def foo3010(): scala.Int = { /* compiled code */ } + def foo3011(): scala.Int = { /* compiled code */ } + def foo3012(): scala.Int = { /* compiled code */ } + def foo3013(): scala.Int = { /* compiled code */ } + def foo3014(): scala.Int = { /* compiled code */ } + def foo3015(): scala.Int = { /* compiled code */ } + def foo3016(): scala.Int = { /* compiled code */ } + def foo3017(): scala.Int = { /* compiled code */ } + def foo3018(): scala.Int = { /* compiled code */ } + def foo3019(): scala.Int = { /* compiled code */ } + def foo3020(): scala.Int = { /* compiled code */ } + def foo3021(): scala.Int = { /* compiled code */ } + def foo3022(): scala.Int = { /* compiled code */ } + def foo3023(): scala.Int = { /* compiled code */ } + def foo3024(): scala.Int = { /* compiled code */ } + def foo3025(): scala.Int = { /* compiled code */ } + def foo3026(): scala.Int = { /* compiled code */ } + def foo3027(): scala.Int = { /* compiled code */ } + def foo3028(): scala.Int = { /* compiled code */ } + def foo3029(): scala.Int = { /* compiled code */ } + def foo3030(): scala.Int = { /* compiled code */ } + def foo3031(): scala.Int = { /* compiled code */ } + def foo3032(): scala.Int = { /* compiled code */ } + def foo3033(): scala.Int = { /* compiled code */ } + def foo3034(): scala.Int = { /* compiled code */ } + def foo3035(): scala.Int = { /* compiled code */ } + def foo3036(): scala.Int = { /* compiled code */ } + def foo3037(): scala.Int = { /* compiled code */ } + def foo3038(): scala.Int = { /* compiled code */ } + def foo3039(): scala.Int = { /* compiled code */ } + def foo3040(): scala.Int = { /* compiled code */ } + def foo3041(): scala.Int = { /* compiled code */ } + def foo3042(): scala.Int = { /* compiled code */ } + def foo3043(): scala.Int = { /* compiled code */ } + def foo3044(): scala.Int = { /* compiled code */ } + def foo3045(): scala.Int = { /* compiled code */ } + def foo3046(): scala.Int = { /* compiled code */ } + def foo3047(): scala.Int = { /* compiled code */ } + def foo3048(): scala.Int = { /* compiled code */ } + def foo3049(): scala.Int = { /* compiled code */ } + def foo3050(): scala.Int = { /* compiled code */ } + def foo3051(): scala.Int = { /* compiled code */ } + def foo3052(): scala.Int = { /* compiled code */ } + def foo3053(): scala.Int = { /* compiled code */ } + def foo3054(): scala.Int = { /* compiled code */ } + def foo3055(): scala.Int = { /* compiled code */ } + def foo3056(): scala.Int = { /* compiled code */ } + def foo3057(): scala.Int = { /* compiled code */ } + def foo3058(): scala.Int = { /* compiled code */ } + def foo3059(): scala.Int = { /* compiled code */ } + def foo3060(): scala.Int = { /* compiled code */ } + def foo3061(): scala.Int = { /* compiled code */ } + def foo3062(): scala.Int = { /* compiled code */ } + def foo3063(): scala.Int = { /* compiled code */ } + def foo3064(): scala.Int = { /* compiled code */ } + def foo3065(): scala.Int = { /* compiled code */ } + def foo3066(): scala.Int = { /* compiled code */ } + def foo3067(): scala.Int = { /* compiled code */ } + def foo3068(): scala.Int = { /* compiled code */ } + def foo3069(): scala.Int = { /* compiled code */ } + def foo3070(): scala.Int = { /* compiled code */ } + def foo3071(): scala.Int = { /* compiled code */ } + def foo3072(): scala.Int = { /* compiled code */ } + def foo3073(): scala.Int = { /* compiled code */ } + def foo3074(): scala.Int = { /* compiled code */ } + def foo3075(): scala.Int = { /* compiled code */ } + def foo3076(): scala.Int = { /* compiled code */ } + def foo3077(): scala.Int = { /* compiled code */ } + def foo3078(): scala.Int = { /* compiled code */ } + def foo3079(): scala.Int = { /* compiled code */ } + def foo3080(): scala.Int = { /* compiled code */ } + def foo3081(): scala.Int = { /* compiled code */ } + def foo3082(): scala.Int = { /* compiled code */ } + def foo3083(): scala.Int = { /* compiled code */ } + def foo3084(): scala.Int = { /* compiled code */ } + def foo3085(): scala.Int = { /* compiled code */ } + def foo3086(): scala.Int = { /* compiled code */ } + def foo3087(): scala.Int = { /* compiled code */ } + def foo3088(): scala.Int = { /* compiled code */ } + def foo3089(): scala.Int = { /* compiled code */ } + def foo3090(): scala.Int = { /* compiled code */ } + def foo3091(): scala.Int = { /* compiled code */ } + def foo3092(): scala.Int = { /* compiled code */ } + def foo3093(): scala.Int = { /* compiled code */ } + def foo3094(): scala.Int = { /* compiled code */ } + def foo3095(): scala.Int = { /* compiled code */ } + def foo3096(): scala.Int = { /* compiled code */ } + def foo3097(): scala.Int = { /* compiled code */ } + def foo3098(): scala.Int = { /* compiled code */ } + def foo3099(): scala.Int = { /* compiled code */ } + def foo3100(): scala.Int = { /* compiled code */ } + def foo3101(): scala.Int = { /* compiled code */ } + def foo3102(): scala.Int = { /* compiled code */ } + def foo3103(): scala.Int = { /* compiled code */ } + def foo3104(): scala.Int = { /* compiled code */ } + def foo3105(): scala.Int = { /* compiled code */ } + def foo3106(): scala.Int = { /* compiled code */ } + def foo3107(): scala.Int = { /* compiled code */ } + def foo3108(): scala.Int = { /* compiled code */ } + def foo3109(): scala.Int = { /* compiled code */ } + def foo3110(): scala.Int = { /* compiled code */ } + def foo3111(): scala.Int = { /* compiled code */ } + def foo3112(): scala.Int = { /* compiled code */ } + def foo3113(): scala.Int = { /* compiled code */ } + def foo3114(): scala.Int = { /* compiled code */ } + def foo3115(): scala.Int = { /* compiled code */ } + def foo3116(): scala.Int = { /* compiled code */ } + def foo3117(): scala.Int = { /* compiled code */ } + def foo3118(): scala.Int = { /* compiled code */ } + def foo3119(): scala.Int = { /* compiled code */ } + def foo3120(): scala.Int = { /* compiled code */ } + def foo3121(): scala.Int = { /* compiled code */ } + def foo3122(): scala.Int = { /* compiled code */ } + def foo3123(): scala.Int = { /* compiled code */ } + def foo3124(): scala.Int = { /* compiled code */ } + def foo3125(): scala.Int = { /* compiled code */ } + def foo3126(): scala.Int = { /* compiled code */ } + def foo3127(): scala.Int = { /* compiled code */ } + def foo3128(): scala.Int = { /* compiled code */ } + def foo3129(): scala.Int = { /* compiled code */ } + def foo3130(): scala.Int = { /* compiled code */ } + def foo3131(): scala.Int = { /* compiled code */ } + def foo3132(): scala.Int = { /* compiled code */ } + def foo3133(): scala.Int = { /* compiled code */ } + def foo3134(): scala.Int = { /* compiled code */ } + def foo3135(): scala.Int = { /* compiled code */ } + def foo3136(): scala.Int = { /* compiled code */ } + def foo3137(): scala.Int = { /* compiled code */ } + def foo3138(): scala.Int = { /* compiled code */ } + def foo3139(): scala.Int = { /* compiled code */ } + def foo3140(): scala.Int = { /* compiled code */ } + def foo3141(): scala.Int = { /* compiled code */ } + def foo3142(): scala.Int = { /* compiled code */ } + def foo3143(): scala.Int = { /* compiled code */ } + def foo3144(): scala.Int = { /* compiled code */ } + def foo3145(): scala.Int = { /* compiled code */ } + def foo3146(): scala.Int = { /* compiled code */ } + def foo3147(): scala.Int = { /* compiled code */ } + def foo3148(): scala.Int = { /* compiled code */ } + def foo3149(): scala.Int = { /* compiled code */ } + def foo3150(): scala.Int = { /* compiled code */ } + def foo3151(): scala.Int = { /* compiled code */ } + def foo3152(): scala.Int = { /* compiled code */ } + def foo3153(): scala.Int = { /* compiled code */ } + def foo3154(): scala.Int = { /* compiled code */ } + def foo3155(): scala.Int = { /* compiled code */ } + def foo3156(): scala.Int = { /* compiled code */ } + def foo3157(): scala.Int = { /* compiled code */ } + def foo3158(): scala.Int = { /* compiled code */ } + def foo3159(): scala.Int = { /* compiled code */ } + def foo3160(): scala.Int = { /* compiled code */ } + def foo3161(): scala.Int = { /* compiled code */ } + def foo3162(): scala.Int = { /* compiled code */ } + def foo3163(): scala.Int = { /* compiled code */ } + def foo3164(): scala.Int = { /* compiled code */ } + def foo3165(): scala.Int = { /* compiled code */ } + def foo3166(): scala.Int = { /* compiled code */ } + def foo3167(): scala.Int = { /* compiled code */ } + def foo3168(): scala.Int = { /* compiled code */ } + def foo3169(): scala.Int = { /* compiled code */ } + def foo3170(): scala.Int = { /* compiled code */ } + def foo3171(): scala.Int = { /* compiled code */ } + def foo3172(): scala.Int = { /* compiled code */ } + def foo3173(): scala.Int = { /* compiled code */ } + def foo3174(): scala.Int = { /* compiled code */ } + def foo3175(): scala.Int = { /* compiled code */ } + def foo3176(): scala.Int = { /* compiled code */ } + def foo3177(): scala.Int = { /* compiled code */ } + def foo3178(): scala.Int = { /* compiled code */ } + def foo3179(): scala.Int = { /* compiled code */ } + def foo3180(): scala.Int = { /* compiled code */ } + def foo3181(): scala.Int = { /* compiled code */ } + def foo3182(): scala.Int = { /* compiled code */ } + def foo3183(): scala.Int = { /* compiled code */ } + def foo3184(): scala.Int = { /* compiled code */ } + def foo3185(): scala.Int = { /* compiled code */ } + def foo3186(): scala.Int = { /* compiled code */ } + def foo3187(): scala.Int = { /* compiled code */ } + def foo3188(): scala.Int = { /* compiled code */ } + def foo3189(): scala.Int = { /* compiled code */ } + def foo3190(): scala.Int = { /* compiled code */ } + def foo3191(): scala.Int = { /* compiled code */ } + def foo3192(): scala.Int = { /* compiled code */ } + def foo3193(): scala.Int = { /* compiled code */ } + def foo3194(): scala.Int = { /* compiled code */ } + def foo3195(): scala.Int = { /* compiled code */ } + def foo3196(): scala.Int = { /* compiled code */ } + def foo3197(): scala.Int = { /* compiled code */ } + def foo3198(): scala.Int = { /* compiled code */ } + def foo3199(): scala.Int = { /* compiled code */ } + def foo3200(): scala.Int = { /* compiled code */ } + def foo3201(): scala.Int = { /* compiled code */ } + def foo3202(): scala.Int = { /* compiled code */ } + def foo3203(): scala.Int = { /* compiled code */ } + def foo3204(): scala.Int = { /* compiled code */ } + def foo3205(): scala.Int = { /* compiled code */ } + def foo3206(): scala.Int = { /* compiled code */ } + def foo3207(): scala.Int = { /* compiled code */ } + def foo3208(): scala.Int = { /* compiled code */ } + def foo3209(): scala.Int = { /* compiled code */ } + def foo3210(): scala.Int = { /* compiled code */ } + def foo3211(): scala.Int = { /* compiled code */ } + def foo3212(): scala.Int = { /* compiled code */ } + def foo3213(): scala.Int = { /* compiled code */ } + def foo3214(): scala.Int = { /* compiled code */ } + def foo3215(): scala.Int = { /* compiled code */ } + def foo3216(): scala.Int = { /* compiled code */ } + def foo3217(): scala.Int = { /* compiled code */ } + def foo3218(): scala.Int = { /* compiled code */ } + def foo3219(): scala.Int = { /* compiled code */ } + def foo3220(): scala.Int = { /* compiled code */ } + def foo3221(): scala.Int = { /* compiled code */ } + def foo3222(): scala.Int = { /* compiled code */ } + def foo3223(): scala.Int = { /* compiled code */ } + def foo3224(): scala.Int = { /* compiled code */ } + def foo3225(): scala.Int = { /* compiled code */ } + def foo3226(): scala.Int = { /* compiled code */ } + def foo3227(): scala.Int = { /* compiled code */ } + def foo3228(): scala.Int = { /* compiled code */ } + def foo3229(): scala.Int = { /* compiled code */ } + def foo3230(): scala.Int = { /* compiled code */ } + def foo3231(): scala.Int = { /* compiled code */ } + def foo3232(): scala.Int = { /* compiled code */ } + def foo3233(): scala.Int = { /* compiled code */ } + def foo3234(): scala.Int = { /* compiled code */ } + def foo3235(): scala.Int = { /* compiled code */ } + def foo3236(): scala.Int = { /* compiled code */ } + def foo3237(): scala.Int = { /* compiled code */ } + def foo3238(): scala.Int = { /* compiled code */ } + def foo3239(): scala.Int = { /* compiled code */ } + def foo3240(): scala.Int = { /* compiled code */ } + def foo3241(): scala.Int = { /* compiled code */ } + def foo3242(): scala.Int = { /* compiled code */ } + def foo3243(): scala.Int = { /* compiled code */ } + def foo3244(): scala.Int = { /* compiled code */ } + def foo3245(): scala.Int = { /* compiled code */ } + def foo3246(): scala.Int = { /* compiled code */ } + def foo3247(): scala.Int = { /* compiled code */ } + def foo3248(): scala.Int = { /* compiled code */ } + def foo3249(): scala.Int = { /* compiled code */ } + def foo3250(): scala.Int = { /* compiled code */ } + def foo3251(): scala.Int = { /* compiled code */ } + def foo3252(): scala.Int = { /* compiled code */ } + def foo3253(): scala.Int = { /* compiled code */ } + def foo3254(): scala.Int = { /* compiled code */ } + def foo3255(): scala.Int = { /* compiled code */ } + def foo3256(): scala.Int = { /* compiled code */ } + def foo3257(): scala.Int = { /* compiled code */ } + def foo3258(): scala.Int = { /* compiled code */ } + def foo3259(): scala.Int = { /* compiled code */ } + def foo3260(): scala.Int = { /* compiled code */ } + def foo3261(): scala.Int = { /* compiled code */ } + def foo3262(): scala.Int = { /* compiled code */ } + def foo3263(): scala.Int = { /* compiled code */ } + def foo3264(): scala.Int = { /* compiled code */ } + def foo3265(): scala.Int = { /* compiled code */ } + def foo3266(): scala.Int = { /* compiled code */ } + def foo3267(): scala.Int = { /* compiled code */ } + def foo3268(): scala.Int = { /* compiled code */ } + def foo3269(): scala.Int = { /* compiled code */ } + def foo3270(): scala.Int = { /* compiled code */ } + def foo3271(): scala.Int = { /* compiled code */ } + def foo3272(): scala.Int = { /* compiled code */ } + def foo3273(): scala.Int = { /* compiled code */ } + def foo3274(): scala.Int = { /* compiled code */ } + def foo3275(): scala.Int = { /* compiled code */ } + def foo3276(): scala.Int = { /* compiled code */ } + def foo3277(): scala.Int = { /* compiled code */ } + def foo3278(): scala.Int = { /* compiled code */ } + def foo3279(): scala.Int = { /* compiled code */ } + def foo3280(): scala.Int = { /* compiled code */ } + def foo3281(): scala.Int = { /* compiled code */ } + def foo3282(): scala.Int = { /* compiled code */ } + def foo3283(): scala.Int = { /* compiled code */ } + def foo3284(): scala.Int = { /* compiled code */ } + def foo3285(): scala.Int = { /* compiled code */ } + def foo3286(): scala.Int = { /* compiled code */ } + def foo3287(): scala.Int = { /* compiled code */ } + def foo3288(): scala.Int = { /* compiled code */ } + def foo3289(): scala.Int = { /* compiled code */ } + def foo3290(): scala.Int = { /* compiled code */ } + def foo3291(): scala.Int = { /* compiled code */ } + def foo3292(): scala.Int = { /* compiled code */ } + def foo3293(): scala.Int = { /* compiled code */ } + def foo3294(): scala.Int = { /* compiled code */ } + def foo3295(): scala.Int = { /* compiled code */ } + def foo3296(): scala.Int = { /* compiled code */ } + def foo3297(): scala.Int = { /* compiled code */ } + def foo3298(): scala.Int = { /* compiled code */ } + def foo3299(): scala.Int = { /* compiled code */ } + def foo3300(): scala.Int = { /* compiled code */ } + def foo3301(): scala.Int = { /* compiled code */ } + def foo3302(): scala.Int = { /* compiled code */ } + def foo3303(): scala.Int = { /* compiled code */ } + def foo3304(): scala.Int = { /* compiled code */ } + def foo3305(): scala.Int = { /* compiled code */ } + def foo3306(): scala.Int = { /* compiled code */ } + def foo3307(): scala.Int = { /* compiled code */ } + def foo3308(): scala.Int = { /* compiled code */ } + def foo3309(): scala.Int = { /* compiled code */ } + def foo3310(): scala.Int = { /* compiled code */ } + def foo3311(): scala.Int = { /* compiled code */ } + def foo3312(): scala.Int = { /* compiled code */ } + def foo3313(): scala.Int = { /* compiled code */ } + def foo3314(): scala.Int = { /* compiled code */ } + def foo3315(): scala.Int = { /* compiled code */ } + def foo3316(): scala.Int = { /* compiled code */ } + def foo3317(): scala.Int = { /* compiled code */ } + def foo3318(): scala.Int = { /* compiled code */ } + def foo3319(): scala.Int = { /* compiled code */ } + def foo3320(): scala.Int = { /* compiled code */ } + def foo3321(): scala.Int = { /* compiled code */ } + def foo3322(): scala.Int = { /* compiled code */ } + def foo3323(): scala.Int = { /* compiled code */ } + def foo3324(): scala.Int = { /* compiled code */ } + def foo3325(): scala.Int = { /* compiled code */ } + def foo3326(): scala.Int = { /* compiled code */ } + def foo3327(): scala.Int = { /* compiled code */ } + def foo3328(): scala.Int = { /* compiled code */ } + def foo3329(): scala.Int = { /* compiled code */ } + def foo3330(): scala.Int = { /* compiled code */ } + def foo3331(): scala.Int = { /* compiled code */ } + def foo3332(): scala.Int = { /* compiled code */ } + def foo3333(): scala.Int = { /* compiled code */ } + def foo3334(): scala.Int = { /* compiled code */ } + def foo3335(): scala.Int = { /* compiled code */ } + def foo3336(): scala.Int = { /* compiled code */ } + def foo3337(): scala.Int = { /* compiled code */ } + def foo3338(): scala.Int = { /* compiled code */ } + def foo3339(): scala.Int = { /* compiled code */ } + def foo3340(): scala.Int = { /* compiled code */ } + def foo3341(): scala.Int = { /* compiled code */ } + def foo3342(): scala.Int = { /* compiled code */ } + def foo3343(): scala.Int = { /* compiled code */ } + def foo3344(): scala.Int = { /* compiled code */ } + def foo3345(): scala.Int = { /* compiled code */ } + def foo3346(): scala.Int = { /* compiled code */ } + def foo3347(): scala.Int = { /* compiled code */ } + def foo3348(): scala.Int = { /* compiled code */ } + def foo3349(): scala.Int = { /* compiled code */ } + def foo3350(): scala.Int = { /* compiled code */ } + def foo3351(): scala.Int = { /* compiled code */ } + def foo3352(): scala.Int = { /* compiled code */ } + def foo3353(): scala.Int = { /* compiled code */ } + def foo3354(): scala.Int = { /* compiled code */ } + def foo3355(): scala.Int = { /* compiled code */ } + def foo3356(): scala.Int = { /* compiled code */ } + def foo3357(): scala.Int = { /* compiled code */ } + def foo3358(): scala.Int = { /* compiled code */ } + def foo3359(): scala.Int = { /* compiled code */ } + def foo3360(): scala.Int = { /* compiled code */ } + def foo3361(): scala.Int = { /* compiled code */ } + def foo3362(): scala.Int = { /* compiled code */ } + def foo3363(): scala.Int = { /* compiled code */ } + def foo3364(): scala.Int = { /* compiled code */ } + def foo3365(): scala.Int = { /* compiled code */ } + def foo3366(): scala.Int = { /* compiled code */ } + def foo3367(): scala.Int = { /* compiled code */ } + def foo3368(): scala.Int = { /* compiled code */ } + def foo3369(): scala.Int = { /* compiled code */ } + def foo3370(): scala.Int = { /* compiled code */ } + def foo3371(): scala.Int = { /* compiled code */ } + def foo3372(): scala.Int = { /* compiled code */ } + def foo3373(): scala.Int = { /* compiled code */ } + def foo3374(): scala.Int = { /* compiled code */ } + def foo3375(): scala.Int = { /* compiled code */ } + def foo3376(): scala.Int = { /* compiled code */ } + def foo3377(): scala.Int = { /* compiled code */ } + def foo3378(): scala.Int = { /* compiled code */ } + def foo3379(): scala.Int = { /* compiled code */ } + def foo3380(): scala.Int = { /* compiled code */ } + def foo3381(): scala.Int = { /* compiled code */ } + def foo3382(): scala.Int = { /* compiled code */ } + def foo3383(): scala.Int = { /* compiled code */ } + def foo3384(): scala.Int = { /* compiled code */ } + def foo3385(): scala.Int = { /* compiled code */ } + def foo3386(): scala.Int = { /* compiled code */ } + def foo3387(): scala.Int = { /* compiled code */ } + def foo3388(): scala.Int = { /* compiled code */ } + def foo3389(): scala.Int = { /* compiled code */ } + def foo3390(): scala.Int = { /* compiled code */ } + def foo3391(): scala.Int = { /* compiled code */ } + def foo3392(): scala.Int = { /* compiled code */ } + def foo3393(): scala.Int = { /* compiled code */ } + def foo3394(): scala.Int = { /* compiled code */ } + def foo3395(): scala.Int = { /* compiled code */ } + def foo3396(): scala.Int = { /* compiled code */ } + def foo3397(): scala.Int = { /* compiled code */ } + def foo3398(): scala.Int = { /* compiled code */ } + def foo3399(): scala.Int = { /* compiled code */ } + def foo3400(): scala.Int = { /* compiled code */ } + def foo3401(): scala.Int = { /* compiled code */ } + def foo3402(): scala.Int = { /* compiled code */ } + def foo3403(): scala.Int = { /* compiled code */ } + def foo3404(): scala.Int = { /* compiled code */ } + def foo3405(): scala.Int = { /* compiled code */ } + def foo3406(): scala.Int = { /* compiled code */ } + def foo3407(): scala.Int = { /* compiled code */ } + def foo3408(): scala.Int = { /* compiled code */ } + def foo3409(): scala.Int = { /* compiled code */ } + def foo3410(): scala.Int = { /* compiled code */ } + def foo3411(): scala.Int = { /* compiled code */ } + def foo3412(): scala.Int = { /* compiled code */ } + def foo3413(): scala.Int = { /* compiled code */ } + def foo3414(): scala.Int = { /* compiled code */ } + def foo3415(): scala.Int = { /* compiled code */ } + def foo3416(): scala.Int = { /* compiled code */ } + def foo3417(): scala.Int = { /* compiled code */ } + def foo3418(): scala.Int = { /* compiled code */ } + def foo3419(): scala.Int = { /* compiled code */ } + def foo3420(): scala.Int = { /* compiled code */ } + def foo3421(): scala.Int = { /* compiled code */ } + def foo3422(): scala.Int = { /* compiled code */ } + def foo3423(): scala.Int = { /* compiled code */ } + def foo3424(): scala.Int = { /* compiled code */ } + def foo3425(): scala.Int = { /* compiled code */ } + def foo3426(): scala.Int = { /* compiled code */ } + def foo3427(): scala.Int = { /* compiled code */ } + def foo3428(): scala.Int = { /* compiled code */ } + def foo3429(): scala.Int = { /* compiled code */ } + def foo3430(): scala.Int = { /* compiled code */ } + def foo3431(): scala.Int = { /* compiled code */ } + def foo3432(): scala.Int = { /* compiled code */ } + def foo3433(): scala.Int = { /* compiled code */ } + def foo3434(): scala.Int = { /* compiled code */ } + def foo3435(): scala.Int = { /* compiled code */ } + def foo3436(): scala.Int = { /* compiled code */ } + def foo3437(): scala.Int = { /* compiled code */ } + def foo3438(): scala.Int = { /* compiled code */ } + def foo3439(): scala.Int = { /* compiled code */ } + def foo3440(): scala.Int = { /* compiled code */ } + def foo3441(): scala.Int = { /* compiled code */ } + def foo3442(): scala.Int = { /* compiled code */ } + def foo3443(): scala.Int = { /* compiled code */ } + def foo3444(): scala.Int = { /* compiled code */ } + def foo3445(): scala.Int = { /* compiled code */ } + def foo3446(): scala.Int = { /* compiled code */ } + def foo3447(): scala.Int = { /* compiled code */ } + def foo3448(): scala.Int = { /* compiled code */ } + def foo3449(): scala.Int = { /* compiled code */ } + def foo3450(): scala.Int = { /* compiled code */ } + def foo3451(): scala.Int = { /* compiled code */ } + def foo3452(): scala.Int = { /* compiled code */ } + def foo3453(): scala.Int = { /* compiled code */ } + def foo3454(): scala.Int = { /* compiled code */ } + def foo3455(): scala.Int = { /* compiled code */ } + def foo3456(): scala.Int = { /* compiled code */ } + def foo3457(): scala.Int = { /* compiled code */ } + def foo3458(): scala.Int = { /* compiled code */ } + def foo3459(): scala.Int = { /* compiled code */ } + def foo3460(): scala.Int = { /* compiled code */ } + def foo3461(): scala.Int = { /* compiled code */ } + def foo3462(): scala.Int = { /* compiled code */ } + def foo3463(): scala.Int = { /* compiled code */ } + def foo3464(): scala.Int = { /* compiled code */ } + def foo3465(): scala.Int = { /* compiled code */ } + def foo3466(): scala.Int = { /* compiled code */ } + def foo3467(): scala.Int = { /* compiled code */ } + def foo3468(): scala.Int = { /* compiled code */ } + def foo3469(): scala.Int = { /* compiled code */ } + def foo3470(): scala.Int = { /* compiled code */ } + def foo3471(): scala.Int = { /* compiled code */ } + def foo3472(): scala.Int = { /* compiled code */ } + def foo3473(): scala.Int = { /* compiled code */ } + def foo3474(): scala.Int = { /* compiled code */ } + def foo3475(): scala.Int = { /* compiled code */ } + def foo3476(): scala.Int = { /* compiled code */ } + def foo3477(): scala.Int = { /* compiled code */ } + def foo3478(): scala.Int = { /* compiled code */ } + def foo3479(): scala.Int = { /* compiled code */ } + def foo3480(): scala.Int = { /* compiled code */ } + def foo3481(): scala.Int = { /* compiled code */ } + def foo3482(): scala.Int = { /* compiled code */ } + def foo3483(): scala.Int = { /* compiled code */ } + def foo3484(): scala.Int = { /* compiled code */ } + def foo3485(): scala.Int = { /* compiled code */ } + def foo3486(): scala.Int = { /* compiled code */ } + def foo3487(): scala.Int = { /* compiled code */ } + def foo3488(): scala.Int = { /* compiled code */ } + def foo3489(): scala.Int = { /* compiled code */ } + def foo3490(): scala.Int = { /* compiled code */ } + def foo3491(): scala.Int = { /* compiled code */ } + def foo3492(): scala.Int = { /* compiled code */ } + def foo3493(): scala.Int = { /* compiled code */ } + def foo3494(): scala.Int = { /* compiled code */ } + def foo3495(): scala.Int = { /* compiled code */ } + def foo3496(): scala.Int = { /* compiled code */ } + def foo3497(): scala.Int = { /* compiled code */ } + def foo3498(): scala.Int = { /* compiled code */ } + def foo3499(): scala.Int = { /* compiled code */ } + def foo3500(): scala.Int = { /* compiled code */ } +} diff --git a/test/files/scalap/t8679.scala b/test/files/scalap/t8679.scala new file mode 100644 index 0000000000..f008a7af35 --- /dev/null +++ b/test/files/scalap/t8679.scala @@ -0,0 +1,3502 @@ +class T8679 { + def foo1(): Int = 3 + def foo2(): Int = 4 + def foo3(): Int = 5 + def foo4(): Int = 6 + def foo5(): Int = 7 + def foo6(): Int = 8 + def foo7(): Int = 9 + def foo8(): Int = 10 + def foo9(): Int = 11 + def foo10(): Int = 12 + def foo11(): Int = 13 + def foo12(): Int = 14 + def foo13(): Int = 15 + def foo14(): Int = 16 + def foo15(): Int = 17 + def foo16(): Int = 18 + def foo17(): Int = 19 + def foo18(): Int = 20 + def foo19(): Int = 21 + def foo20(): Int = 22 + def foo21(): Int = 23 + def foo22(): Int = 24 + def foo23(): Int = 25 + def foo24(): Int = 26 + def foo25(): Int = 27 + def foo26(): Int = 28 + def foo27(): Int = 29 + def foo28(): Int = 30 + def foo29(): Int = 31 + def foo30(): Int = 32 + def foo31(): Int = 33 + def foo32(): Int = 34 + def foo33(): Int = 35 + def foo34(): Int = 36 + def foo35(): Int = 37 + def foo36(): Int = 38 + def foo37(): Int = 39 + def foo38(): Int = 40 + def foo39(): Int = 41 + def foo40(): Int = 42 + def foo41(): Int = 43 + def foo42(): Int = 44 + def foo43(): Int = 45 + def foo44(): Int = 46 + def foo45(): Int = 47 + def foo46(): Int = 48 + def foo47(): Int = 49 + def foo48(): Int = 50 + def foo49(): Int = 51 + def foo50(): Int = 52 + def foo51(): Int = 53 + def foo52(): Int = 54 + def foo53(): Int = 55 + def foo54(): Int = 56 + def foo55(): Int = 57 + def foo56(): Int = 58 + def foo57(): Int = 59 + def foo58(): Int = 60 + def foo59(): Int = 61 + def foo60(): Int = 62 + def foo61(): Int = 63 + def foo62(): Int = 64 + def foo63(): Int = 65 + def foo64(): Int = 66 + def foo65(): Int = 67 + def foo66(): Int = 68 + def foo67(): Int = 69 + def foo68(): Int = 70 + def foo69(): Int = 71 + def foo70(): Int = 72 + def foo71(): Int = 73 + def foo72(): Int = 74 + def foo73(): Int = 75 + def foo74(): Int = 76 + def foo75(): Int = 77 + def foo76(): Int = 78 + def foo77(): Int = 79 + def foo78(): Int = 80 + def foo79(): Int = 81 + def foo80(): Int = 82 + def foo81(): Int = 83 + def foo82(): Int = 84 + def foo83(): Int = 85 + def foo84(): Int = 86 + def foo85(): Int = 87 + def foo86(): Int = 88 + def foo87(): Int = 89 + def foo88(): Int = 90 + def foo89(): Int = 91 + def foo90(): Int = 92 + def foo91(): Int = 93 + def foo92(): Int = 94 + def foo93(): Int = 95 + def foo94(): Int = 96 + def foo95(): Int = 97 + def foo96(): Int = 98 + def foo97(): Int = 99 + def foo98(): Int = 100 + def foo99(): Int = 101 + def foo100(): Int = 102 + def foo101(): Int = 103 + def foo102(): Int = 104 + def foo103(): Int = 105 + def foo104(): Int = 106 + def foo105(): Int = 107 + def foo106(): Int = 108 + def foo107(): Int = 109 + def foo108(): Int = 110 + def foo109(): Int = 111 + def foo110(): Int = 112 + def foo111(): Int = 113 + def foo112(): Int = 114 + def foo113(): Int = 115 + def foo114(): Int = 116 + def foo115(): Int = 117 + def foo116(): Int = 118 + def foo117(): Int = 119 + def foo118(): Int = 120 + def foo119(): Int = 121 + def foo120(): Int = 122 + def foo121(): Int = 123 + def foo122(): Int = 124 + def foo123(): Int = 125 + def foo124(): Int = 126 + def foo125(): Int = 127 + def foo126(): Int = 128 + def foo127(): Int = 129 + def foo128(): Int = 130 + def foo129(): Int = 131 + def foo130(): Int = 132 + def foo131(): Int = 133 + def foo132(): Int = 134 + def foo133(): Int = 135 + def foo134(): Int = 136 + def foo135(): Int = 137 + def foo136(): Int = 138 + def foo137(): Int = 139 + def foo138(): Int = 140 + def foo139(): Int = 141 + def foo140(): Int = 142 + def foo141(): Int = 143 + def foo142(): Int = 144 + def foo143(): Int = 145 + def foo144(): Int = 146 + def foo145(): Int = 147 + def foo146(): Int = 148 + def foo147(): Int = 149 + def foo148(): Int = 150 + def foo149(): Int = 151 + def foo150(): Int = 152 + def foo151(): Int = 153 + def foo152(): Int = 154 + def foo153(): Int = 155 + def foo154(): Int = 156 + def foo155(): Int = 157 + def foo156(): Int = 158 + def foo157(): Int = 159 + def foo158(): Int = 160 + def foo159(): Int = 161 + def foo160(): Int = 162 + def foo161(): Int = 163 + def foo162(): Int = 164 + def foo163(): Int = 165 + def foo164(): Int = 166 + def foo165(): Int = 167 + def foo166(): Int = 168 + def foo167(): Int = 169 + def foo168(): Int = 170 + def foo169(): Int = 171 + def foo170(): Int = 172 + def foo171(): Int = 173 + def foo172(): Int = 174 + def foo173(): Int = 175 + def foo174(): Int = 176 + def foo175(): Int = 177 + def foo176(): Int = 178 + def foo177(): Int = 179 + def foo178(): Int = 180 + def foo179(): Int = 181 + def foo180(): Int = 182 + def foo181(): Int = 183 + def foo182(): Int = 184 + def foo183(): Int = 185 + def foo184(): Int = 186 + def foo185(): Int = 187 + def foo186(): Int = 188 + def foo187(): Int = 189 + def foo188(): Int = 190 + def foo189(): Int = 191 + def foo190(): Int = 192 + def foo191(): Int = 193 + def foo192(): Int = 194 + def foo193(): Int = 195 + def foo194(): Int = 196 + def foo195(): Int = 197 + def foo196(): Int = 198 + def foo197(): Int = 199 + def foo198(): Int = 200 + def foo199(): Int = 201 + def foo200(): Int = 202 + def foo201(): Int = 203 + def foo202(): Int = 204 + def foo203(): Int = 205 + def foo204(): Int = 206 + def foo205(): Int = 207 + def foo206(): Int = 208 + def foo207(): Int = 209 + def foo208(): Int = 210 + def foo209(): Int = 211 + def foo210(): Int = 212 + def foo211(): Int = 213 + def foo212(): Int = 214 + def foo213(): Int = 215 + def foo214(): Int = 216 + def foo215(): Int = 217 + def foo216(): Int = 218 + def foo217(): Int = 219 + def foo218(): Int = 220 + def foo219(): Int = 221 + def foo220(): Int = 222 + def foo221(): Int = 223 + def foo222(): Int = 224 + def foo223(): Int = 225 + def foo224(): Int = 226 + def foo225(): Int = 227 + def foo226(): Int = 228 + def foo227(): Int = 229 + def foo228(): Int = 230 + def foo229(): Int = 231 + def foo230(): Int = 232 + def foo231(): Int = 233 + def foo232(): Int = 234 + def foo233(): Int = 235 + def foo234(): Int = 236 + def foo235(): Int = 237 + def foo236(): Int = 238 + def foo237(): Int = 239 + def foo238(): Int = 240 + def foo239(): Int = 241 + def foo240(): Int = 242 + def foo241(): Int = 243 + def foo242(): Int = 244 + def foo243(): Int = 245 + def foo244(): Int = 246 + def foo245(): Int = 247 + def foo246(): Int = 248 + def foo247(): Int = 249 + def foo248(): Int = 250 + def foo249(): Int = 251 + def foo250(): Int = 252 + def foo251(): Int = 253 + def foo252(): Int = 254 + def foo253(): Int = 255 + def foo254(): Int = 256 + def foo255(): Int = 257 + def foo256(): Int = 258 + def foo257(): Int = 259 + def foo258(): Int = 260 + def foo259(): Int = 261 + def foo260(): Int = 262 + def foo261(): Int = 263 + def foo262(): Int = 264 + def foo263(): Int = 265 + def foo264(): Int = 266 + def foo265(): Int = 267 + def foo266(): Int = 268 + def foo267(): Int = 269 + def foo268(): Int = 270 + def foo269(): Int = 271 + def foo270(): Int = 272 + def foo271(): Int = 273 + def foo272(): Int = 274 + def foo273(): Int = 275 + def foo274(): Int = 276 + def foo275(): Int = 277 + def foo276(): Int = 278 + def foo277(): Int = 279 + def foo278(): Int = 280 + def foo279(): Int = 281 + def foo280(): Int = 282 + def foo281(): Int = 283 + def foo282(): Int = 284 + def foo283(): Int = 285 + def foo284(): Int = 286 + def foo285(): Int = 287 + def foo286(): Int = 288 + def foo287(): Int = 289 + def foo288(): Int = 290 + def foo289(): Int = 291 + def foo290(): Int = 292 + def foo291(): Int = 293 + def foo292(): Int = 294 + def foo293(): Int = 295 + def foo294(): Int = 296 + def foo295(): Int = 297 + def foo296(): Int = 298 + def foo297(): Int = 299 + def foo298(): Int = 300 + def foo299(): Int = 301 + def foo300(): Int = 302 + def foo301(): Int = 303 + def foo302(): Int = 304 + def foo303(): Int = 305 + def foo304(): Int = 306 + def foo305(): Int = 307 + def foo306(): Int = 308 + def foo307(): Int = 309 + def foo308(): Int = 310 + def foo309(): Int = 311 + def foo310(): Int = 312 + def foo311(): Int = 313 + def foo312(): Int = 314 + def foo313(): Int = 315 + def foo314(): Int = 316 + def foo315(): Int = 317 + def foo316(): Int = 318 + def foo317(): Int = 319 + def foo318(): Int = 320 + def foo319(): Int = 321 + def foo320(): Int = 322 + def foo321(): Int = 323 + def foo322(): Int = 324 + def foo323(): Int = 325 + def foo324(): Int = 326 + def foo325(): Int = 327 + def foo326(): Int = 328 + def foo327(): Int = 329 + def foo328(): Int = 330 + def foo329(): Int = 331 + def foo330(): Int = 332 + def foo331(): Int = 333 + def foo332(): Int = 334 + def foo333(): Int = 335 + def foo334(): Int = 336 + def foo335(): Int = 337 + def foo336(): Int = 338 + def foo337(): Int = 339 + def foo338(): Int = 340 + def foo339(): Int = 341 + def foo340(): Int = 342 + def foo341(): Int = 343 + def foo342(): Int = 344 + def foo343(): Int = 345 + def foo344(): Int = 346 + def foo345(): Int = 347 + def foo346(): Int = 348 + def foo347(): Int = 349 + def foo348(): Int = 350 + def foo349(): Int = 351 + def foo350(): Int = 352 + def foo351(): Int = 353 + def foo352(): Int = 354 + def foo353(): Int = 355 + def foo354(): Int = 356 + def foo355(): Int = 357 + def foo356(): Int = 358 + def foo357(): Int = 359 + def foo358(): Int = 360 + def foo359(): Int = 361 + def foo360(): Int = 362 + def foo361(): Int = 363 + def foo362(): Int = 364 + def foo363(): Int = 365 + def foo364(): Int = 366 + def foo365(): Int = 367 + def foo366(): Int = 368 + def foo367(): Int = 369 + def foo368(): Int = 370 + def foo369(): Int = 371 + def foo370(): Int = 372 + def foo371(): Int = 373 + def foo372(): Int = 374 + def foo373(): Int = 375 + def foo374(): Int = 376 + def foo375(): Int = 377 + def foo376(): Int = 378 + def foo377(): Int = 379 + def foo378(): Int = 380 + def foo379(): Int = 381 + def foo380(): Int = 382 + def foo381(): Int = 383 + def foo382(): Int = 384 + def foo383(): Int = 385 + def foo384(): Int = 386 + def foo385(): Int = 387 + def foo386(): Int = 388 + def foo387(): Int = 389 + def foo388(): Int = 390 + def foo389(): Int = 391 + def foo390(): Int = 392 + def foo391(): Int = 393 + def foo392(): Int = 394 + def foo393(): Int = 395 + def foo394(): Int = 396 + def foo395(): Int = 397 + def foo396(): Int = 398 + def foo397(): Int = 399 + def foo398(): Int = 400 + def foo399(): Int = 401 + def foo400(): Int = 402 + def foo401(): Int = 403 + def foo402(): Int = 404 + def foo403(): Int = 405 + def foo404(): Int = 406 + def foo405(): Int = 407 + def foo406(): Int = 408 + def foo407(): Int = 409 + def foo408(): Int = 410 + def foo409(): Int = 411 + def foo410(): Int = 412 + def foo411(): Int = 413 + def foo412(): Int = 414 + def foo413(): Int = 415 + def foo414(): Int = 416 + def foo415(): Int = 417 + def foo416(): Int = 418 + def foo417(): Int = 419 + def foo418(): Int = 420 + def foo419(): Int = 421 + def foo420(): Int = 422 + def foo421(): Int = 423 + def foo422(): Int = 424 + def foo423(): Int = 425 + def foo424(): Int = 426 + def foo425(): Int = 427 + def foo426(): Int = 428 + def foo427(): Int = 429 + def foo428(): Int = 430 + def foo429(): Int = 431 + def foo430(): Int = 432 + def foo431(): Int = 433 + def foo432(): Int = 434 + def foo433(): Int = 435 + def foo434(): Int = 436 + def foo435(): Int = 437 + def foo436(): Int = 438 + def foo437(): Int = 439 + def foo438(): Int = 440 + def foo439(): Int = 441 + def foo440(): Int = 442 + def foo441(): Int = 443 + def foo442(): Int = 444 + def foo443(): Int = 445 + def foo444(): Int = 446 + def foo445(): Int = 447 + def foo446(): Int = 448 + def foo447(): Int = 449 + def foo448(): Int = 450 + def foo449(): Int = 451 + def foo450(): Int = 452 + def foo451(): Int = 453 + def foo452(): Int = 454 + def foo453(): Int = 455 + def foo454(): Int = 456 + def foo455(): Int = 457 + def foo456(): Int = 458 + def foo457(): Int = 459 + def foo458(): Int = 460 + def foo459(): Int = 461 + def foo460(): Int = 462 + def foo461(): Int = 463 + def foo462(): Int = 464 + def foo463(): Int = 465 + def foo464(): Int = 466 + def foo465(): Int = 467 + def foo466(): Int = 468 + def foo467(): Int = 469 + def foo468(): Int = 470 + def foo469(): Int = 471 + def foo470(): Int = 472 + def foo471(): Int = 473 + def foo472(): Int = 474 + def foo473(): Int = 475 + def foo474(): Int = 476 + def foo475(): Int = 477 + def foo476(): Int = 478 + def foo477(): Int = 479 + def foo478(): Int = 480 + def foo479(): Int = 481 + def foo480(): Int = 482 + def foo481(): Int = 483 + def foo482(): Int = 484 + def foo483(): Int = 485 + def foo484(): Int = 486 + def foo485(): Int = 487 + def foo486(): Int = 488 + def foo487(): Int = 489 + def foo488(): Int = 490 + def foo489(): Int = 491 + def foo490(): Int = 492 + def foo491(): Int = 493 + def foo492(): Int = 494 + def foo493(): Int = 495 + def foo494(): Int = 496 + def foo495(): Int = 497 + def foo496(): Int = 498 + def foo497(): Int = 499 + def foo498(): Int = 500 + def foo499(): Int = 501 + def foo500(): Int = 502 + def foo501(): Int = 503 + def foo502(): Int = 504 + def foo503(): Int = 505 + def foo504(): Int = 506 + def foo505(): Int = 507 + def foo506(): Int = 508 + def foo507(): Int = 509 + def foo508(): Int = 510 + def foo509(): Int = 511 + def foo510(): Int = 512 + def foo511(): Int = 513 + def foo512(): Int = 514 + def foo513(): Int = 515 + def foo514(): Int = 516 + def foo515(): Int = 517 + def foo516(): Int = 518 + def foo517(): Int = 519 + def foo518(): Int = 520 + def foo519(): Int = 521 + def foo520(): Int = 522 + def foo521(): Int = 523 + def foo522(): Int = 524 + def foo523(): Int = 525 + def foo524(): Int = 526 + def foo525(): Int = 527 + def foo526(): Int = 528 + def foo527(): Int = 529 + def foo528(): Int = 530 + def foo529(): Int = 531 + def foo530(): Int = 532 + def foo531(): Int = 533 + def foo532(): Int = 534 + def foo533(): Int = 535 + def foo534(): Int = 536 + def foo535(): Int = 537 + def foo536(): Int = 538 + def foo537(): Int = 539 + def foo538(): Int = 540 + def foo539(): Int = 541 + def foo540(): Int = 542 + def foo541(): Int = 543 + def foo542(): Int = 544 + def foo543(): Int = 545 + def foo544(): Int = 546 + def foo545(): Int = 547 + def foo546(): Int = 548 + def foo547(): Int = 549 + def foo548(): Int = 550 + def foo549(): Int = 551 + def foo550(): Int = 552 + def foo551(): Int = 553 + def foo552(): Int = 554 + def foo553(): Int = 555 + def foo554(): Int = 556 + def foo555(): Int = 557 + def foo556(): Int = 558 + def foo557(): Int = 559 + def foo558(): Int = 560 + def foo559(): Int = 561 + def foo560(): Int = 562 + def foo561(): Int = 563 + def foo562(): Int = 564 + def foo563(): Int = 565 + def foo564(): Int = 566 + def foo565(): Int = 567 + def foo566(): Int = 568 + def foo567(): Int = 569 + def foo568(): Int = 570 + def foo569(): Int = 571 + def foo570(): Int = 572 + def foo571(): Int = 573 + def foo572(): Int = 574 + def foo573(): Int = 575 + def foo574(): Int = 576 + def foo575(): Int = 577 + def foo576(): Int = 578 + def foo577(): Int = 579 + def foo578(): Int = 580 + def foo579(): Int = 581 + def foo580(): Int = 582 + def foo581(): Int = 583 + def foo582(): Int = 584 + def foo583(): Int = 585 + def foo584(): Int = 586 + def foo585(): Int = 587 + def foo586(): Int = 588 + def foo587(): Int = 589 + def foo588(): Int = 590 + def foo589(): Int = 591 + def foo590(): Int = 592 + def foo591(): Int = 593 + def foo592(): Int = 594 + def foo593(): Int = 595 + def foo594(): Int = 596 + def foo595(): Int = 597 + def foo596(): Int = 598 + def foo597(): Int = 599 + def foo598(): Int = 600 + def foo599(): Int = 601 + def foo600(): Int = 602 + def foo601(): Int = 603 + def foo602(): Int = 604 + def foo603(): Int = 605 + def foo604(): Int = 606 + def foo605(): Int = 607 + def foo606(): Int = 608 + def foo607(): Int = 609 + def foo608(): Int = 610 + def foo609(): Int = 611 + def foo610(): Int = 612 + def foo611(): Int = 613 + def foo612(): Int = 614 + def foo613(): Int = 615 + def foo614(): Int = 616 + def foo615(): Int = 617 + def foo616(): Int = 618 + def foo617(): Int = 619 + def foo618(): Int = 620 + def foo619(): Int = 621 + def foo620(): Int = 622 + def foo621(): Int = 623 + def foo622(): Int = 624 + def foo623(): Int = 625 + def foo624(): Int = 626 + def foo625(): Int = 627 + def foo626(): Int = 628 + def foo627(): Int = 629 + def foo628(): Int = 630 + def foo629(): Int = 631 + def foo630(): Int = 632 + def foo631(): Int = 633 + def foo632(): Int = 634 + def foo633(): Int = 635 + def foo634(): Int = 636 + def foo635(): Int = 637 + def foo636(): Int = 638 + def foo637(): Int = 639 + def foo638(): Int = 640 + def foo639(): Int = 641 + def foo640(): Int = 642 + def foo641(): Int = 643 + def foo642(): Int = 644 + def foo643(): Int = 645 + def foo644(): Int = 646 + def foo645(): Int = 647 + def foo646(): Int = 648 + def foo647(): Int = 649 + def foo648(): Int = 650 + def foo649(): Int = 651 + def foo650(): Int = 652 + def foo651(): Int = 653 + def foo652(): Int = 654 + def foo653(): Int = 655 + def foo654(): Int = 656 + def foo655(): Int = 657 + def foo656(): Int = 658 + def foo657(): Int = 659 + def foo658(): Int = 660 + def foo659(): Int = 661 + def foo660(): Int = 662 + def foo661(): Int = 663 + def foo662(): Int = 664 + def foo663(): Int = 665 + def foo664(): Int = 666 + def foo665(): Int = 667 + def foo666(): Int = 668 + def foo667(): Int = 669 + def foo668(): Int = 670 + def foo669(): Int = 671 + def foo670(): Int = 672 + def foo671(): Int = 673 + def foo672(): Int = 674 + def foo673(): Int = 675 + def foo674(): Int = 676 + def foo675(): Int = 677 + def foo676(): Int = 678 + def foo677(): Int = 679 + def foo678(): Int = 680 + def foo679(): Int = 681 + def foo680(): Int = 682 + def foo681(): Int = 683 + def foo682(): Int = 684 + def foo683(): Int = 685 + def foo684(): Int = 686 + def foo685(): Int = 687 + def foo686(): Int = 688 + def foo687(): Int = 689 + def foo688(): Int = 690 + def foo689(): Int = 691 + def foo690(): Int = 692 + def foo691(): Int = 693 + def foo692(): Int = 694 + def foo693(): Int = 695 + def foo694(): Int = 696 + def foo695(): Int = 697 + def foo696(): Int = 698 + def foo697(): Int = 699 + def foo698(): Int = 700 + def foo699(): Int = 701 + def foo700(): Int = 702 + def foo701(): Int = 703 + def foo702(): Int = 704 + def foo703(): Int = 705 + def foo704(): Int = 706 + def foo705(): Int = 707 + def foo706(): Int = 708 + def foo707(): Int = 709 + def foo708(): Int = 710 + def foo709(): Int = 711 + def foo710(): Int = 712 + def foo711(): Int = 713 + def foo712(): Int = 714 + def foo713(): Int = 715 + def foo714(): Int = 716 + def foo715(): Int = 717 + def foo716(): Int = 718 + def foo717(): Int = 719 + def foo718(): Int = 720 + def foo719(): Int = 721 + def foo720(): Int = 722 + def foo721(): Int = 723 + def foo722(): Int = 724 + def foo723(): Int = 725 + def foo724(): Int = 726 + def foo725(): Int = 727 + def foo726(): Int = 728 + def foo727(): Int = 729 + def foo728(): Int = 730 + def foo729(): Int = 731 + def foo730(): Int = 732 + def foo731(): Int = 733 + def foo732(): Int = 734 + def foo733(): Int = 735 + def foo734(): Int = 736 + def foo735(): Int = 737 + def foo736(): Int = 738 + def foo737(): Int = 739 + def foo738(): Int = 740 + def foo739(): Int = 741 + def foo740(): Int = 742 + def foo741(): Int = 743 + def foo742(): Int = 744 + def foo743(): Int = 745 + def foo744(): Int = 746 + def foo745(): Int = 747 + def foo746(): Int = 748 + def foo747(): Int = 749 + def foo748(): Int = 750 + def foo749(): Int = 751 + def foo750(): Int = 752 + def foo751(): Int = 753 + def foo752(): Int = 754 + def foo753(): Int = 755 + def foo754(): Int = 756 + def foo755(): Int = 757 + def foo756(): Int = 758 + def foo757(): Int = 759 + def foo758(): Int = 760 + def foo759(): Int = 761 + def foo760(): Int = 762 + def foo761(): Int = 763 + def foo762(): Int = 764 + def foo763(): Int = 765 + def foo764(): Int = 766 + def foo765(): Int = 767 + def foo766(): Int = 768 + def foo767(): Int = 769 + def foo768(): Int = 770 + def foo769(): Int = 771 + def foo770(): Int = 772 + def foo771(): Int = 773 + def foo772(): Int = 774 + def foo773(): Int = 775 + def foo774(): Int = 776 + def foo775(): Int = 777 + def foo776(): Int = 778 + def foo777(): Int = 779 + def foo778(): Int = 780 + def foo779(): Int = 781 + def foo780(): Int = 782 + def foo781(): Int = 783 + def foo782(): Int = 784 + def foo783(): Int = 785 + def foo784(): Int = 786 + def foo785(): Int = 787 + def foo786(): Int = 788 + def foo787(): Int = 789 + def foo788(): Int = 790 + def foo789(): Int = 791 + def foo790(): Int = 792 + def foo791(): Int = 793 + def foo792(): Int = 794 + def foo793(): Int = 795 + def foo794(): Int = 796 + def foo795(): Int = 797 + def foo796(): Int = 798 + def foo797(): Int = 799 + def foo798(): Int = 800 + def foo799(): Int = 801 + def foo800(): Int = 802 + def foo801(): Int = 803 + def foo802(): Int = 804 + def foo803(): Int = 805 + def foo804(): Int = 806 + def foo805(): Int = 807 + def foo806(): Int = 808 + def foo807(): Int = 809 + def foo808(): Int = 810 + def foo809(): Int = 811 + def foo810(): Int = 812 + def foo811(): Int = 813 + def foo812(): Int = 814 + def foo813(): Int = 815 + def foo814(): Int = 816 + def foo815(): Int = 817 + def foo816(): Int = 818 + def foo817(): Int = 819 + def foo818(): Int = 820 + def foo819(): Int = 821 + def foo820(): Int = 822 + def foo821(): Int = 823 + def foo822(): Int = 824 + def foo823(): Int = 825 + def foo824(): Int = 826 + def foo825(): Int = 827 + def foo826(): Int = 828 + def foo827(): Int = 829 + def foo828(): Int = 830 + def foo829(): Int = 831 + def foo830(): Int = 832 + def foo831(): Int = 833 + def foo832(): Int = 834 + def foo833(): Int = 835 + def foo834(): Int = 836 + def foo835(): Int = 837 + def foo836(): Int = 838 + def foo837(): Int = 839 + def foo838(): Int = 840 + def foo839(): Int = 841 + def foo840(): Int = 842 + def foo841(): Int = 843 + def foo842(): Int = 844 + def foo843(): Int = 845 + def foo844(): Int = 846 + def foo845(): Int = 847 + def foo846(): Int = 848 + def foo847(): Int = 849 + def foo848(): Int = 850 + def foo849(): Int = 851 + def foo850(): Int = 852 + def foo851(): Int = 853 + def foo852(): Int = 854 + def foo853(): Int = 855 + def foo854(): Int = 856 + def foo855(): Int = 857 + def foo856(): Int = 858 + def foo857(): Int = 859 + def foo858(): Int = 860 + def foo859(): Int = 861 + def foo860(): Int = 862 + def foo861(): Int = 863 + def foo862(): Int = 864 + def foo863(): Int = 865 + def foo864(): Int = 866 + def foo865(): Int = 867 + def foo866(): Int = 868 + def foo867(): Int = 869 + def foo868(): Int = 870 + def foo869(): Int = 871 + def foo870(): Int = 872 + def foo871(): Int = 873 + def foo872(): Int = 874 + def foo873(): Int = 875 + def foo874(): Int = 876 + def foo875(): Int = 877 + def foo876(): Int = 878 + def foo877(): Int = 879 + def foo878(): Int = 880 + def foo879(): Int = 881 + def foo880(): Int = 882 + def foo881(): Int = 883 + def foo882(): Int = 884 + def foo883(): Int = 885 + def foo884(): Int = 886 + def foo885(): Int = 887 + def foo886(): Int = 888 + def foo887(): Int = 889 + def foo888(): Int = 890 + def foo889(): Int = 891 + def foo890(): Int = 892 + def foo891(): Int = 893 + def foo892(): Int = 894 + def foo893(): Int = 895 + def foo894(): Int = 896 + def foo895(): Int = 897 + def foo896(): Int = 898 + def foo897(): Int = 899 + def foo898(): Int = 900 + def foo899(): Int = 901 + def foo900(): Int = 902 + def foo901(): Int = 903 + def foo902(): Int = 904 + def foo903(): Int = 905 + def foo904(): Int = 906 + def foo905(): Int = 907 + def foo906(): Int = 908 + def foo907(): Int = 909 + def foo908(): Int = 910 + def foo909(): Int = 911 + def foo910(): Int = 912 + def foo911(): Int = 913 + def foo912(): Int = 914 + def foo913(): Int = 915 + def foo914(): Int = 916 + def foo915(): Int = 917 + def foo916(): Int = 918 + def foo917(): Int = 919 + def foo918(): Int = 920 + def foo919(): Int = 921 + def foo920(): Int = 922 + def foo921(): Int = 923 + def foo922(): Int = 924 + def foo923(): Int = 925 + def foo924(): Int = 926 + def foo925(): Int = 927 + def foo926(): Int = 928 + def foo927(): Int = 929 + def foo928(): Int = 930 + def foo929(): Int = 931 + def foo930(): Int = 932 + def foo931(): Int = 933 + def foo932(): Int = 934 + def foo933(): Int = 935 + def foo934(): Int = 936 + def foo935(): Int = 937 + def foo936(): Int = 938 + def foo937(): Int = 939 + def foo938(): Int = 940 + def foo939(): Int = 941 + def foo940(): Int = 942 + def foo941(): Int = 943 + def foo942(): Int = 944 + def foo943(): Int = 945 + def foo944(): Int = 946 + def foo945(): Int = 947 + def foo946(): Int = 948 + def foo947(): Int = 949 + def foo948(): Int = 950 + def foo949(): Int = 951 + def foo950(): Int = 952 + def foo951(): Int = 953 + def foo952(): Int = 954 + def foo953(): Int = 955 + def foo954(): Int = 956 + def foo955(): Int = 957 + def foo956(): Int = 958 + def foo957(): Int = 959 + def foo958(): Int = 960 + def foo959(): Int = 961 + def foo960(): Int = 962 + def foo961(): Int = 963 + def foo962(): Int = 964 + def foo963(): Int = 965 + def foo964(): Int = 966 + def foo965(): Int = 967 + def foo966(): Int = 968 + def foo967(): Int = 969 + def foo968(): Int = 970 + def foo969(): Int = 971 + def foo970(): Int = 972 + def foo971(): Int = 973 + def foo972(): Int = 974 + def foo973(): Int = 975 + def foo974(): Int = 976 + def foo975(): Int = 977 + def foo976(): Int = 978 + def foo977(): Int = 979 + def foo978(): Int = 980 + def foo979(): Int = 981 + def foo980(): Int = 982 + def foo981(): Int = 983 + def foo982(): Int = 984 + def foo983(): Int = 985 + def foo984(): Int = 986 + def foo985(): Int = 987 + def foo986(): Int = 988 + def foo987(): Int = 989 + def foo988(): Int = 990 + def foo989(): Int = 991 + def foo990(): Int = 992 + def foo991(): Int = 993 + def foo992(): Int = 994 + def foo993(): Int = 995 + def foo994(): Int = 996 + def foo995(): Int = 997 + def foo996(): Int = 998 + def foo997(): Int = 999 + def foo998(): Int = 1000 + def foo999(): Int = 1001 + def foo1000(): Int = 1002 + def foo1001(): Int = 1003 + def foo1002(): Int = 1004 + def foo1003(): Int = 1005 + def foo1004(): Int = 1006 + def foo1005(): Int = 1007 + def foo1006(): Int = 1008 + def foo1007(): Int = 1009 + def foo1008(): Int = 1010 + def foo1009(): Int = 1011 + def foo1010(): Int = 1012 + def foo1011(): Int = 1013 + def foo1012(): Int = 1014 + def foo1013(): Int = 1015 + def foo1014(): Int = 1016 + def foo1015(): Int = 1017 + def foo1016(): Int = 1018 + def foo1017(): Int = 1019 + def foo1018(): Int = 1020 + def foo1019(): Int = 1021 + def foo1020(): Int = 1022 + def foo1021(): Int = 1023 + def foo1022(): Int = 1024 + def foo1023(): Int = 1025 + def foo1024(): Int = 1026 + def foo1025(): Int = 1027 + def foo1026(): Int = 1028 + def foo1027(): Int = 1029 + def foo1028(): Int = 1030 + def foo1029(): Int = 1031 + def foo1030(): Int = 1032 + def foo1031(): Int = 1033 + def foo1032(): Int = 1034 + def foo1033(): Int = 1035 + def foo1034(): Int = 1036 + def foo1035(): Int = 1037 + def foo1036(): Int = 1038 + def foo1037(): Int = 1039 + def foo1038(): Int = 1040 + def foo1039(): Int = 1041 + def foo1040(): Int = 1042 + def foo1041(): Int = 1043 + def foo1042(): Int = 1044 + def foo1043(): Int = 1045 + def foo1044(): Int = 1046 + def foo1045(): Int = 1047 + def foo1046(): Int = 1048 + def foo1047(): Int = 1049 + def foo1048(): Int = 1050 + def foo1049(): Int = 1051 + def foo1050(): Int = 1052 + def foo1051(): Int = 1053 + def foo1052(): Int = 1054 + def foo1053(): Int = 1055 + def foo1054(): Int = 1056 + def foo1055(): Int = 1057 + def foo1056(): Int = 1058 + def foo1057(): Int = 1059 + def foo1058(): Int = 1060 + def foo1059(): Int = 1061 + def foo1060(): Int = 1062 + def foo1061(): Int = 1063 + def foo1062(): Int = 1064 + def foo1063(): Int = 1065 + def foo1064(): Int = 1066 + def foo1065(): Int = 1067 + def foo1066(): Int = 1068 + def foo1067(): Int = 1069 + def foo1068(): Int = 1070 + def foo1069(): Int = 1071 + def foo1070(): Int = 1072 + def foo1071(): Int = 1073 + def foo1072(): Int = 1074 + def foo1073(): Int = 1075 + def foo1074(): Int = 1076 + def foo1075(): Int = 1077 + def foo1076(): Int = 1078 + def foo1077(): Int = 1079 + def foo1078(): Int = 1080 + def foo1079(): Int = 1081 + def foo1080(): Int = 1082 + def foo1081(): Int = 1083 + def foo1082(): Int = 1084 + def foo1083(): Int = 1085 + def foo1084(): Int = 1086 + def foo1085(): Int = 1087 + def foo1086(): Int = 1088 + def foo1087(): Int = 1089 + def foo1088(): Int = 1090 + def foo1089(): Int = 1091 + def foo1090(): Int = 1092 + def foo1091(): Int = 1093 + def foo1092(): Int = 1094 + def foo1093(): Int = 1095 + def foo1094(): Int = 1096 + def foo1095(): Int = 1097 + def foo1096(): Int = 1098 + def foo1097(): Int = 1099 + def foo1098(): Int = 1100 + def foo1099(): Int = 1101 + def foo1100(): Int = 1102 + def foo1101(): Int = 1103 + def foo1102(): Int = 1104 + def foo1103(): Int = 1105 + def foo1104(): Int = 1106 + def foo1105(): Int = 1107 + def foo1106(): Int = 1108 + def foo1107(): Int = 1109 + def foo1108(): Int = 1110 + def foo1109(): Int = 1111 + def foo1110(): Int = 1112 + def foo1111(): Int = 1113 + def foo1112(): Int = 1114 + def foo1113(): Int = 1115 + def foo1114(): Int = 1116 + def foo1115(): Int = 1117 + def foo1116(): Int = 1118 + def foo1117(): Int = 1119 + def foo1118(): Int = 1120 + def foo1119(): Int = 1121 + def foo1120(): Int = 1122 + def foo1121(): Int = 1123 + def foo1122(): Int = 1124 + def foo1123(): Int = 1125 + def foo1124(): Int = 1126 + def foo1125(): Int = 1127 + def foo1126(): Int = 1128 + def foo1127(): Int = 1129 + def foo1128(): Int = 1130 + def foo1129(): Int = 1131 + def foo1130(): Int = 1132 + def foo1131(): Int = 1133 + def foo1132(): Int = 1134 + def foo1133(): Int = 1135 + def foo1134(): Int = 1136 + def foo1135(): Int = 1137 + def foo1136(): Int = 1138 + def foo1137(): Int = 1139 + def foo1138(): Int = 1140 + def foo1139(): Int = 1141 + def foo1140(): Int = 1142 + def foo1141(): Int = 1143 + def foo1142(): Int = 1144 + def foo1143(): Int = 1145 + def foo1144(): Int = 1146 + def foo1145(): Int = 1147 + def foo1146(): Int = 1148 + def foo1147(): Int = 1149 + def foo1148(): Int = 1150 + def foo1149(): Int = 1151 + def foo1150(): Int = 1152 + def foo1151(): Int = 1153 + def foo1152(): Int = 1154 + def foo1153(): Int = 1155 + def foo1154(): Int = 1156 + def foo1155(): Int = 1157 + def foo1156(): Int = 1158 + def foo1157(): Int = 1159 + def foo1158(): Int = 1160 + def foo1159(): Int = 1161 + def foo1160(): Int = 1162 + def foo1161(): Int = 1163 + def foo1162(): Int = 1164 + def foo1163(): Int = 1165 + def foo1164(): Int = 1166 + def foo1165(): Int = 1167 + def foo1166(): Int = 1168 + def foo1167(): Int = 1169 + def foo1168(): Int = 1170 + def foo1169(): Int = 1171 + def foo1170(): Int = 1172 + def foo1171(): Int = 1173 + def foo1172(): Int = 1174 + def foo1173(): Int = 1175 + def foo1174(): Int = 1176 + def foo1175(): Int = 1177 + def foo1176(): Int = 1178 + def foo1177(): Int = 1179 + def foo1178(): Int = 1180 + def foo1179(): Int = 1181 + def foo1180(): Int = 1182 + def foo1181(): Int = 1183 + def foo1182(): Int = 1184 + def foo1183(): Int = 1185 + def foo1184(): Int = 1186 + def foo1185(): Int = 1187 + def foo1186(): Int = 1188 + def foo1187(): Int = 1189 + def foo1188(): Int = 1190 + def foo1189(): Int = 1191 + def foo1190(): Int = 1192 + def foo1191(): Int = 1193 + def foo1192(): Int = 1194 + def foo1193(): Int = 1195 + def foo1194(): Int = 1196 + def foo1195(): Int = 1197 + def foo1196(): Int = 1198 + def foo1197(): Int = 1199 + def foo1198(): Int = 1200 + def foo1199(): Int = 1201 + def foo1200(): Int = 1202 + def foo1201(): Int = 1203 + def foo1202(): Int = 1204 + def foo1203(): Int = 1205 + def foo1204(): Int = 1206 + def foo1205(): Int = 1207 + def foo1206(): Int = 1208 + def foo1207(): Int = 1209 + def foo1208(): Int = 1210 + def foo1209(): Int = 1211 + def foo1210(): Int = 1212 + def foo1211(): Int = 1213 + def foo1212(): Int = 1214 + def foo1213(): Int = 1215 + def foo1214(): Int = 1216 + def foo1215(): Int = 1217 + def foo1216(): Int = 1218 + def foo1217(): Int = 1219 + def foo1218(): Int = 1220 + def foo1219(): Int = 1221 + def foo1220(): Int = 1222 + def foo1221(): Int = 1223 + def foo1222(): Int = 1224 + def foo1223(): Int = 1225 + def foo1224(): Int = 1226 + def foo1225(): Int = 1227 + def foo1226(): Int = 1228 + def foo1227(): Int = 1229 + def foo1228(): Int = 1230 + def foo1229(): Int = 1231 + def foo1230(): Int = 1232 + def foo1231(): Int = 1233 + def foo1232(): Int = 1234 + def foo1233(): Int = 1235 + def foo1234(): Int = 1236 + def foo1235(): Int = 1237 + def foo1236(): Int = 1238 + def foo1237(): Int = 1239 + def foo1238(): Int = 1240 + def foo1239(): Int = 1241 + def foo1240(): Int = 1242 + def foo1241(): Int = 1243 + def foo1242(): Int = 1244 + def foo1243(): Int = 1245 + def foo1244(): Int = 1246 + def foo1245(): Int = 1247 + def foo1246(): Int = 1248 + def foo1247(): Int = 1249 + def foo1248(): Int = 1250 + def foo1249(): Int = 1251 + def foo1250(): Int = 1252 + def foo1251(): Int = 1253 + def foo1252(): Int = 1254 + def foo1253(): Int = 1255 + def foo1254(): Int = 1256 + def foo1255(): Int = 1257 + def foo1256(): Int = 1258 + def foo1257(): Int = 1259 + def foo1258(): Int = 1260 + def foo1259(): Int = 1261 + def foo1260(): Int = 1262 + def foo1261(): Int = 1263 + def foo1262(): Int = 1264 + def foo1263(): Int = 1265 + def foo1264(): Int = 1266 + def foo1265(): Int = 1267 + def foo1266(): Int = 1268 + def foo1267(): Int = 1269 + def foo1268(): Int = 1270 + def foo1269(): Int = 1271 + def foo1270(): Int = 1272 + def foo1271(): Int = 1273 + def foo1272(): Int = 1274 + def foo1273(): Int = 1275 + def foo1274(): Int = 1276 + def foo1275(): Int = 1277 + def foo1276(): Int = 1278 + def foo1277(): Int = 1279 + def foo1278(): Int = 1280 + def foo1279(): Int = 1281 + def foo1280(): Int = 1282 + def foo1281(): Int = 1283 + def foo1282(): Int = 1284 + def foo1283(): Int = 1285 + def foo1284(): Int = 1286 + def foo1285(): Int = 1287 + def foo1286(): Int = 1288 + def foo1287(): Int = 1289 + def foo1288(): Int = 1290 + def foo1289(): Int = 1291 + def foo1290(): Int = 1292 + def foo1291(): Int = 1293 + def foo1292(): Int = 1294 + def foo1293(): Int = 1295 + def foo1294(): Int = 1296 + def foo1295(): Int = 1297 + def foo1296(): Int = 1298 + def foo1297(): Int = 1299 + def foo1298(): Int = 1300 + def foo1299(): Int = 1301 + def foo1300(): Int = 1302 + def foo1301(): Int = 1303 + def foo1302(): Int = 1304 + def foo1303(): Int = 1305 + def foo1304(): Int = 1306 + def foo1305(): Int = 1307 + def foo1306(): Int = 1308 + def foo1307(): Int = 1309 + def foo1308(): Int = 1310 + def foo1309(): Int = 1311 + def foo1310(): Int = 1312 + def foo1311(): Int = 1313 + def foo1312(): Int = 1314 + def foo1313(): Int = 1315 + def foo1314(): Int = 1316 + def foo1315(): Int = 1317 + def foo1316(): Int = 1318 + def foo1317(): Int = 1319 + def foo1318(): Int = 1320 + def foo1319(): Int = 1321 + def foo1320(): Int = 1322 + def foo1321(): Int = 1323 + def foo1322(): Int = 1324 + def foo1323(): Int = 1325 + def foo1324(): Int = 1326 + def foo1325(): Int = 1327 + def foo1326(): Int = 1328 + def foo1327(): Int = 1329 + def foo1328(): Int = 1330 + def foo1329(): Int = 1331 + def foo1330(): Int = 1332 + def foo1331(): Int = 1333 + def foo1332(): Int = 1334 + def foo1333(): Int = 1335 + def foo1334(): Int = 1336 + def foo1335(): Int = 1337 + def foo1336(): Int = 1338 + def foo1337(): Int = 1339 + def foo1338(): Int = 1340 + def foo1339(): Int = 1341 + def foo1340(): Int = 1342 + def foo1341(): Int = 1343 + def foo1342(): Int = 1344 + def foo1343(): Int = 1345 + def foo1344(): Int = 1346 + def foo1345(): Int = 1347 + def foo1346(): Int = 1348 + def foo1347(): Int = 1349 + def foo1348(): Int = 1350 + def foo1349(): Int = 1351 + def foo1350(): Int = 1352 + def foo1351(): Int = 1353 + def foo1352(): Int = 1354 + def foo1353(): Int = 1355 + def foo1354(): Int = 1356 + def foo1355(): Int = 1357 + def foo1356(): Int = 1358 + def foo1357(): Int = 1359 + def foo1358(): Int = 1360 + def foo1359(): Int = 1361 + def foo1360(): Int = 1362 + def foo1361(): Int = 1363 + def foo1362(): Int = 1364 + def foo1363(): Int = 1365 + def foo1364(): Int = 1366 + def foo1365(): Int = 1367 + def foo1366(): Int = 1368 + def foo1367(): Int = 1369 + def foo1368(): Int = 1370 + def foo1369(): Int = 1371 + def foo1370(): Int = 1372 + def foo1371(): Int = 1373 + def foo1372(): Int = 1374 + def foo1373(): Int = 1375 + def foo1374(): Int = 1376 + def foo1375(): Int = 1377 + def foo1376(): Int = 1378 + def foo1377(): Int = 1379 + def foo1378(): Int = 1380 + def foo1379(): Int = 1381 + def foo1380(): Int = 1382 + def foo1381(): Int = 1383 + def foo1382(): Int = 1384 + def foo1383(): Int = 1385 + def foo1384(): Int = 1386 + def foo1385(): Int = 1387 + def foo1386(): Int = 1388 + def foo1387(): Int = 1389 + def foo1388(): Int = 1390 + def foo1389(): Int = 1391 + def foo1390(): Int = 1392 + def foo1391(): Int = 1393 + def foo1392(): Int = 1394 + def foo1393(): Int = 1395 + def foo1394(): Int = 1396 + def foo1395(): Int = 1397 + def foo1396(): Int = 1398 + def foo1397(): Int = 1399 + def foo1398(): Int = 1400 + def foo1399(): Int = 1401 + def foo1400(): Int = 1402 + def foo1401(): Int = 1403 + def foo1402(): Int = 1404 + def foo1403(): Int = 1405 + def foo1404(): Int = 1406 + def foo1405(): Int = 1407 + def foo1406(): Int = 1408 + def foo1407(): Int = 1409 + def foo1408(): Int = 1410 + def foo1409(): Int = 1411 + def foo1410(): Int = 1412 + def foo1411(): Int = 1413 + def foo1412(): Int = 1414 + def foo1413(): Int = 1415 + def foo1414(): Int = 1416 + def foo1415(): Int = 1417 + def foo1416(): Int = 1418 + def foo1417(): Int = 1419 + def foo1418(): Int = 1420 + def foo1419(): Int = 1421 + def foo1420(): Int = 1422 + def foo1421(): Int = 1423 + def foo1422(): Int = 1424 + def foo1423(): Int = 1425 + def foo1424(): Int = 1426 + def foo1425(): Int = 1427 + def foo1426(): Int = 1428 + def foo1427(): Int = 1429 + def foo1428(): Int = 1430 + def foo1429(): Int = 1431 + def foo1430(): Int = 1432 + def foo1431(): Int = 1433 + def foo1432(): Int = 1434 + def foo1433(): Int = 1435 + def foo1434(): Int = 1436 + def foo1435(): Int = 1437 + def foo1436(): Int = 1438 + def foo1437(): Int = 1439 + def foo1438(): Int = 1440 + def foo1439(): Int = 1441 + def foo1440(): Int = 1442 + def foo1441(): Int = 1443 + def foo1442(): Int = 1444 + def foo1443(): Int = 1445 + def foo1444(): Int = 1446 + def foo1445(): Int = 1447 + def foo1446(): Int = 1448 + def foo1447(): Int = 1449 + def foo1448(): Int = 1450 + def foo1449(): Int = 1451 + def foo1450(): Int = 1452 + def foo1451(): Int = 1453 + def foo1452(): Int = 1454 + def foo1453(): Int = 1455 + def foo1454(): Int = 1456 + def foo1455(): Int = 1457 + def foo1456(): Int = 1458 + def foo1457(): Int = 1459 + def foo1458(): Int = 1460 + def foo1459(): Int = 1461 + def foo1460(): Int = 1462 + def foo1461(): Int = 1463 + def foo1462(): Int = 1464 + def foo1463(): Int = 1465 + def foo1464(): Int = 1466 + def foo1465(): Int = 1467 + def foo1466(): Int = 1468 + def foo1467(): Int = 1469 + def foo1468(): Int = 1470 + def foo1469(): Int = 1471 + def foo1470(): Int = 1472 + def foo1471(): Int = 1473 + def foo1472(): Int = 1474 + def foo1473(): Int = 1475 + def foo1474(): Int = 1476 + def foo1475(): Int = 1477 + def foo1476(): Int = 1478 + def foo1477(): Int = 1479 + def foo1478(): Int = 1480 + def foo1479(): Int = 1481 + def foo1480(): Int = 1482 + def foo1481(): Int = 1483 + def foo1482(): Int = 1484 + def foo1483(): Int = 1485 + def foo1484(): Int = 1486 + def foo1485(): Int = 1487 + def foo1486(): Int = 1488 + def foo1487(): Int = 1489 + def foo1488(): Int = 1490 + def foo1489(): Int = 1491 + def foo1490(): Int = 1492 + def foo1491(): Int = 1493 + def foo1492(): Int = 1494 + def foo1493(): Int = 1495 + def foo1494(): Int = 1496 + def foo1495(): Int = 1497 + def foo1496(): Int = 1498 + def foo1497(): Int = 1499 + def foo1498(): Int = 1500 + def foo1499(): Int = 1501 + def foo1500(): Int = 1502 + def foo1501(): Int = 1503 + def foo1502(): Int = 1504 + def foo1503(): Int = 1505 + def foo1504(): Int = 1506 + def foo1505(): Int = 1507 + def foo1506(): Int = 1508 + def foo1507(): Int = 1509 + def foo1508(): Int = 1510 + def foo1509(): Int = 1511 + def foo1510(): Int = 1512 + def foo1511(): Int = 1513 + def foo1512(): Int = 1514 + def foo1513(): Int = 1515 + def foo1514(): Int = 1516 + def foo1515(): Int = 1517 + def foo1516(): Int = 1518 + def foo1517(): Int = 1519 + def foo1518(): Int = 1520 + def foo1519(): Int = 1521 + def foo1520(): Int = 1522 + def foo1521(): Int = 1523 + def foo1522(): Int = 1524 + def foo1523(): Int = 1525 + def foo1524(): Int = 1526 + def foo1525(): Int = 1527 + def foo1526(): Int = 1528 + def foo1527(): Int = 1529 + def foo1528(): Int = 1530 + def foo1529(): Int = 1531 + def foo1530(): Int = 1532 + def foo1531(): Int = 1533 + def foo1532(): Int = 1534 + def foo1533(): Int = 1535 + def foo1534(): Int = 1536 + def foo1535(): Int = 1537 + def foo1536(): Int = 1538 + def foo1537(): Int = 1539 + def foo1538(): Int = 1540 + def foo1539(): Int = 1541 + def foo1540(): Int = 1542 + def foo1541(): Int = 1543 + def foo1542(): Int = 1544 + def foo1543(): Int = 1545 + def foo1544(): Int = 1546 + def foo1545(): Int = 1547 + def foo1546(): Int = 1548 + def foo1547(): Int = 1549 + def foo1548(): Int = 1550 + def foo1549(): Int = 1551 + def foo1550(): Int = 1552 + def foo1551(): Int = 1553 + def foo1552(): Int = 1554 + def foo1553(): Int = 1555 + def foo1554(): Int = 1556 + def foo1555(): Int = 1557 + def foo1556(): Int = 1558 + def foo1557(): Int = 1559 + def foo1558(): Int = 1560 + def foo1559(): Int = 1561 + def foo1560(): Int = 1562 + def foo1561(): Int = 1563 + def foo1562(): Int = 1564 + def foo1563(): Int = 1565 + def foo1564(): Int = 1566 + def foo1565(): Int = 1567 + def foo1566(): Int = 1568 + def foo1567(): Int = 1569 + def foo1568(): Int = 1570 + def foo1569(): Int = 1571 + def foo1570(): Int = 1572 + def foo1571(): Int = 1573 + def foo1572(): Int = 1574 + def foo1573(): Int = 1575 + def foo1574(): Int = 1576 + def foo1575(): Int = 1577 + def foo1576(): Int = 1578 + def foo1577(): Int = 1579 + def foo1578(): Int = 1580 + def foo1579(): Int = 1581 + def foo1580(): Int = 1582 + def foo1581(): Int = 1583 + def foo1582(): Int = 1584 + def foo1583(): Int = 1585 + def foo1584(): Int = 1586 + def foo1585(): Int = 1587 + def foo1586(): Int = 1588 + def foo1587(): Int = 1589 + def foo1588(): Int = 1590 + def foo1589(): Int = 1591 + def foo1590(): Int = 1592 + def foo1591(): Int = 1593 + def foo1592(): Int = 1594 + def foo1593(): Int = 1595 + def foo1594(): Int = 1596 + def foo1595(): Int = 1597 + def foo1596(): Int = 1598 + def foo1597(): Int = 1599 + def foo1598(): Int = 1600 + def foo1599(): Int = 1601 + def foo1600(): Int = 1602 + def foo1601(): Int = 1603 + def foo1602(): Int = 1604 + def foo1603(): Int = 1605 + def foo1604(): Int = 1606 + def foo1605(): Int = 1607 + def foo1606(): Int = 1608 + def foo1607(): Int = 1609 + def foo1608(): Int = 1610 + def foo1609(): Int = 1611 + def foo1610(): Int = 1612 + def foo1611(): Int = 1613 + def foo1612(): Int = 1614 + def foo1613(): Int = 1615 + def foo1614(): Int = 1616 + def foo1615(): Int = 1617 + def foo1616(): Int = 1618 + def foo1617(): Int = 1619 + def foo1618(): Int = 1620 + def foo1619(): Int = 1621 + def foo1620(): Int = 1622 + def foo1621(): Int = 1623 + def foo1622(): Int = 1624 + def foo1623(): Int = 1625 + def foo1624(): Int = 1626 + def foo1625(): Int = 1627 + def foo1626(): Int = 1628 + def foo1627(): Int = 1629 + def foo1628(): Int = 1630 + def foo1629(): Int = 1631 + def foo1630(): Int = 1632 + def foo1631(): Int = 1633 + def foo1632(): Int = 1634 + def foo1633(): Int = 1635 + def foo1634(): Int = 1636 + def foo1635(): Int = 1637 + def foo1636(): Int = 1638 + def foo1637(): Int = 1639 + def foo1638(): Int = 1640 + def foo1639(): Int = 1641 + def foo1640(): Int = 1642 + def foo1641(): Int = 1643 + def foo1642(): Int = 1644 + def foo1643(): Int = 1645 + def foo1644(): Int = 1646 + def foo1645(): Int = 1647 + def foo1646(): Int = 1648 + def foo1647(): Int = 1649 + def foo1648(): Int = 1650 + def foo1649(): Int = 1651 + def foo1650(): Int = 1652 + def foo1651(): Int = 1653 + def foo1652(): Int = 1654 + def foo1653(): Int = 1655 + def foo1654(): Int = 1656 + def foo1655(): Int = 1657 + def foo1656(): Int = 1658 + def foo1657(): Int = 1659 + def foo1658(): Int = 1660 + def foo1659(): Int = 1661 + def foo1660(): Int = 1662 + def foo1661(): Int = 1663 + def foo1662(): Int = 1664 + def foo1663(): Int = 1665 + def foo1664(): Int = 1666 + def foo1665(): Int = 1667 + def foo1666(): Int = 1668 + def foo1667(): Int = 1669 + def foo1668(): Int = 1670 + def foo1669(): Int = 1671 + def foo1670(): Int = 1672 + def foo1671(): Int = 1673 + def foo1672(): Int = 1674 + def foo1673(): Int = 1675 + def foo1674(): Int = 1676 + def foo1675(): Int = 1677 + def foo1676(): Int = 1678 + def foo1677(): Int = 1679 + def foo1678(): Int = 1680 + def foo1679(): Int = 1681 + def foo1680(): Int = 1682 + def foo1681(): Int = 1683 + def foo1682(): Int = 1684 + def foo1683(): Int = 1685 + def foo1684(): Int = 1686 + def foo1685(): Int = 1687 + def foo1686(): Int = 1688 + def foo1687(): Int = 1689 + def foo1688(): Int = 1690 + def foo1689(): Int = 1691 + def foo1690(): Int = 1692 + def foo1691(): Int = 1693 + def foo1692(): Int = 1694 + def foo1693(): Int = 1695 + def foo1694(): Int = 1696 + def foo1695(): Int = 1697 + def foo1696(): Int = 1698 + def foo1697(): Int = 1699 + def foo1698(): Int = 1700 + def foo1699(): Int = 1701 + def foo1700(): Int = 1702 + def foo1701(): Int = 1703 + def foo1702(): Int = 1704 + def foo1703(): Int = 1705 + def foo1704(): Int = 1706 + def foo1705(): Int = 1707 + def foo1706(): Int = 1708 + def foo1707(): Int = 1709 + def foo1708(): Int = 1710 + def foo1709(): Int = 1711 + def foo1710(): Int = 1712 + def foo1711(): Int = 1713 + def foo1712(): Int = 1714 + def foo1713(): Int = 1715 + def foo1714(): Int = 1716 + def foo1715(): Int = 1717 + def foo1716(): Int = 1718 + def foo1717(): Int = 1719 + def foo1718(): Int = 1720 + def foo1719(): Int = 1721 + def foo1720(): Int = 1722 + def foo1721(): Int = 1723 + def foo1722(): Int = 1724 + def foo1723(): Int = 1725 + def foo1724(): Int = 1726 + def foo1725(): Int = 1727 + def foo1726(): Int = 1728 + def foo1727(): Int = 1729 + def foo1728(): Int = 1730 + def foo1729(): Int = 1731 + def foo1730(): Int = 1732 + def foo1731(): Int = 1733 + def foo1732(): Int = 1734 + def foo1733(): Int = 1735 + def foo1734(): Int = 1736 + def foo1735(): Int = 1737 + def foo1736(): Int = 1738 + def foo1737(): Int = 1739 + def foo1738(): Int = 1740 + def foo1739(): Int = 1741 + def foo1740(): Int = 1742 + def foo1741(): Int = 1743 + def foo1742(): Int = 1744 + def foo1743(): Int = 1745 + def foo1744(): Int = 1746 + def foo1745(): Int = 1747 + def foo1746(): Int = 1748 + def foo1747(): Int = 1749 + def foo1748(): Int = 1750 + def foo1749(): Int = 1751 + def foo1750(): Int = 1752 + def foo1751(): Int = 1753 + def foo1752(): Int = 1754 + def foo1753(): Int = 1755 + def foo1754(): Int = 1756 + def foo1755(): Int = 1757 + def foo1756(): Int = 1758 + def foo1757(): Int = 1759 + def foo1758(): Int = 1760 + def foo1759(): Int = 1761 + def foo1760(): Int = 1762 + def foo1761(): Int = 1763 + def foo1762(): Int = 1764 + def foo1763(): Int = 1765 + def foo1764(): Int = 1766 + def foo1765(): Int = 1767 + def foo1766(): Int = 1768 + def foo1767(): Int = 1769 + def foo1768(): Int = 1770 + def foo1769(): Int = 1771 + def foo1770(): Int = 1772 + def foo1771(): Int = 1773 + def foo1772(): Int = 1774 + def foo1773(): Int = 1775 + def foo1774(): Int = 1776 + def foo1775(): Int = 1777 + def foo1776(): Int = 1778 + def foo1777(): Int = 1779 + def foo1778(): Int = 1780 + def foo1779(): Int = 1781 + def foo1780(): Int = 1782 + def foo1781(): Int = 1783 + def foo1782(): Int = 1784 + def foo1783(): Int = 1785 + def foo1784(): Int = 1786 + def foo1785(): Int = 1787 + def foo1786(): Int = 1788 + def foo1787(): Int = 1789 + def foo1788(): Int = 1790 + def foo1789(): Int = 1791 + def foo1790(): Int = 1792 + def foo1791(): Int = 1793 + def foo1792(): Int = 1794 + def foo1793(): Int = 1795 + def foo1794(): Int = 1796 + def foo1795(): Int = 1797 + def foo1796(): Int = 1798 + def foo1797(): Int = 1799 + def foo1798(): Int = 1800 + def foo1799(): Int = 1801 + def foo1800(): Int = 1802 + def foo1801(): Int = 1803 + def foo1802(): Int = 1804 + def foo1803(): Int = 1805 + def foo1804(): Int = 1806 + def foo1805(): Int = 1807 + def foo1806(): Int = 1808 + def foo1807(): Int = 1809 + def foo1808(): Int = 1810 + def foo1809(): Int = 1811 + def foo1810(): Int = 1812 + def foo1811(): Int = 1813 + def foo1812(): Int = 1814 + def foo1813(): Int = 1815 + def foo1814(): Int = 1816 + def foo1815(): Int = 1817 + def foo1816(): Int = 1818 + def foo1817(): Int = 1819 + def foo1818(): Int = 1820 + def foo1819(): Int = 1821 + def foo1820(): Int = 1822 + def foo1821(): Int = 1823 + def foo1822(): Int = 1824 + def foo1823(): Int = 1825 + def foo1824(): Int = 1826 + def foo1825(): Int = 1827 + def foo1826(): Int = 1828 + def foo1827(): Int = 1829 + def foo1828(): Int = 1830 + def foo1829(): Int = 1831 + def foo1830(): Int = 1832 + def foo1831(): Int = 1833 + def foo1832(): Int = 1834 + def foo1833(): Int = 1835 + def foo1834(): Int = 1836 + def foo1835(): Int = 1837 + def foo1836(): Int = 1838 + def foo1837(): Int = 1839 + def foo1838(): Int = 1840 + def foo1839(): Int = 1841 + def foo1840(): Int = 1842 + def foo1841(): Int = 1843 + def foo1842(): Int = 1844 + def foo1843(): Int = 1845 + def foo1844(): Int = 1846 + def foo1845(): Int = 1847 + def foo1846(): Int = 1848 + def foo1847(): Int = 1849 + def foo1848(): Int = 1850 + def foo1849(): Int = 1851 + def foo1850(): Int = 1852 + def foo1851(): Int = 1853 + def foo1852(): Int = 1854 + def foo1853(): Int = 1855 + def foo1854(): Int = 1856 + def foo1855(): Int = 1857 + def foo1856(): Int = 1858 + def foo1857(): Int = 1859 + def foo1858(): Int = 1860 + def foo1859(): Int = 1861 + def foo1860(): Int = 1862 + def foo1861(): Int = 1863 + def foo1862(): Int = 1864 + def foo1863(): Int = 1865 + def foo1864(): Int = 1866 + def foo1865(): Int = 1867 + def foo1866(): Int = 1868 + def foo1867(): Int = 1869 + def foo1868(): Int = 1870 + def foo1869(): Int = 1871 + def foo1870(): Int = 1872 + def foo1871(): Int = 1873 + def foo1872(): Int = 1874 + def foo1873(): Int = 1875 + def foo1874(): Int = 1876 + def foo1875(): Int = 1877 + def foo1876(): Int = 1878 + def foo1877(): Int = 1879 + def foo1878(): Int = 1880 + def foo1879(): Int = 1881 + def foo1880(): Int = 1882 + def foo1881(): Int = 1883 + def foo1882(): Int = 1884 + def foo1883(): Int = 1885 + def foo1884(): Int = 1886 + def foo1885(): Int = 1887 + def foo1886(): Int = 1888 + def foo1887(): Int = 1889 + def foo1888(): Int = 1890 + def foo1889(): Int = 1891 + def foo1890(): Int = 1892 + def foo1891(): Int = 1893 + def foo1892(): Int = 1894 + def foo1893(): Int = 1895 + def foo1894(): Int = 1896 + def foo1895(): Int = 1897 + def foo1896(): Int = 1898 + def foo1897(): Int = 1899 + def foo1898(): Int = 1900 + def foo1899(): Int = 1901 + def foo1900(): Int = 1902 + def foo1901(): Int = 1903 + def foo1902(): Int = 1904 + def foo1903(): Int = 1905 + def foo1904(): Int = 1906 + def foo1905(): Int = 1907 + def foo1906(): Int = 1908 + def foo1907(): Int = 1909 + def foo1908(): Int = 1910 + def foo1909(): Int = 1911 + def foo1910(): Int = 1912 + def foo1911(): Int = 1913 + def foo1912(): Int = 1914 + def foo1913(): Int = 1915 + def foo1914(): Int = 1916 + def foo1915(): Int = 1917 + def foo1916(): Int = 1918 + def foo1917(): Int = 1919 + def foo1918(): Int = 1920 + def foo1919(): Int = 1921 + def foo1920(): Int = 1922 + def foo1921(): Int = 1923 + def foo1922(): Int = 1924 + def foo1923(): Int = 1925 + def foo1924(): Int = 1926 + def foo1925(): Int = 1927 + def foo1926(): Int = 1928 + def foo1927(): Int = 1929 + def foo1928(): Int = 1930 + def foo1929(): Int = 1931 + def foo1930(): Int = 1932 + def foo1931(): Int = 1933 + def foo1932(): Int = 1934 + def foo1933(): Int = 1935 + def foo1934(): Int = 1936 + def foo1935(): Int = 1937 + def foo1936(): Int = 1938 + def foo1937(): Int = 1939 + def foo1938(): Int = 1940 + def foo1939(): Int = 1941 + def foo1940(): Int = 1942 + def foo1941(): Int = 1943 + def foo1942(): Int = 1944 + def foo1943(): Int = 1945 + def foo1944(): Int = 1946 + def foo1945(): Int = 1947 + def foo1946(): Int = 1948 + def foo1947(): Int = 1949 + def foo1948(): Int = 1950 + def foo1949(): Int = 1951 + def foo1950(): Int = 1952 + def foo1951(): Int = 1953 + def foo1952(): Int = 1954 + def foo1953(): Int = 1955 + def foo1954(): Int = 1956 + def foo1955(): Int = 1957 + def foo1956(): Int = 1958 + def foo1957(): Int = 1959 + def foo1958(): Int = 1960 + def foo1959(): Int = 1961 + def foo1960(): Int = 1962 + def foo1961(): Int = 1963 + def foo1962(): Int = 1964 + def foo1963(): Int = 1965 + def foo1964(): Int = 1966 + def foo1965(): Int = 1967 + def foo1966(): Int = 1968 + def foo1967(): Int = 1969 + def foo1968(): Int = 1970 + def foo1969(): Int = 1971 + def foo1970(): Int = 1972 + def foo1971(): Int = 1973 + def foo1972(): Int = 1974 + def foo1973(): Int = 1975 + def foo1974(): Int = 1976 + def foo1975(): Int = 1977 + def foo1976(): Int = 1978 + def foo1977(): Int = 1979 + def foo1978(): Int = 1980 + def foo1979(): Int = 1981 + def foo1980(): Int = 1982 + def foo1981(): Int = 1983 + def foo1982(): Int = 1984 + def foo1983(): Int = 1985 + def foo1984(): Int = 1986 + def foo1985(): Int = 1987 + def foo1986(): Int = 1988 + def foo1987(): Int = 1989 + def foo1988(): Int = 1990 + def foo1989(): Int = 1991 + def foo1990(): Int = 1992 + def foo1991(): Int = 1993 + def foo1992(): Int = 1994 + def foo1993(): Int = 1995 + def foo1994(): Int = 1996 + def foo1995(): Int = 1997 + def foo1996(): Int = 1998 + def foo1997(): Int = 1999 + def foo1998(): Int = 2000 + def foo1999(): Int = 2001 + def foo2000(): Int = 2002 + def foo2001(): Int = 2003 + def foo2002(): Int = 2004 + def foo2003(): Int = 2005 + def foo2004(): Int = 2006 + def foo2005(): Int = 2007 + def foo2006(): Int = 2008 + def foo2007(): Int = 2009 + def foo2008(): Int = 2010 + def foo2009(): Int = 2011 + def foo2010(): Int = 2012 + def foo2011(): Int = 2013 + def foo2012(): Int = 2014 + def foo2013(): Int = 2015 + def foo2014(): Int = 2016 + def foo2015(): Int = 2017 + def foo2016(): Int = 2018 + def foo2017(): Int = 2019 + def foo2018(): Int = 2020 + def foo2019(): Int = 2021 + def foo2020(): Int = 2022 + def foo2021(): Int = 2023 + def foo2022(): Int = 2024 + def foo2023(): Int = 2025 + def foo2024(): Int = 2026 + def foo2025(): Int = 2027 + def foo2026(): Int = 2028 + def foo2027(): Int = 2029 + def foo2028(): Int = 2030 + def foo2029(): Int = 2031 + def foo2030(): Int = 2032 + def foo2031(): Int = 2033 + def foo2032(): Int = 2034 + def foo2033(): Int = 2035 + def foo2034(): Int = 2036 + def foo2035(): Int = 2037 + def foo2036(): Int = 2038 + def foo2037(): Int = 2039 + def foo2038(): Int = 2040 + def foo2039(): Int = 2041 + def foo2040(): Int = 2042 + def foo2041(): Int = 2043 + def foo2042(): Int = 2044 + def foo2043(): Int = 2045 + def foo2044(): Int = 2046 + def foo2045(): Int = 2047 + def foo2046(): Int = 2048 + def foo2047(): Int = 2049 + def foo2048(): Int = 2050 + def foo2049(): Int = 2051 + def foo2050(): Int = 2052 + def foo2051(): Int = 2053 + def foo2052(): Int = 2054 + def foo2053(): Int = 2055 + def foo2054(): Int = 2056 + def foo2055(): Int = 2057 + def foo2056(): Int = 2058 + def foo2057(): Int = 2059 + def foo2058(): Int = 2060 + def foo2059(): Int = 2061 + def foo2060(): Int = 2062 + def foo2061(): Int = 2063 + def foo2062(): Int = 2064 + def foo2063(): Int = 2065 + def foo2064(): Int = 2066 + def foo2065(): Int = 2067 + def foo2066(): Int = 2068 + def foo2067(): Int = 2069 + def foo2068(): Int = 2070 + def foo2069(): Int = 2071 + def foo2070(): Int = 2072 + def foo2071(): Int = 2073 + def foo2072(): Int = 2074 + def foo2073(): Int = 2075 + def foo2074(): Int = 2076 + def foo2075(): Int = 2077 + def foo2076(): Int = 2078 + def foo2077(): Int = 2079 + def foo2078(): Int = 2080 + def foo2079(): Int = 2081 + def foo2080(): Int = 2082 + def foo2081(): Int = 2083 + def foo2082(): Int = 2084 + def foo2083(): Int = 2085 + def foo2084(): Int = 2086 + def foo2085(): Int = 2087 + def foo2086(): Int = 2088 + def foo2087(): Int = 2089 + def foo2088(): Int = 2090 + def foo2089(): Int = 2091 + def foo2090(): Int = 2092 + def foo2091(): Int = 2093 + def foo2092(): Int = 2094 + def foo2093(): Int = 2095 + def foo2094(): Int = 2096 + def foo2095(): Int = 2097 + def foo2096(): Int = 2098 + def foo2097(): Int = 2099 + def foo2098(): Int = 2100 + def foo2099(): Int = 2101 + def foo2100(): Int = 2102 + def foo2101(): Int = 2103 + def foo2102(): Int = 2104 + def foo2103(): Int = 2105 + def foo2104(): Int = 2106 + def foo2105(): Int = 2107 + def foo2106(): Int = 2108 + def foo2107(): Int = 2109 + def foo2108(): Int = 2110 + def foo2109(): Int = 2111 + def foo2110(): Int = 2112 + def foo2111(): Int = 2113 + def foo2112(): Int = 2114 + def foo2113(): Int = 2115 + def foo2114(): Int = 2116 + def foo2115(): Int = 2117 + def foo2116(): Int = 2118 + def foo2117(): Int = 2119 + def foo2118(): Int = 2120 + def foo2119(): Int = 2121 + def foo2120(): Int = 2122 + def foo2121(): Int = 2123 + def foo2122(): Int = 2124 + def foo2123(): Int = 2125 + def foo2124(): Int = 2126 + def foo2125(): Int = 2127 + def foo2126(): Int = 2128 + def foo2127(): Int = 2129 + def foo2128(): Int = 2130 + def foo2129(): Int = 2131 + def foo2130(): Int = 2132 + def foo2131(): Int = 2133 + def foo2132(): Int = 2134 + def foo2133(): Int = 2135 + def foo2134(): Int = 2136 + def foo2135(): Int = 2137 + def foo2136(): Int = 2138 + def foo2137(): Int = 2139 + def foo2138(): Int = 2140 + def foo2139(): Int = 2141 + def foo2140(): Int = 2142 + def foo2141(): Int = 2143 + def foo2142(): Int = 2144 + def foo2143(): Int = 2145 + def foo2144(): Int = 2146 + def foo2145(): Int = 2147 + def foo2146(): Int = 2148 + def foo2147(): Int = 2149 + def foo2148(): Int = 2150 + def foo2149(): Int = 2151 + def foo2150(): Int = 2152 + def foo2151(): Int = 2153 + def foo2152(): Int = 2154 + def foo2153(): Int = 2155 + def foo2154(): Int = 2156 + def foo2155(): Int = 2157 + def foo2156(): Int = 2158 + def foo2157(): Int = 2159 + def foo2158(): Int = 2160 + def foo2159(): Int = 2161 + def foo2160(): Int = 2162 + def foo2161(): Int = 2163 + def foo2162(): Int = 2164 + def foo2163(): Int = 2165 + def foo2164(): Int = 2166 + def foo2165(): Int = 2167 + def foo2166(): Int = 2168 + def foo2167(): Int = 2169 + def foo2168(): Int = 2170 + def foo2169(): Int = 2171 + def foo2170(): Int = 2172 + def foo2171(): Int = 2173 + def foo2172(): Int = 2174 + def foo2173(): Int = 2175 + def foo2174(): Int = 2176 + def foo2175(): Int = 2177 + def foo2176(): Int = 2178 + def foo2177(): Int = 2179 + def foo2178(): Int = 2180 + def foo2179(): Int = 2181 + def foo2180(): Int = 2182 + def foo2181(): Int = 2183 + def foo2182(): Int = 2184 + def foo2183(): Int = 2185 + def foo2184(): Int = 2186 + def foo2185(): Int = 2187 + def foo2186(): Int = 2188 + def foo2187(): Int = 2189 + def foo2188(): Int = 2190 + def foo2189(): Int = 2191 + def foo2190(): Int = 2192 + def foo2191(): Int = 2193 + def foo2192(): Int = 2194 + def foo2193(): Int = 2195 + def foo2194(): Int = 2196 + def foo2195(): Int = 2197 + def foo2196(): Int = 2198 + def foo2197(): Int = 2199 + def foo2198(): Int = 2200 + def foo2199(): Int = 2201 + def foo2200(): Int = 2202 + def foo2201(): Int = 2203 + def foo2202(): Int = 2204 + def foo2203(): Int = 2205 + def foo2204(): Int = 2206 + def foo2205(): Int = 2207 + def foo2206(): Int = 2208 + def foo2207(): Int = 2209 + def foo2208(): Int = 2210 + def foo2209(): Int = 2211 + def foo2210(): Int = 2212 + def foo2211(): Int = 2213 + def foo2212(): Int = 2214 + def foo2213(): Int = 2215 + def foo2214(): Int = 2216 + def foo2215(): Int = 2217 + def foo2216(): Int = 2218 + def foo2217(): Int = 2219 + def foo2218(): Int = 2220 + def foo2219(): Int = 2221 + def foo2220(): Int = 2222 + def foo2221(): Int = 2223 + def foo2222(): Int = 2224 + def foo2223(): Int = 2225 + def foo2224(): Int = 2226 + def foo2225(): Int = 2227 + def foo2226(): Int = 2228 + def foo2227(): Int = 2229 + def foo2228(): Int = 2230 + def foo2229(): Int = 2231 + def foo2230(): Int = 2232 + def foo2231(): Int = 2233 + def foo2232(): Int = 2234 + def foo2233(): Int = 2235 + def foo2234(): Int = 2236 + def foo2235(): Int = 2237 + def foo2236(): Int = 2238 + def foo2237(): Int = 2239 + def foo2238(): Int = 2240 + def foo2239(): Int = 2241 + def foo2240(): Int = 2242 + def foo2241(): Int = 2243 + def foo2242(): Int = 2244 + def foo2243(): Int = 2245 + def foo2244(): Int = 2246 + def foo2245(): Int = 2247 + def foo2246(): Int = 2248 + def foo2247(): Int = 2249 + def foo2248(): Int = 2250 + def foo2249(): Int = 2251 + def foo2250(): Int = 2252 + def foo2251(): Int = 2253 + def foo2252(): Int = 2254 + def foo2253(): Int = 2255 + def foo2254(): Int = 2256 + def foo2255(): Int = 2257 + def foo2256(): Int = 2258 + def foo2257(): Int = 2259 + def foo2258(): Int = 2260 + def foo2259(): Int = 2261 + def foo2260(): Int = 2262 + def foo2261(): Int = 2263 + def foo2262(): Int = 2264 + def foo2263(): Int = 2265 + def foo2264(): Int = 2266 + def foo2265(): Int = 2267 + def foo2266(): Int = 2268 + def foo2267(): Int = 2269 + def foo2268(): Int = 2270 + def foo2269(): Int = 2271 + def foo2270(): Int = 2272 + def foo2271(): Int = 2273 + def foo2272(): Int = 2274 + def foo2273(): Int = 2275 + def foo2274(): Int = 2276 + def foo2275(): Int = 2277 + def foo2276(): Int = 2278 + def foo2277(): Int = 2279 + def foo2278(): Int = 2280 + def foo2279(): Int = 2281 + def foo2280(): Int = 2282 + def foo2281(): Int = 2283 + def foo2282(): Int = 2284 + def foo2283(): Int = 2285 + def foo2284(): Int = 2286 + def foo2285(): Int = 2287 + def foo2286(): Int = 2288 + def foo2287(): Int = 2289 + def foo2288(): Int = 2290 + def foo2289(): Int = 2291 + def foo2290(): Int = 2292 + def foo2291(): Int = 2293 + def foo2292(): Int = 2294 + def foo2293(): Int = 2295 + def foo2294(): Int = 2296 + def foo2295(): Int = 2297 + def foo2296(): Int = 2298 + def foo2297(): Int = 2299 + def foo2298(): Int = 2300 + def foo2299(): Int = 2301 + def foo2300(): Int = 2302 + def foo2301(): Int = 2303 + def foo2302(): Int = 2304 + def foo2303(): Int = 2305 + def foo2304(): Int = 2306 + def foo2305(): Int = 2307 + def foo2306(): Int = 2308 + def foo2307(): Int = 2309 + def foo2308(): Int = 2310 + def foo2309(): Int = 2311 + def foo2310(): Int = 2312 + def foo2311(): Int = 2313 + def foo2312(): Int = 2314 + def foo2313(): Int = 2315 + def foo2314(): Int = 2316 + def foo2315(): Int = 2317 + def foo2316(): Int = 2318 + def foo2317(): Int = 2319 + def foo2318(): Int = 2320 + def foo2319(): Int = 2321 + def foo2320(): Int = 2322 + def foo2321(): Int = 2323 + def foo2322(): Int = 2324 + def foo2323(): Int = 2325 + def foo2324(): Int = 2326 + def foo2325(): Int = 2327 + def foo2326(): Int = 2328 + def foo2327(): Int = 2329 + def foo2328(): Int = 2330 + def foo2329(): Int = 2331 + def foo2330(): Int = 2332 + def foo2331(): Int = 2333 + def foo2332(): Int = 2334 + def foo2333(): Int = 2335 + def foo2334(): Int = 2336 + def foo2335(): Int = 2337 + def foo2336(): Int = 2338 + def foo2337(): Int = 2339 + def foo2338(): Int = 2340 + def foo2339(): Int = 2341 + def foo2340(): Int = 2342 + def foo2341(): Int = 2343 + def foo2342(): Int = 2344 + def foo2343(): Int = 2345 + def foo2344(): Int = 2346 + def foo2345(): Int = 2347 + def foo2346(): Int = 2348 + def foo2347(): Int = 2349 + def foo2348(): Int = 2350 + def foo2349(): Int = 2351 + def foo2350(): Int = 2352 + def foo2351(): Int = 2353 + def foo2352(): Int = 2354 + def foo2353(): Int = 2355 + def foo2354(): Int = 2356 + def foo2355(): Int = 2357 + def foo2356(): Int = 2358 + def foo2357(): Int = 2359 + def foo2358(): Int = 2360 + def foo2359(): Int = 2361 + def foo2360(): Int = 2362 + def foo2361(): Int = 2363 + def foo2362(): Int = 2364 + def foo2363(): Int = 2365 + def foo2364(): Int = 2366 + def foo2365(): Int = 2367 + def foo2366(): Int = 2368 + def foo2367(): Int = 2369 + def foo2368(): Int = 2370 + def foo2369(): Int = 2371 + def foo2370(): Int = 2372 + def foo2371(): Int = 2373 + def foo2372(): Int = 2374 + def foo2373(): Int = 2375 + def foo2374(): Int = 2376 + def foo2375(): Int = 2377 + def foo2376(): Int = 2378 + def foo2377(): Int = 2379 + def foo2378(): Int = 2380 + def foo2379(): Int = 2381 + def foo2380(): Int = 2382 + def foo2381(): Int = 2383 + def foo2382(): Int = 2384 + def foo2383(): Int = 2385 + def foo2384(): Int = 2386 + def foo2385(): Int = 2387 + def foo2386(): Int = 2388 + def foo2387(): Int = 2389 + def foo2388(): Int = 2390 + def foo2389(): Int = 2391 + def foo2390(): Int = 2392 + def foo2391(): Int = 2393 + def foo2392(): Int = 2394 + def foo2393(): Int = 2395 + def foo2394(): Int = 2396 + def foo2395(): Int = 2397 + def foo2396(): Int = 2398 + def foo2397(): Int = 2399 + def foo2398(): Int = 2400 + def foo2399(): Int = 2401 + def foo2400(): Int = 2402 + def foo2401(): Int = 2403 + def foo2402(): Int = 2404 + def foo2403(): Int = 2405 + def foo2404(): Int = 2406 + def foo2405(): Int = 2407 + def foo2406(): Int = 2408 + def foo2407(): Int = 2409 + def foo2408(): Int = 2410 + def foo2409(): Int = 2411 + def foo2410(): Int = 2412 + def foo2411(): Int = 2413 + def foo2412(): Int = 2414 + def foo2413(): Int = 2415 + def foo2414(): Int = 2416 + def foo2415(): Int = 2417 + def foo2416(): Int = 2418 + def foo2417(): Int = 2419 + def foo2418(): Int = 2420 + def foo2419(): Int = 2421 + def foo2420(): Int = 2422 + def foo2421(): Int = 2423 + def foo2422(): Int = 2424 + def foo2423(): Int = 2425 + def foo2424(): Int = 2426 + def foo2425(): Int = 2427 + def foo2426(): Int = 2428 + def foo2427(): Int = 2429 + def foo2428(): Int = 2430 + def foo2429(): Int = 2431 + def foo2430(): Int = 2432 + def foo2431(): Int = 2433 + def foo2432(): Int = 2434 + def foo2433(): Int = 2435 + def foo2434(): Int = 2436 + def foo2435(): Int = 2437 + def foo2436(): Int = 2438 + def foo2437(): Int = 2439 + def foo2438(): Int = 2440 + def foo2439(): Int = 2441 + def foo2440(): Int = 2442 + def foo2441(): Int = 2443 + def foo2442(): Int = 2444 + def foo2443(): Int = 2445 + def foo2444(): Int = 2446 + def foo2445(): Int = 2447 + def foo2446(): Int = 2448 + def foo2447(): Int = 2449 + def foo2448(): Int = 2450 + def foo2449(): Int = 2451 + def foo2450(): Int = 2452 + def foo2451(): Int = 2453 + def foo2452(): Int = 2454 + def foo2453(): Int = 2455 + def foo2454(): Int = 2456 + def foo2455(): Int = 2457 + def foo2456(): Int = 2458 + def foo2457(): Int = 2459 + def foo2458(): Int = 2460 + def foo2459(): Int = 2461 + def foo2460(): Int = 2462 + def foo2461(): Int = 2463 + def foo2462(): Int = 2464 + def foo2463(): Int = 2465 + def foo2464(): Int = 2466 + def foo2465(): Int = 2467 + def foo2466(): Int = 2468 + def foo2467(): Int = 2469 + def foo2468(): Int = 2470 + def foo2469(): Int = 2471 + def foo2470(): Int = 2472 + def foo2471(): Int = 2473 + def foo2472(): Int = 2474 + def foo2473(): Int = 2475 + def foo2474(): Int = 2476 + def foo2475(): Int = 2477 + def foo2476(): Int = 2478 + def foo2477(): Int = 2479 + def foo2478(): Int = 2480 + def foo2479(): Int = 2481 + def foo2480(): Int = 2482 + def foo2481(): Int = 2483 + def foo2482(): Int = 2484 + def foo2483(): Int = 2485 + def foo2484(): Int = 2486 + def foo2485(): Int = 2487 + def foo2486(): Int = 2488 + def foo2487(): Int = 2489 + def foo2488(): Int = 2490 + def foo2489(): Int = 2491 + def foo2490(): Int = 2492 + def foo2491(): Int = 2493 + def foo2492(): Int = 2494 + def foo2493(): Int = 2495 + def foo2494(): Int = 2496 + def foo2495(): Int = 2497 + def foo2496(): Int = 2498 + def foo2497(): Int = 2499 + def foo2498(): Int = 2500 + def foo2499(): Int = 2501 + def foo2500(): Int = 2502 + def foo2501(): Int = 2503 + def foo2502(): Int = 2504 + def foo2503(): Int = 2505 + def foo2504(): Int = 2506 + def foo2505(): Int = 2507 + def foo2506(): Int = 2508 + def foo2507(): Int = 2509 + def foo2508(): Int = 2510 + def foo2509(): Int = 2511 + def foo2510(): Int = 2512 + def foo2511(): Int = 2513 + def foo2512(): Int = 2514 + def foo2513(): Int = 2515 + def foo2514(): Int = 2516 + def foo2515(): Int = 2517 + def foo2516(): Int = 2518 + def foo2517(): Int = 2519 + def foo2518(): Int = 2520 + def foo2519(): Int = 2521 + def foo2520(): Int = 2522 + def foo2521(): Int = 2523 + def foo2522(): Int = 2524 + def foo2523(): Int = 2525 + def foo2524(): Int = 2526 + def foo2525(): Int = 2527 + def foo2526(): Int = 2528 + def foo2527(): Int = 2529 + def foo2528(): Int = 2530 + def foo2529(): Int = 2531 + def foo2530(): Int = 2532 + def foo2531(): Int = 2533 + def foo2532(): Int = 2534 + def foo2533(): Int = 2535 + def foo2534(): Int = 2536 + def foo2535(): Int = 2537 + def foo2536(): Int = 2538 + def foo2537(): Int = 2539 + def foo2538(): Int = 2540 + def foo2539(): Int = 2541 + def foo2540(): Int = 2542 + def foo2541(): Int = 2543 + def foo2542(): Int = 2544 + def foo2543(): Int = 2545 + def foo2544(): Int = 2546 + def foo2545(): Int = 2547 + def foo2546(): Int = 2548 + def foo2547(): Int = 2549 + def foo2548(): Int = 2550 + def foo2549(): Int = 2551 + def foo2550(): Int = 2552 + def foo2551(): Int = 2553 + def foo2552(): Int = 2554 + def foo2553(): Int = 2555 + def foo2554(): Int = 2556 + def foo2555(): Int = 2557 + def foo2556(): Int = 2558 + def foo2557(): Int = 2559 + def foo2558(): Int = 2560 + def foo2559(): Int = 2561 + def foo2560(): Int = 2562 + def foo2561(): Int = 2563 + def foo2562(): Int = 2564 + def foo2563(): Int = 2565 + def foo2564(): Int = 2566 + def foo2565(): Int = 2567 + def foo2566(): Int = 2568 + def foo2567(): Int = 2569 + def foo2568(): Int = 2570 + def foo2569(): Int = 2571 + def foo2570(): Int = 2572 + def foo2571(): Int = 2573 + def foo2572(): Int = 2574 + def foo2573(): Int = 2575 + def foo2574(): Int = 2576 + def foo2575(): Int = 2577 + def foo2576(): Int = 2578 + def foo2577(): Int = 2579 + def foo2578(): Int = 2580 + def foo2579(): Int = 2581 + def foo2580(): Int = 2582 + def foo2581(): Int = 2583 + def foo2582(): Int = 2584 + def foo2583(): Int = 2585 + def foo2584(): Int = 2586 + def foo2585(): Int = 2587 + def foo2586(): Int = 2588 + def foo2587(): Int = 2589 + def foo2588(): Int = 2590 + def foo2589(): Int = 2591 + def foo2590(): Int = 2592 + def foo2591(): Int = 2593 + def foo2592(): Int = 2594 + def foo2593(): Int = 2595 + def foo2594(): Int = 2596 + def foo2595(): Int = 2597 + def foo2596(): Int = 2598 + def foo2597(): Int = 2599 + def foo2598(): Int = 2600 + def foo2599(): Int = 2601 + def foo2600(): Int = 2602 + def foo2601(): Int = 2603 + def foo2602(): Int = 2604 + def foo2603(): Int = 2605 + def foo2604(): Int = 2606 + def foo2605(): Int = 2607 + def foo2606(): Int = 2608 + def foo2607(): Int = 2609 + def foo2608(): Int = 2610 + def foo2609(): Int = 2611 + def foo2610(): Int = 2612 + def foo2611(): Int = 2613 + def foo2612(): Int = 2614 + def foo2613(): Int = 2615 + def foo2614(): Int = 2616 + def foo2615(): Int = 2617 + def foo2616(): Int = 2618 + def foo2617(): Int = 2619 + def foo2618(): Int = 2620 + def foo2619(): Int = 2621 + def foo2620(): Int = 2622 + def foo2621(): Int = 2623 + def foo2622(): Int = 2624 + def foo2623(): Int = 2625 + def foo2624(): Int = 2626 + def foo2625(): Int = 2627 + def foo2626(): Int = 2628 + def foo2627(): Int = 2629 + def foo2628(): Int = 2630 + def foo2629(): Int = 2631 + def foo2630(): Int = 2632 + def foo2631(): Int = 2633 + def foo2632(): Int = 2634 + def foo2633(): Int = 2635 + def foo2634(): Int = 2636 + def foo2635(): Int = 2637 + def foo2636(): Int = 2638 + def foo2637(): Int = 2639 + def foo2638(): Int = 2640 + def foo2639(): Int = 2641 + def foo2640(): Int = 2642 + def foo2641(): Int = 2643 + def foo2642(): Int = 2644 + def foo2643(): Int = 2645 + def foo2644(): Int = 2646 + def foo2645(): Int = 2647 + def foo2646(): Int = 2648 + def foo2647(): Int = 2649 + def foo2648(): Int = 2650 + def foo2649(): Int = 2651 + def foo2650(): Int = 2652 + def foo2651(): Int = 2653 + def foo2652(): Int = 2654 + def foo2653(): Int = 2655 + def foo2654(): Int = 2656 + def foo2655(): Int = 2657 + def foo2656(): Int = 2658 + def foo2657(): Int = 2659 + def foo2658(): Int = 2660 + def foo2659(): Int = 2661 + def foo2660(): Int = 2662 + def foo2661(): Int = 2663 + def foo2662(): Int = 2664 + def foo2663(): Int = 2665 + def foo2664(): Int = 2666 + def foo2665(): Int = 2667 + def foo2666(): Int = 2668 + def foo2667(): Int = 2669 + def foo2668(): Int = 2670 + def foo2669(): Int = 2671 + def foo2670(): Int = 2672 + def foo2671(): Int = 2673 + def foo2672(): Int = 2674 + def foo2673(): Int = 2675 + def foo2674(): Int = 2676 + def foo2675(): Int = 2677 + def foo2676(): Int = 2678 + def foo2677(): Int = 2679 + def foo2678(): Int = 2680 + def foo2679(): Int = 2681 + def foo2680(): Int = 2682 + def foo2681(): Int = 2683 + def foo2682(): Int = 2684 + def foo2683(): Int = 2685 + def foo2684(): Int = 2686 + def foo2685(): Int = 2687 + def foo2686(): Int = 2688 + def foo2687(): Int = 2689 + def foo2688(): Int = 2690 + def foo2689(): Int = 2691 + def foo2690(): Int = 2692 + def foo2691(): Int = 2693 + def foo2692(): Int = 2694 + def foo2693(): Int = 2695 + def foo2694(): Int = 2696 + def foo2695(): Int = 2697 + def foo2696(): Int = 2698 + def foo2697(): Int = 2699 + def foo2698(): Int = 2700 + def foo2699(): Int = 2701 + def foo2700(): Int = 2702 + def foo2701(): Int = 2703 + def foo2702(): Int = 2704 + def foo2703(): Int = 2705 + def foo2704(): Int = 2706 + def foo2705(): Int = 2707 + def foo2706(): Int = 2708 + def foo2707(): Int = 2709 + def foo2708(): Int = 2710 + def foo2709(): Int = 2711 + def foo2710(): Int = 2712 + def foo2711(): Int = 2713 + def foo2712(): Int = 2714 + def foo2713(): Int = 2715 + def foo2714(): Int = 2716 + def foo2715(): Int = 2717 + def foo2716(): Int = 2718 + def foo2717(): Int = 2719 + def foo2718(): Int = 2720 + def foo2719(): Int = 2721 + def foo2720(): Int = 2722 + def foo2721(): Int = 2723 + def foo2722(): Int = 2724 + def foo2723(): Int = 2725 + def foo2724(): Int = 2726 + def foo2725(): Int = 2727 + def foo2726(): Int = 2728 + def foo2727(): Int = 2729 + def foo2728(): Int = 2730 + def foo2729(): Int = 2731 + def foo2730(): Int = 2732 + def foo2731(): Int = 2733 + def foo2732(): Int = 2734 + def foo2733(): Int = 2735 + def foo2734(): Int = 2736 + def foo2735(): Int = 2737 + def foo2736(): Int = 2738 + def foo2737(): Int = 2739 + def foo2738(): Int = 2740 + def foo2739(): Int = 2741 + def foo2740(): Int = 2742 + def foo2741(): Int = 2743 + def foo2742(): Int = 2744 + def foo2743(): Int = 2745 + def foo2744(): Int = 2746 + def foo2745(): Int = 2747 + def foo2746(): Int = 2748 + def foo2747(): Int = 2749 + def foo2748(): Int = 2750 + def foo2749(): Int = 2751 + def foo2750(): Int = 2752 + def foo2751(): Int = 2753 + def foo2752(): Int = 2754 + def foo2753(): Int = 2755 + def foo2754(): Int = 2756 + def foo2755(): Int = 2757 + def foo2756(): Int = 2758 + def foo2757(): Int = 2759 + def foo2758(): Int = 2760 + def foo2759(): Int = 2761 + def foo2760(): Int = 2762 + def foo2761(): Int = 2763 + def foo2762(): Int = 2764 + def foo2763(): Int = 2765 + def foo2764(): Int = 2766 + def foo2765(): Int = 2767 + def foo2766(): Int = 2768 + def foo2767(): Int = 2769 + def foo2768(): Int = 2770 + def foo2769(): Int = 2771 + def foo2770(): Int = 2772 + def foo2771(): Int = 2773 + def foo2772(): Int = 2774 + def foo2773(): Int = 2775 + def foo2774(): Int = 2776 + def foo2775(): Int = 2777 + def foo2776(): Int = 2778 + def foo2777(): Int = 2779 + def foo2778(): Int = 2780 + def foo2779(): Int = 2781 + def foo2780(): Int = 2782 + def foo2781(): Int = 2783 + def foo2782(): Int = 2784 + def foo2783(): Int = 2785 + def foo2784(): Int = 2786 + def foo2785(): Int = 2787 + def foo2786(): Int = 2788 + def foo2787(): Int = 2789 + def foo2788(): Int = 2790 + def foo2789(): Int = 2791 + def foo2790(): Int = 2792 + def foo2791(): Int = 2793 + def foo2792(): Int = 2794 + def foo2793(): Int = 2795 + def foo2794(): Int = 2796 + def foo2795(): Int = 2797 + def foo2796(): Int = 2798 + def foo2797(): Int = 2799 + def foo2798(): Int = 2800 + def foo2799(): Int = 2801 + def foo2800(): Int = 2802 + def foo2801(): Int = 2803 + def foo2802(): Int = 2804 + def foo2803(): Int = 2805 + def foo2804(): Int = 2806 + def foo2805(): Int = 2807 + def foo2806(): Int = 2808 + def foo2807(): Int = 2809 + def foo2808(): Int = 2810 + def foo2809(): Int = 2811 + def foo2810(): Int = 2812 + def foo2811(): Int = 2813 + def foo2812(): Int = 2814 + def foo2813(): Int = 2815 + def foo2814(): Int = 2816 + def foo2815(): Int = 2817 + def foo2816(): Int = 2818 + def foo2817(): Int = 2819 + def foo2818(): Int = 2820 + def foo2819(): Int = 2821 + def foo2820(): Int = 2822 + def foo2821(): Int = 2823 + def foo2822(): Int = 2824 + def foo2823(): Int = 2825 + def foo2824(): Int = 2826 + def foo2825(): Int = 2827 + def foo2826(): Int = 2828 + def foo2827(): Int = 2829 + def foo2828(): Int = 2830 + def foo2829(): Int = 2831 + def foo2830(): Int = 2832 + def foo2831(): Int = 2833 + def foo2832(): Int = 2834 + def foo2833(): Int = 2835 + def foo2834(): Int = 2836 + def foo2835(): Int = 2837 + def foo2836(): Int = 2838 + def foo2837(): Int = 2839 + def foo2838(): Int = 2840 + def foo2839(): Int = 2841 + def foo2840(): Int = 2842 + def foo2841(): Int = 2843 + def foo2842(): Int = 2844 + def foo2843(): Int = 2845 + def foo2844(): Int = 2846 + def foo2845(): Int = 2847 + def foo2846(): Int = 2848 + def foo2847(): Int = 2849 + def foo2848(): Int = 2850 + def foo2849(): Int = 2851 + def foo2850(): Int = 2852 + def foo2851(): Int = 2853 + def foo2852(): Int = 2854 + def foo2853(): Int = 2855 + def foo2854(): Int = 2856 + def foo2855(): Int = 2857 + def foo2856(): Int = 2858 + def foo2857(): Int = 2859 + def foo2858(): Int = 2860 + def foo2859(): Int = 2861 + def foo2860(): Int = 2862 + def foo2861(): Int = 2863 + def foo2862(): Int = 2864 + def foo2863(): Int = 2865 + def foo2864(): Int = 2866 + def foo2865(): Int = 2867 + def foo2866(): Int = 2868 + def foo2867(): Int = 2869 + def foo2868(): Int = 2870 + def foo2869(): Int = 2871 + def foo2870(): Int = 2872 + def foo2871(): Int = 2873 + def foo2872(): Int = 2874 + def foo2873(): Int = 2875 + def foo2874(): Int = 2876 + def foo2875(): Int = 2877 + def foo2876(): Int = 2878 + def foo2877(): Int = 2879 + def foo2878(): Int = 2880 + def foo2879(): Int = 2881 + def foo2880(): Int = 2882 + def foo2881(): Int = 2883 + def foo2882(): Int = 2884 + def foo2883(): Int = 2885 + def foo2884(): Int = 2886 + def foo2885(): Int = 2887 + def foo2886(): Int = 2888 + def foo2887(): Int = 2889 + def foo2888(): Int = 2890 + def foo2889(): Int = 2891 + def foo2890(): Int = 2892 + def foo2891(): Int = 2893 + def foo2892(): Int = 2894 + def foo2893(): Int = 2895 + def foo2894(): Int = 2896 + def foo2895(): Int = 2897 + def foo2896(): Int = 2898 + def foo2897(): Int = 2899 + def foo2898(): Int = 2900 + def foo2899(): Int = 2901 + def foo2900(): Int = 2902 + def foo2901(): Int = 2903 + def foo2902(): Int = 2904 + def foo2903(): Int = 2905 + def foo2904(): Int = 2906 + def foo2905(): Int = 2907 + def foo2906(): Int = 2908 + def foo2907(): Int = 2909 + def foo2908(): Int = 2910 + def foo2909(): Int = 2911 + def foo2910(): Int = 2912 + def foo2911(): Int = 2913 + def foo2912(): Int = 2914 + def foo2913(): Int = 2915 + def foo2914(): Int = 2916 + def foo2915(): Int = 2917 + def foo2916(): Int = 2918 + def foo2917(): Int = 2919 + def foo2918(): Int = 2920 + def foo2919(): Int = 2921 + def foo2920(): Int = 2922 + def foo2921(): Int = 2923 + def foo2922(): Int = 2924 + def foo2923(): Int = 2925 + def foo2924(): Int = 2926 + def foo2925(): Int = 2927 + def foo2926(): Int = 2928 + def foo2927(): Int = 2929 + def foo2928(): Int = 2930 + def foo2929(): Int = 2931 + def foo2930(): Int = 2932 + def foo2931(): Int = 2933 + def foo2932(): Int = 2934 + def foo2933(): Int = 2935 + def foo2934(): Int = 2936 + def foo2935(): Int = 2937 + def foo2936(): Int = 2938 + def foo2937(): Int = 2939 + def foo2938(): Int = 2940 + def foo2939(): Int = 2941 + def foo2940(): Int = 2942 + def foo2941(): Int = 2943 + def foo2942(): Int = 2944 + def foo2943(): Int = 2945 + def foo2944(): Int = 2946 + def foo2945(): Int = 2947 + def foo2946(): Int = 2948 + def foo2947(): Int = 2949 + def foo2948(): Int = 2950 + def foo2949(): Int = 2951 + def foo2950(): Int = 2952 + def foo2951(): Int = 2953 + def foo2952(): Int = 2954 + def foo2953(): Int = 2955 + def foo2954(): Int = 2956 + def foo2955(): Int = 2957 + def foo2956(): Int = 2958 + def foo2957(): Int = 2959 + def foo2958(): Int = 2960 + def foo2959(): Int = 2961 + def foo2960(): Int = 2962 + def foo2961(): Int = 2963 + def foo2962(): Int = 2964 + def foo2963(): Int = 2965 + def foo2964(): Int = 2966 + def foo2965(): Int = 2967 + def foo2966(): Int = 2968 + def foo2967(): Int = 2969 + def foo2968(): Int = 2970 + def foo2969(): Int = 2971 + def foo2970(): Int = 2972 + def foo2971(): Int = 2973 + def foo2972(): Int = 2974 + def foo2973(): Int = 2975 + def foo2974(): Int = 2976 + def foo2975(): Int = 2977 + def foo2976(): Int = 2978 + def foo2977(): Int = 2979 + def foo2978(): Int = 2980 + def foo2979(): Int = 2981 + def foo2980(): Int = 2982 + def foo2981(): Int = 2983 + def foo2982(): Int = 2984 + def foo2983(): Int = 2985 + def foo2984(): Int = 2986 + def foo2985(): Int = 2987 + def foo2986(): Int = 2988 + def foo2987(): Int = 2989 + def foo2988(): Int = 2990 + def foo2989(): Int = 2991 + def foo2990(): Int = 2992 + def foo2991(): Int = 2993 + def foo2992(): Int = 2994 + def foo2993(): Int = 2995 + def foo2994(): Int = 2996 + def foo2995(): Int = 2997 + def foo2996(): Int = 2998 + def foo2997(): Int = 2999 + def foo2998(): Int = 3000 + def foo2999(): Int = 3001 + def foo3000(): Int = 3002 + def foo3001(): Int = 3003 + def foo3002(): Int = 3004 + def foo3003(): Int = 3005 + def foo3004(): Int = 3006 + def foo3005(): Int = 3007 + def foo3006(): Int = 3008 + def foo3007(): Int = 3009 + def foo3008(): Int = 3010 + def foo3009(): Int = 3011 + def foo3010(): Int = 3012 + def foo3011(): Int = 3013 + def foo3012(): Int = 3014 + def foo3013(): Int = 3015 + def foo3014(): Int = 3016 + def foo3015(): Int = 3017 + def foo3016(): Int = 3018 + def foo3017(): Int = 3019 + def foo3018(): Int = 3020 + def foo3019(): Int = 3021 + def foo3020(): Int = 3022 + def foo3021(): Int = 3023 + def foo3022(): Int = 3024 + def foo3023(): Int = 3025 + def foo3024(): Int = 3026 + def foo3025(): Int = 3027 + def foo3026(): Int = 3028 + def foo3027(): Int = 3029 + def foo3028(): Int = 3030 + def foo3029(): Int = 3031 + def foo3030(): Int = 3032 + def foo3031(): Int = 3033 + def foo3032(): Int = 3034 + def foo3033(): Int = 3035 + def foo3034(): Int = 3036 + def foo3035(): Int = 3037 + def foo3036(): Int = 3038 + def foo3037(): Int = 3039 + def foo3038(): Int = 3040 + def foo3039(): Int = 3041 + def foo3040(): Int = 3042 + def foo3041(): Int = 3043 + def foo3042(): Int = 3044 + def foo3043(): Int = 3045 + def foo3044(): Int = 3046 + def foo3045(): Int = 3047 + def foo3046(): Int = 3048 + def foo3047(): Int = 3049 + def foo3048(): Int = 3050 + def foo3049(): Int = 3051 + def foo3050(): Int = 3052 + def foo3051(): Int = 3053 + def foo3052(): Int = 3054 + def foo3053(): Int = 3055 + def foo3054(): Int = 3056 + def foo3055(): Int = 3057 + def foo3056(): Int = 3058 + def foo3057(): Int = 3059 + def foo3058(): Int = 3060 + def foo3059(): Int = 3061 + def foo3060(): Int = 3062 + def foo3061(): Int = 3063 + def foo3062(): Int = 3064 + def foo3063(): Int = 3065 + def foo3064(): Int = 3066 + def foo3065(): Int = 3067 + def foo3066(): Int = 3068 + def foo3067(): Int = 3069 + def foo3068(): Int = 3070 + def foo3069(): Int = 3071 + def foo3070(): Int = 3072 + def foo3071(): Int = 3073 + def foo3072(): Int = 3074 + def foo3073(): Int = 3075 + def foo3074(): Int = 3076 + def foo3075(): Int = 3077 + def foo3076(): Int = 3078 + def foo3077(): Int = 3079 + def foo3078(): Int = 3080 + def foo3079(): Int = 3081 + def foo3080(): Int = 3082 + def foo3081(): Int = 3083 + def foo3082(): Int = 3084 + def foo3083(): Int = 3085 + def foo3084(): Int = 3086 + def foo3085(): Int = 3087 + def foo3086(): Int = 3088 + def foo3087(): Int = 3089 + def foo3088(): Int = 3090 + def foo3089(): Int = 3091 + def foo3090(): Int = 3092 + def foo3091(): Int = 3093 + def foo3092(): Int = 3094 + def foo3093(): Int = 3095 + def foo3094(): Int = 3096 + def foo3095(): Int = 3097 + def foo3096(): Int = 3098 + def foo3097(): Int = 3099 + def foo3098(): Int = 3100 + def foo3099(): Int = 3101 + def foo3100(): Int = 3102 + def foo3101(): Int = 3103 + def foo3102(): Int = 3104 + def foo3103(): Int = 3105 + def foo3104(): Int = 3106 + def foo3105(): Int = 3107 + def foo3106(): Int = 3108 + def foo3107(): Int = 3109 + def foo3108(): Int = 3110 + def foo3109(): Int = 3111 + def foo3110(): Int = 3112 + def foo3111(): Int = 3113 + def foo3112(): Int = 3114 + def foo3113(): Int = 3115 + def foo3114(): Int = 3116 + def foo3115(): Int = 3117 + def foo3116(): Int = 3118 + def foo3117(): Int = 3119 + def foo3118(): Int = 3120 + def foo3119(): Int = 3121 + def foo3120(): Int = 3122 + def foo3121(): Int = 3123 + def foo3122(): Int = 3124 + def foo3123(): Int = 3125 + def foo3124(): Int = 3126 + def foo3125(): Int = 3127 + def foo3126(): Int = 3128 + def foo3127(): Int = 3129 + def foo3128(): Int = 3130 + def foo3129(): Int = 3131 + def foo3130(): Int = 3132 + def foo3131(): Int = 3133 + def foo3132(): Int = 3134 + def foo3133(): Int = 3135 + def foo3134(): Int = 3136 + def foo3135(): Int = 3137 + def foo3136(): Int = 3138 + def foo3137(): Int = 3139 + def foo3138(): Int = 3140 + def foo3139(): Int = 3141 + def foo3140(): Int = 3142 + def foo3141(): Int = 3143 + def foo3142(): Int = 3144 + def foo3143(): Int = 3145 + def foo3144(): Int = 3146 + def foo3145(): Int = 3147 + def foo3146(): Int = 3148 + def foo3147(): Int = 3149 + def foo3148(): Int = 3150 + def foo3149(): Int = 3151 + def foo3150(): Int = 3152 + def foo3151(): Int = 3153 + def foo3152(): Int = 3154 + def foo3153(): Int = 3155 + def foo3154(): Int = 3156 + def foo3155(): Int = 3157 + def foo3156(): Int = 3158 + def foo3157(): Int = 3159 + def foo3158(): Int = 3160 + def foo3159(): Int = 3161 + def foo3160(): Int = 3162 + def foo3161(): Int = 3163 + def foo3162(): Int = 3164 + def foo3163(): Int = 3165 + def foo3164(): Int = 3166 + def foo3165(): Int = 3167 + def foo3166(): Int = 3168 + def foo3167(): Int = 3169 + def foo3168(): Int = 3170 + def foo3169(): Int = 3171 + def foo3170(): Int = 3172 + def foo3171(): Int = 3173 + def foo3172(): Int = 3174 + def foo3173(): Int = 3175 + def foo3174(): Int = 3176 + def foo3175(): Int = 3177 + def foo3176(): Int = 3178 + def foo3177(): Int = 3179 + def foo3178(): Int = 3180 + def foo3179(): Int = 3181 + def foo3180(): Int = 3182 + def foo3181(): Int = 3183 + def foo3182(): Int = 3184 + def foo3183(): Int = 3185 + def foo3184(): Int = 3186 + def foo3185(): Int = 3187 + def foo3186(): Int = 3188 + def foo3187(): Int = 3189 + def foo3188(): Int = 3190 + def foo3189(): Int = 3191 + def foo3190(): Int = 3192 + def foo3191(): Int = 3193 + def foo3192(): Int = 3194 + def foo3193(): Int = 3195 + def foo3194(): Int = 3196 + def foo3195(): Int = 3197 + def foo3196(): Int = 3198 + def foo3197(): Int = 3199 + def foo3198(): Int = 3200 + def foo3199(): Int = 3201 + def foo3200(): Int = 3202 + def foo3201(): Int = 3203 + def foo3202(): Int = 3204 + def foo3203(): Int = 3205 + def foo3204(): Int = 3206 + def foo3205(): Int = 3207 + def foo3206(): Int = 3208 + def foo3207(): Int = 3209 + def foo3208(): Int = 3210 + def foo3209(): Int = 3211 + def foo3210(): Int = 3212 + def foo3211(): Int = 3213 + def foo3212(): Int = 3214 + def foo3213(): Int = 3215 + def foo3214(): Int = 3216 + def foo3215(): Int = 3217 + def foo3216(): Int = 3218 + def foo3217(): Int = 3219 + def foo3218(): Int = 3220 + def foo3219(): Int = 3221 + def foo3220(): Int = 3222 + def foo3221(): Int = 3223 + def foo3222(): Int = 3224 + def foo3223(): Int = 3225 + def foo3224(): Int = 3226 + def foo3225(): Int = 3227 + def foo3226(): Int = 3228 + def foo3227(): Int = 3229 + def foo3228(): Int = 3230 + def foo3229(): Int = 3231 + def foo3230(): Int = 3232 + def foo3231(): Int = 3233 + def foo3232(): Int = 3234 + def foo3233(): Int = 3235 + def foo3234(): Int = 3236 + def foo3235(): Int = 3237 + def foo3236(): Int = 3238 + def foo3237(): Int = 3239 + def foo3238(): Int = 3240 + def foo3239(): Int = 3241 + def foo3240(): Int = 3242 + def foo3241(): Int = 3243 + def foo3242(): Int = 3244 + def foo3243(): Int = 3245 + def foo3244(): Int = 3246 + def foo3245(): Int = 3247 + def foo3246(): Int = 3248 + def foo3247(): Int = 3249 + def foo3248(): Int = 3250 + def foo3249(): Int = 3251 + def foo3250(): Int = 3252 + def foo3251(): Int = 3253 + def foo3252(): Int = 3254 + def foo3253(): Int = 3255 + def foo3254(): Int = 3256 + def foo3255(): Int = 3257 + def foo3256(): Int = 3258 + def foo3257(): Int = 3259 + def foo3258(): Int = 3260 + def foo3259(): Int = 3261 + def foo3260(): Int = 3262 + def foo3261(): Int = 3263 + def foo3262(): Int = 3264 + def foo3263(): Int = 3265 + def foo3264(): Int = 3266 + def foo3265(): Int = 3267 + def foo3266(): Int = 3268 + def foo3267(): Int = 3269 + def foo3268(): Int = 3270 + def foo3269(): Int = 3271 + def foo3270(): Int = 3272 + def foo3271(): Int = 3273 + def foo3272(): Int = 3274 + def foo3273(): Int = 3275 + def foo3274(): Int = 3276 + def foo3275(): Int = 3277 + def foo3276(): Int = 3278 + def foo3277(): Int = 3279 + def foo3278(): Int = 3280 + def foo3279(): Int = 3281 + def foo3280(): Int = 3282 + def foo3281(): Int = 3283 + def foo3282(): Int = 3284 + def foo3283(): Int = 3285 + def foo3284(): Int = 3286 + def foo3285(): Int = 3287 + def foo3286(): Int = 3288 + def foo3287(): Int = 3289 + def foo3288(): Int = 3290 + def foo3289(): Int = 3291 + def foo3290(): Int = 3292 + def foo3291(): Int = 3293 + def foo3292(): Int = 3294 + def foo3293(): Int = 3295 + def foo3294(): Int = 3296 + def foo3295(): Int = 3297 + def foo3296(): Int = 3298 + def foo3297(): Int = 3299 + def foo3298(): Int = 3300 + def foo3299(): Int = 3301 + def foo3300(): Int = 3302 + def foo3301(): Int = 3303 + def foo3302(): Int = 3304 + def foo3303(): Int = 3305 + def foo3304(): Int = 3306 + def foo3305(): Int = 3307 + def foo3306(): Int = 3308 + def foo3307(): Int = 3309 + def foo3308(): Int = 3310 + def foo3309(): Int = 3311 + def foo3310(): Int = 3312 + def foo3311(): Int = 3313 + def foo3312(): Int = 3314 + def foo3313(): Int = 3315 + def foo3314(): Int = 3316 + def foo3315(): Int = 3317 + def foo3316(): Int = 3318 + def foo3317(): Int = 3319 + def foo3318(): Int = 3320 + def foo3319(): Int = 3321 + def foo3320(): Int = 3322 + def foo3321(): Int = 3323 + def foo3322(): Int = 3324 + def foo3323(): Int = 3325 + def foo3324(): Int = 3326 + def foo3325(): Int = 3327 + def foo3326(): Int = 3328 + def foo3327(): Int = 3329 + def foo3328(): Int = 3330 + def foo3329(): Int = 3331 + def foo3330(): Int = 3332 + def foo3331(): Int = 3333 + def foo3332(): Int = 3334 + def foo3333(): Int = 3335 + def foo3334(): Int = 3336 + def foo3335(): Int = 3337 + def foo3336(): Int = 3338 + def foo3337(): Int = 3339 + def foo3338(): Int = 3340 + def foo3339(): Int = 3341 + def foo3340(): Int = 3342 + def foo3341(): Int = 3343 + def foo3342(): Int = 3344 + def foo3343(): Int = 3345 + def foo3344(): Int = 3346 + def foo3345(): Int = 3347 + def foo3346(): Int = 3348 + def foo3347(): Int = 3349 + def foo3348(): Int = 3350 + def foo3349(): Int = 3351 + def foo3350(): Int = 3352 + def foo3351(): Int = 3353 + def foo3352(): Int = 3354 + def foo3353(): Int = 3355 + def foo3354(): Int = 3356 + def foo3355(): Int = 3357 + def foo3356(): Int = 3358 + def foo3357(): Int = 3359 + def foo3358(): Int = 3360 + def foo3359(): Int = 3361 + def foo3360(): Int = 3362 + def foo3361(): Int = 3363 + def foo3362(): Int = 3364 + def foo3363(): Int = 3365 + def foo3364(): Int = 3366 + def foo3365(): Int = 3367 + def foo3366(): Int = 3368 + def foo3367(): Int = 3369 + def foo3368(): Int = 3370 + def foo3369(): Int = 3371 + def foo3370(): Int = 3372 + def foo3371(): Int = 3373 + def foo3372(): Int = 3374 + def foo3373(): Int = 3375 + def foo3374(): Int = 3376 + def foo3375(): Int = 3377 + def foo3376(): Int = 3378 + def foo3377(): Int = 3379 + def foo3378(): Int = 3380 + def foo3379(): Int = 3381 + def foo3380(): Int = 3382 + def foo3381(): Int = 3383 + def foo3382(): Int = 3384 + def foo3383(): Int = 3385 + def foo3384(): Int = 3386 + def foo3385(): Int = 3387 + def foo3386(): Int = 3388 + def foo3387(): Int = 3389 + def foo3388(): Int = 3390 + def foo3389(): Int = 3391 + def foo3390(): Int = 3392 + def foo3391(): Int = 3393 + def foo3392(): Int = 3394 + def foo3393(): Int = 3395 + def foo3394(): Int = 3396 + def foo3395(): Int = 3397 + def foo3396(): Int = 3398 + def foo3397(): Int = 3399 + def foo3398(): Int = 3400 + def foo3399(): Int = 3401 + def foo3400(): Int = 3402 + def foo3401(): Int = 3403 + def foo3402(): Int = 3404 + def foo3403(): Int = 3405 + def foo3404(): Int = 3406 + def foo3405(): Int = 3407 + def foo3406(): Int = 3408 + def foo3407(): Int = 3409 + def foo3408(): Int = 3410 + def foo3409(): Int = 3411 + def foo3410(): Int = 3412 + def foo3411(): Int = 3413 + def foo3412(): Int = 3414 + def foo3413(): Int = 3415 + def foo3414(): Int = 3416 + def foo3415(): Int = 3417 + def foo3416(): Int = 3418 + def foo3417(): Int = 3419 + def foo3418(): Int = 3420 + def foo3419(): Int = 3421 + def foo3420(): Int = 3422 + def foo3421(): Int = 3423 + def foo3422(): Int = 3424 + def foo3423(): Int = 3425 + def foo3424(): Int = 3426 + def foo3425(): Int = 3427 + def foo3426(): Int = 3428 + def foo3427(): Int = 3429 + def foo3428(): Int = 3430 + def foo3429(): Int = 3431 + def foo3430(): Int = 3432 + def foo3431(): Int = 3433 + def foo3432(): Int = 3434 + def foo3433(): Int = 3435 + def foo3434(): Int = 3436 + def foo3435(): Int = 3437 + def foo3436(): Int = 3438 + def foo3437(): Int = 3439 + def foo3438(): Int = 3440 + def foo3439(): Int = 3441 + def foo3440(): Int = 3442 + def foo3441(): Int = 3443 + def foo3442(): Int = 3444 + def foo3443(): Int = 3445 + def foo3444(): Int = 3446 + def foo3445(): Int = 3447 + def foo3446(): Int = 3448 + def foo3447(): Int = 3449 + def foo3448(): Int = 3450 + def foo3449(): Int = 3451 + def foo3450(): Int = 3452 + def foo3451(): Int = 3453 + def foo3452(): Int = 3454 + def foo3453(): Int = 3455 + def foo3454(): Int = 3456 + def foo3455(): Int = 3457 + def foo3456(): Int = 3458 + def foo3457(): Int = 3459 + def foo3458(): Int = 3460 + def foo3459(): Int = 3461 + def foo3460(): Int = 3462 + def foo3461(): Int = 3463 + def foo3462(): Int = 3464 + def foo3463(): Int = 3465 + def foo3464(): Int = 3466 + def foo3465(): Int = 3467 + def foo3466(): Int = 3468 + def foo3467(): Int = 3469 + def foo3468(): Int = 3470 + def foo3469(): Int = 3471 + def foo3470(): Int = 3472 + def foo3471(): Int = 3473 + def foo3472(): Int = 3474 + def foo3473(): Int = 3475 + def foo3474(): Int = 3476 + def foo3475(): Int = 3477 + def foo3476(): Int = 3478 + def foo3477(): Int = 3479 + def foo3478(): Int = 3480 + def foo3479(): Int = 3481 + def foo3480(): Int = 3482 + def foo3481(): Int = 3483 + def foo3482(): Int = 3484 + def foo3483(): Int = 3485 + def foo3484(): Int = 3486 + def foo3485(): Int = 3487 + def foo3486(): Int = 3488 + def foo3487(): Int = 3489 + def foo3488(): Int = 3490 + def foo3489(): Int = 3491 + def foo3490(): Int = 3492 + def foo3491(): Int = 3493 + def foo3492(): Int = 3494 + def foo3493(): Int = 3495 + def foo3494(): Int = 3496 + def foo3495(): Int = 3497 + def foo3496(): Int = 3498 + def foo3497(): Int = 3499 + def foo3498(): Int = 3500 + def foo3499(): Int = 3501 + def foo3500(): Int = 3502 +} diff --git a/test/junit/scala/collection/IteratorTest.scala b/test/junit/scala/collection/IteratorTest.scala index d5389afd0c..1c1e50aed9 100644 --- a/test/junit/scala/collection/IteratorTest.scala +++ b/test/junit/scala/collection/IteratorTest.scala @@ -154,4 +154,14 @@ class IteratorTest { results += (Stream from 1).toIterator.drop(10).toStream.drop(10).toIterator.next() assertSameElements(List(1,1,21), results) } + // SI-9332 + @Test def spanExhaustsLeadingIterator(): Unit = { + def it = Iterator.iterate(0)(_ + 1).take(6) + val (x, y) = it.span(_ != 1) + val z = x.toList + assertEquals(1, z.size) + assertFalse(x.hasNext) + assertEquals(1, y.next) + assertFalse(x.hasNext) // was true, after advancing underlying iterator + } } diff --git a/test/junit/scala/collection/mutable/UnrolledBufferTest.scala b/test/junit/scala/collection/mutable/UnrolledBufferTest.scala new file mode 100644 index 0000000000..8660b6cbc1 --- /dev/null +++ b/test/junit/scala/collection/mutable/UnrolledBufferTest.scala @@ -0,0 +1,25 @@ +package scala.collection.mutable + +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.Test + +@RunWith(classOf[JUnit4]) +class UnrolledBufferTestTest { + @Test + def test_SI9254_original() { + val b = new UnrolledBuffer[Int]() + (1 to 16).foreach(i => b append i) + b.insert(0,-1) + b append 17 + assert(b sameElements (Seq(-1) ++ (1 to 16) ++ Seq(17))) + } + + @Test + def test_SI9254_additional() { + val b = new UnrolledBuffer[Int]() + (1 to 100).foreach(i => b append i) + b.insert(40, -1) + assert(b sameElements((1 to 40) ++ Seq(-1) ++ (41 to 100))) + } +} diff --git a/test/junit/scala/collection/mutable/VectorTest.scala b/test/junit/scala/collection/mutable/VectorTest.scala index e9c4d44a72..b3219d1b02 100644 --- a/test/junit/scala/collection/mutable/VectorTest.scala +++ b/test/junit/scala/collection/mutable/VectorTest.scala @@ -38,7 +38,6 @@ class VectorTest { def iteratorCat() { def its = vecs.map(_.toList.toIterator) val cats = vecs.map(a => its.map(a ++ _)) - println(cats) assert( cats == ans ) } diff --git a/test/junit/scala/concurrent/duration/SerializationTest.scala b/test/junit/scala/concurrent/duration/SerializationTest.scala new file mode 100644 index 0000000000..af90a10984 --- /dev/null +++ b/test/junit/scala/concurrent/duration/SerializationTest.scala @@ -0,0 +1,24 @@ +package scala.concurrent.duration + +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.Test + + +@RunWith(classOf[JUnit4]) +class SerializationTest { + @Test + def test_SI9197 { + def ser(a: AnyRef): Array[Byte] = { + val bais = new java.io.ByteArrayOutputStream + (new java.io.ObjectOutputStream(bais)).writeObject(a) + bais.toByteArray + } + def des(ab: Array[Byte]): AnyRef = + (new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(ab))).readObject + + assert(Duration.Undefined eq des(ser(Duration.Undefined))) + assert(Duration.Inf eq des(ser(Duration.Inf))) + assert(Duration.MinusInf eq des(ser(Duration.MinusInf))) + } +} diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala index 5d5215d887..d0ffd06b01 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala @@ -8,7 +8,6 @@ import scala.reflect.io.VirtualDirectory import scala.tools.asm.Opcodes import scala.tools.asm.tree.{ClassNode, MethodNode} import scala.tools.cmd.CommandLineParser -import scala.tools.nsc.backend.jvm.opt.LocalOpt import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.reporters.StoreReporter import scala.tools.nsc.settings.MutableSettings @@ -157,12 +156,6 @@ object CodeGenTools { assertTrue(h.start == insVec(startIndex) && h.end == insVec(endIndex) && h.handler == insVec(handlerIndex)) } - val localOpt = { - val settings = new MutableSettings(msg => throw new IllegalArgumentException(msg)) - settings.processArguments(List("-Yopt:l:method"), processAll = true) - new LocalOpt(settings) - } - import scala.language.implicitConversions implicit def aliveInstruction(ins: Instruction): (Instruction, Boolean) = (ins, true) diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala new file mode 100644 index 0000000000..3a85f03da2 --- /dev/null +++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala @@ -0,0 +1,231 @@ +package scala.tools.nsc +package backend.jvm +package analysis + +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.Test +import scala.tools.asm.Opcodes._ +import org.junit.Assert._ + +import CodeGenTools._ +import scala.tools.asm.tree.{AbstractInsnNode, MethodNode} +import scala.tools.nsc.backend.jvm.BTypes._ +import scala.tools.partest.ASMConverters +import ASMConverters._ +import scala.tools.testing.ClearAfterClass +import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._ +import AsmUtils._ + +import scala.collection.convert.decorateAsScala._ + +object NullnessAnalyzerTest extends ClearAfterClass.Clearable { + var noOptCompiler = newCompiler(extraArgs = "-Ybackend:GenBCode -Yopt:l:none") + + def clear(): Unit = { + noOptCompiler = null + } +} + +@RunWith(classOf[JUnit4]) +class NullnessAnalyzerTest extends ClearAfterClass { + ClearAfterClass.stateToClear = NullnessAnalyzerTest + val noOptCompiler = NullnessAnalyzerTest.noOptCompiler + + def newNullnessAnalyzer(methodNode: MethodNode, classInternalName: InternalName = "C"): NullnessAnalyzer = { + val nullnessAnalyzer = new NullnessAnalyzer + nullnessAnalyzer.analyze(classInternalName, methodNode) + nullnessAnalyzer + } + + /** + * Instructions that match `query` when textified. + * If `query` starts with a `+`, the next instruction is returned. + */ + def findInstr(method: MethodNode, query: String): List[AbstractInsnNode] = { + val useNext = query(0) == '+' + val instrPart = if (useNext) query.drop(1) else query + val insns = method.instructions.iterator.asScala.find(i => textify(i) contains instrPart).toList + if (useNext) insns.map(_.getNext) else insns + } + + def testNullness(analyzer: NullnessAnalyzer, method: MethodNode, query: String, index: Int, nullness: Nullness): Unit = { + for (i <- findInstr(method, query)) { + val r = analyzer.frameAt(i, method).getValue(index).nullness + assertTrue(s"Expected: $nullness, found: $r. At instr ${textify(i)}", nullness == r) + } + } + + // debug / helper for writing tests + def showAllNullnessFrames(analyzer: NullnessAnalyzer, method: MethodNode): String = { + val instrLength = method.instructions.iterator.asScala.map(textify(_).length).max + val lines = for (i <- method.instructions.iterator.asScala) yield { + val f = analyzer.frameAt(i, method) + val frameString = { + if (f == null) "null" + else (0 until (f.getLocals + f.getStackSize)).iterator + .map(f.getValue(_).toString) + .map(s => "%8s".format(s)) + .zipWithIndex.map({case (s, i) => s"$i: $s"}) + .mkString(", ") + } + ("%"+ instrLength +"s: %s").format(textify(i), frameString) + } + lines.mkString("\n") + } + + @Test + def showNullnessFramesTest(): Unit = { + val List(m) = compileMethods(noOptCompiler)("def f = this.toString") + + // NOTE: the frame for an instruction represents the state *before* executing that instr. + // So in the frame for `ALOAD 0`, the stack is still empty. + + val res = + """ L0: 0: NotNull + | LINENUMBER 1 L0: 0: NotNull + | ALOAD 0: 0: NotNull + |INVOKEVIRTUAL java/lang/Object.toString ()Ljava/lang/String;: 0: NotNull, 1: NotNull + | ARETURN: 0: NotNull, 1: Unknown1 + | L0: null""".stripMargin + assertEquals(showAllNullnessFrames(newNullnessAnalyzer(m), m), res) + } + + @Test + def thisNonNull(): Unit = { + val List(m) = compileMethods(noOptCompiler)("def f = this.toString") + val a = newNullnessAnalyzer(m) + testNullness(a, m, "ALOAD 0", 0, NotNull) + } + + @Test + def instanceMethodCall(): Unit = { + val List(m) = compileMethods(noOptCompiler)("def f(a: String) = a.trim") + val a = newNullnessAnalyzer(m) + testNullness(a, m, "INVOKEVIRTUAL java/lang/String.trim", 1, Unknown) + testNullness(a, m, "ARETURN", 1, NotNull) + } + + @Test + def constructorCall(): Unit = { + val List(m) = compileMethods(noOptCompiler)("def f = { val a = new Object; a.toString }") + val a = newNullnessAnalyzer(m) + + // for reference, the output of showAllNullnessFrames(a, m) - note that the frame represents the state *before* executing the instr. + // NEW java/lang/Object: 0: NotNull, 1: Unknown + // DUP: 0: NotNull, 1: Unknown, 2: Unknown + // INVOKESPECIAL java/lang/Object.<init>: 0: NotNull, 1: Unknown, 2: Unknown, 3: Unknown + // ASTORE 1: 0: NotNull, 1: Unknown, 2: NotNull + // ALOAD 1: 0: NotNull, 1: NotNull + // INVOKEVIRTUAL java/lang/Object.toString: 0: NotNull, 1: NotNull, 2: NotNull + // ARETURN: 0: NotNull, 1: NotNull, 2: Unknown + + for ((insn, index, nullness) <- List( + ("+NEW", 2, Unknown), // new value at slot 2 on the stack + ("+DUP", 3, Unknown), + ("+INVOKESPECIAL java/lang/Object", 2, NotNull), // after calling the initializer on 3, the value at 2 becomes NotNull + ("ASTORE 1", 1, Unknown), // before the ASTORE 1, nullness of the value in local 1 is Unknown + ("+ASTORE 1", 1, NotNull), // after storing the value at 2 in local 1, the local 1 is NotNull + ("+ALOAD 1", 2, NotNull), // loading the value 1 puts a NotNull value on the stack (at 2) + ("+INVOKEVIRTUAL java/lang/Object.toString", 2, Unknown) // nullness of value returned by `toString` is Unknown + )) testNullness(a, m, insn, index, nullness) + } + + @Test + def explicitNull(): Unit = { + val List(m) = compileMethods(noOptCompiler)("def f = { var a: Object = null; a }") + val a = newNullnessAnalyzer(m) + for ((insn, index, nullness) <- List( + ("+ACONST_NULL", 2, Null), + ("+ASTORE 1", 1, Null), + ("+ALOAD 1", 2, Null) + )) testNullness(a, m, insn, index, nullness) + } + + @Test + def stringLiteralsNotNull(): Unit = { + val List(m) = compileMethods(noOptCompiler)("""def f = { val a = "hi"; a.trim }""") + val a = newNullnessAnalyzer(m) + testNullness(a, m, "+ASTORE 1", 1, NotNull) + } + + @Test + def newArraynotNull() { + val List(m) = compileMethods(noOptCompiler)("def f = { val a = new Array[Int](2); a(0) }") + val a = newNullnessAnalyzer(m) + testNullness(a, m, "+NEWARRAY T_INT", 2, NotNull) // new array on stack + testNullness(a, m, "+ASTORE 1", 1, NotNull) // local var (a) + } + + @Test + def aliasBranching(): Unit = { + val code = + """def f(o: Object) = { + | var a: Object = o // a and o are aliases + | var b: Object = null + | var c: Object = null + | var d: Object = o + | if ("".trim == "") { + | b = o + | c = o // a, o, b, aliases + | d = null + | } else { + | b = a // a, o, b aliases + | d = null + | } + | b.toString // a, o, b aliases (so they become NotNull), but not c + | // d is null here, assinged in both branches. + |} + """.stripMargin + val List(m) = compileMethods(noOptCompiler)(code) + val a = newNullnessAnalyzer(m) + + val trim = "INVOKEVIRTUAL java/lang/String.trim" + val toSt = "INVOKEVIRTUAL java/lang/Object.toString" + val end = s"+$toSt" + for ((insn, index, nullness) <- List( + (trim, 0, NotNull), // this + (trim, 1, Unknown), // parameter o + (trim, 2, Unknown), // a + (trim, 3, Null), // b + (trim, 4, Null), // c + (trim, 5, Unknown), // d + + (toSt, 2, Unknown), // a, still the same + (toSt, 3, Unknown), // b, was re-assinged in both branches to Unknown + (toSt, 4, Unknown), // c, was re-assigned in one branch to Unknown + (toSt, 5, Null), // d, was assigned to null in both branches + + (end, 2, NotNull), // a, NotNull (alias of b) + (end, 3, NotNull), // b, receiver of toString + (end, 4, Unknown), // c, no change (not an alias of b) + (end, 5, Null) // d, no change + )) testNullness(a, m, insn, index, nullness) + } + + @Test + def testInstanceOf(): Unit = { + val code = + """def f(a: Object) = { + | val x = a + | x.isInstanceOf[Throwable] // x and a remain unknown - INSTANCEOF doesn't throw a NPE on null + | x.toString // x and a are not null + | a.asInstanceOf[String].trim // the stack value (LOAD of local a) is still not-null after the CHECKCAST + |} + """.stripMargin + val List(m) = compileMethods(noOptCompiler)(code) + val a = newNullnessAnalyzer(m) + + val instof = "+INSTANCEOF" + val tost = "+INVOKEVIRTUAL java/lang/Object.toString" + val trim = "INVOKEVIRTUAL java/lang/String.trim" + + for ((insn, index, nullness) <- List( + (instof, 1, Unknown), // a after INSTANCEOF + (instof, 2, Unknown), // x after INSTANCEOF + (tost, 1, NotNull), + (tost, 2, NotNull), + (trim, 3, NotNull) // receiver at `trim` + )) testNullness(a, m, insn, index, nullness) + } +} diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala index 7b0504fec0..cb01f3d164 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala @@ -40,7 +40,7 @@ class EmptyExceptionHandlersTest extends ClearAfterClass { Op(RETURN) ) assertTrue(convertMethod(asmMethod).handlers.length == 1) - localOpt.removeEmptyExceptionHandlers(asmMethod) + LocalOptImpls.removeEmptyExceptionHandlers(asmMethod) assertTrue(convertMethod(asmMethod).handlers.isEmpty) } @@ -61,7 +61,7 @@ class EmptyExceptionHandlersTest extends ClearAfterClass { Op(RETURN) ) assertTrue(convertMethod(asmMethod).handlers.length == 1) - localOpt.removeEmptyExceptionHandlers(asmMethod) + LocalOptImpls.removeEmptyExceptionHandlers(asmMethod) assertTrue(convertMethod(asmMethod).handlers.isEmpty) } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala index 8c0168826e..7283e20745 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala @@ -42,14 +42,14 @@ class EmptyLabelsAndLineNumbersTest { ) val method = genMethod()(ops.map(_._1): _*) - assertTrue(localOpt.removeEmptyLineNumbers(method)) + assertTrue(LocalOptImpls.removeEmptyLineNumbers(method)) assertSameCode(instructionsFromMethod(method), ops.filter(_._2).map(_._1)) } @Test def badlyLocatedLineNumbers(): Unit = { def t(ops: Instruction*) = - assertThrows[AssertionError](localOpt.removeEmptyLineNumbers(genMethod()(ops: _*))) + assertThrows[AssertionError](LocalOptImpls.removeEmptyLineNumbers(genMethod()(ops: _*))) // line numbers have to be right after their referenced label node t(LineNumber(0, Label(1)), Label(1)) @@ -88,7 +88,7 @@ class EmptyLabelsAndLineNumbersTest { ) val method = genMethod(handlers = handler)(ops(2, 3, 8, 8, 9, 11).map(_._1): _*) - assertTrue(localOpt.removeEmptyLabelNodes(method)) + assertTrue(LocalOptImpls.removeEmptyLabelNodes(method)) val m = convertMethod(method) assertSameCode(m.instructions, ops(1, 1, 7, 7, 7, 10).filter(_._2).map(_._1)) assertTrue(m.handlers match { diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala index fedc074a15..029caa995c 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala @@ -143,4 +143,52 @@ class InlineWarningTest extends ClearAfterClass { compileClasses(newCompiler(extraArgs = InlineWarningTest.argsNoWarn + " -Yopt-warnings:no-inline-mixed"))(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)}) assert(c == 2, c) } + + @Test + def cannotInlinePrivateCallIntoDifferentClass(): Unit = { + val code = + """class M { + | @inline final def f = { + | @noinline def nested = 0 + | nested + | } + | + | def t = f // ok + |} + | + |class N { + | def t(a: M) = a.f // not possible + |} + """.stripMargin + + val warn = + """M::f()I is annotated @inline but could not be inlined: + |The callee M::f()I contains the instruction INVOKESPECIAL M.nested$1 ()I + |that would cause an IllegalAccessError when inlined into class N""".stripMargin + + var c = 0 + compile(code, allowMessage = i => { c += 1; i.msg contains warn }) + assert(c == 1, c) + } + + @Test + def cannotMixStrictfp(): Unit = { + val code = + """import annotation.strictfp + |class C { + | @strictfp @inline final def f = 0 + | @strictfp def t1 = f + | def t2 = f + |} + """.stripMargin + + val warn = + """C::f()I is annotated @inline but could not be inlined: + |The callsite method C::t2()I + |does not have the same strictfp mode as the callee C::f()I.""".stripMargin + + var c = 0 + compile(code, allowMessage = i => { c += 1; i.msg contains warn }) + assert(c == 1, c) + } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 39fb28570e..b8c5f85c49 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -152,7 +152,7 @@ class InlinerTest extends ClearAfterClass { assertSameCode(convertMethod(g).instructions.dropNonOp.take(4), expectedInlined) - localOpt.methodOptimizations(g, "C") + compiler.genBCode.bTypes.localOpt.methodOptimizations(g, "C") assertSameCode(convertMethod(g).instructions.dropNonOp, expectedInlined ++ List(VarOp(ASTORE, 2), VarOp(ALOAD, 2), Op(ATHROW))) } @@ -720,7 +720,7 @@ class InlinerTest extends ClearAfterClass { |final class D extends C |object E extends C |class T { - | def t1(d: D) = d.f + d.g + E.f + E.g // d.f can be inlined because the reciever type is D, which is final. + | def t1(d: D) = d.f + d.g + E.f + E.g // d.f can be inlined because the receiver type is D, which is final. |} // so d.f can be resolved statically. same for E.f """.stripMargin val List(c, d, e, eModule, t) = compile(code) @@ -950,4 +950,45 @@ class InlinerTest extends ClearAfterClass { assertInvoke(getSingleMethod(t, "t3"), "B", "<init>") assertInvoke(getSingleMethod(t, "t4"), "B", "<init>") } + + @Test + def dontInlineNative(): Unit = { + val code = + """class C { + | def t = System.arraycopy(null, 0, null, 0, 0) + |} + """.stripMargin + val List(c) = compileClasses(newCompiler(extraArgs = InlinerTest.args + " -Yopt-inline-heuristics:everything"))(code) + assertInvoke(getSingleMethod(c, "t"), "java/lang/System", "arraycopy") + } + + @Test + def inlineMayRenderCodeDead(): Unit = { + val code = + """class C { + | @inline final def f: String = throw new Error("") + | @inline final def g: String = "a" + f + "b" // after inlining f, need to run DCE, because the rest of g becomes dead. + | def t = g // the inliner requires no dead code when inlining g (uses an Analyzer). + |} + """.stripMargin + + val List(c) = compile(code) + assertInvoke(getSingleMethod(c, "t"), "java/lang/Error", "<init>") + } + + @Test + def noRedunantNullChecks(): Unit = { + val code = + """class C { + | @inline final def f: String = "hai!" + | def t(c: C) = {c.f; c.f} // null check on the first, but not the second + |} + """.stripMargin + + val List(c) = compile(code) + val t = getSingleMethod(c, "t").instructions + assertNoInvoke(t) + assert(2 == t.collect({case Ldc(_, "hai!") => }).size) // twice the body of f + assert(1 == t.collect({case Jump(IFNONNULL, _) => }).size) // one single null check + } } 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 360fa1d23d..a685ae7dd5 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala @@ -26,7 +26,7 @@ class SimplifyJumpsTest { Op(RETURN) ) val method = genMethod()(ops: _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), Op(RETURN) :: ops.tail) } @@ -45,7 +45,7 @@ class SimplifyJumpsTest { Jump(GOTO, Label(2)) :: // replaced by ATHROW rest: _* ) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), Op(ACONST_NULL) :: Op(ATHROW) :: rest) } @@ -66,11 +66,11 @@ class SimplifyJumpsTest { Op(RETURN) ) val method = genMethod(handlers = handler)(initialInstrs: _*) - assertFalse(localOpt.simplifyJumps(method)) + assertFalse(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), initialInstrs) val optMethod = genMethod()(initialInstrs: _*) // no handler - assertTrue(localOpt.simplifyJumps(optMethod)) + assertTrue(LocalOptImpls.simplifyJumps(optMethod)) assertSameCode(instructionsFromMethod(optMethod).take(3), List(Label(1), Op(ACONST_NULL), Op(ATHROW))) } @@ -91,7 +91,7 @@ class SimplifyJumpsTest { Op(IRETURN) ) val method = genMethod()(begin ::: rest: _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode( instructionsFromMethod(method), List(VarOp(ILOAD, 1), Jump(IFLT, Label(3))) ::: rest.tail ) @@ -99,7 +99,7 @@ class SimplifyJumpsTest { // 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(localOpt.simplifyJumps(nonOptMethod)) + assertFalse(LocalOptImpls.simplifyJumps(nonOptMethod)) } @Test @@ -116,7 +116,7 @@ class SimplifyJumpsTest { // ensures that the goto is safely removed. ASM supports removing while iterating, but not the // next element of the current. Here, the current is the IFGE, the next is the GOTO. val method = genMethod()(code(Jump(IFGE, Label(2)), Jump(GOTO, Label(3))): _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), code(Jump(IFLT, Label(3)))) } @@ -131,7 +131,7 @@ class SimplifyJumpsTest { Op(IRETURN) ) val method = genMethod()(ops: _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), ops.tail) } @@ -157,7 +157,7 @@ class SimplifyJumpsTest { Op(IRETURN) ) val method = genMethod()(ops(1, 2, 3): _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), ops(3, 3, 3)) } @@ -181,7 +181,7 @@ class SimplifyJumpsTest { ) val method = genMethod()(ops(2): _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), ops(3)) } @@ -202,7 +202,7 @@ class SimplifyJumpsTest { ) val method = genMethod()(ops(Jump(IFGE, Label(1))): _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), ops(Op(POP))) } @@ -215,7 +215,7 @@ class SimplifyJumpsTest { Jump(GOTO, Label(1)) ) val method = genMethod()(ops(List(Jump(IF_ICMPGE, Label(1)))): _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), ops(List(Op(POP), Op(POP)))) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala index da9853148b..902af7b7fa 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala @@ -44,7 +44,7 @@ class UnreachableCodeTest extends ClearAfterClass { def assertEliminateDead(code: (Instruction, Boolean)*): Unit = { val method = genMethod()(code.map(_._1): _*) - localOpt.removeUnreachableCodeImpl(method, "C") + LocalOptImpls.removeUnreachableCodeImpl(method, "C") val nonEliminated = instructionsFromMethod(method) val expectedLive = code.filter(_._2).map(_._1).toList assertSameCode(nonEliminated, expectedLive) diff --git a/test/junit/scala/tools/nsc/interpreter/TabulatorTest.scala b/test/junit/scala/tools/nsc/interpreter/TabulatorTest.scala index 21e338eac0..263265026a 100644 --- a/test/junit/scala/tools/nsc/interpreter/TabulatorTest.scala +++ b/test/junit/scala/tools/nsc/interpreter/TabulatorTest.scala @@ -82,4 +82,24 @@ class TabulatorTest { assert(rows(0).size == 1) assert(rows(0)(0).size == "efg".length + sut.marginSize) // 6 } + @Test def badFit() = { + val sut = VTabby(isAcross = true) + val items = ('a' until 'z').map(_.toString).toList + val rows = sut tabulate items + assert(rows.size == 2) + assert(rows(0).size == 20) // 20 * 4 = 80 + assert(rows(1)(0).dropRight(sut.marginSize) == "u") + } + @Test def badFitter() = { + val sut = VTabby(isAcross = true) + val items = List ( + "%", "&", "*", "+", "-", "/", ">", ">=", ">>", ">>>", "^", + "asInstanceOf", "isInstanceOf", "toByte", "toChar", "toDouble", "toFloat", + "toInt", "toLong", "toShort", "toString", "unary_+", "unary_-", "unary_~", "|" + ) + val rows = sut tabulate items + assert(rows.size == 4) + assert(rows(3).size == 4) // 7 cols + assert(rows(3)(0).dropRight(sut.marginSize) == "unary_+") + } } diff --git a/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala b/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala index 1fff9c9a32..7bcb90a2ee 100644 --- a/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala +++ b/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala @@ -6,6 +6,7 @@ import org.junit.runner.RunWith import org.junit.runners.JUnit4 import scala.collection.mutable +import scala.reflect.internal.util.Position import scala.tools.nsc.{Global, Settings} object TestSolver extends Logic with Solving { @@ -51,6 +52,8 @@ object TestSolver extends Logic with Solving { def domainSyms = None + def groupedDomains: List[Set[TestSolver.Sym]] = Nil + def implications = Nil def mayBeNull = false @@ -72,6 +75,8 @@ object TestSolver extends Logic with Solving { def prepareNewAnalysis() = {} + def uncheckedWarning(pos: Position, msg: String) = sys.error(msg) + def reportWarning(msg: String) = sys.error(msg) /** @@ -204,11 +209,44 @@ class SolvingTest { import scala.tools.nsc.transform.patmat.TestSolver.TestSolver._ - implicit val Ord: Ordering[TestSolver.TestSolver.Model] = Ordering.by { - _.toSeq.sortBy(_.toString()).toIterable + object SymName { + def unapply(s: Sym): Option[String] = { + val Var(Tree(name)) = s.variable + Some(name) + } + } + + implicit val ModelOrd: Ordering[TestSolver.TestSolver.Model] = Ordering.by { + _.toSeq.sortWith { + case ((sym1, v1), (sym2, v2)) => + val SymName(name1) = sym1 + val SymName(name2) = sym2 + if (name1 < name2) + true + else if (name1 > name2) + false + else + v1 < v2 + }.toIterable } - private def sym(name: String) = Sym(Var(Tree(name)), NullConst) + implicit val SolutionOrd: Ordering[TestSolver.TestSolver.Solution] = + Ordering.by(_.model) + + def formatSolution(solution: Solution): String = { + formatModel(solution.model) + } + + def formatModel(model: Model): String = { + (for { + (SymName(name), value) <- model + } yield { + val v = if (value) "T" else "F" + s"$name -> $v" + }).mkString(", ") + } + + def sym(name: String) = Sym(Var(Tree(name)), NullConst) @Test def testSymCreation() { @@ -550,6 +588,23 @@ class SolvingTest { assertEquals(tseitinNoUnassigned, expansionNoUnassigned) } } + + def pairWiseEncoding(ops: List[Sym]) = { + And(ops.combinations(2).collect { + case a :: b :: Nil => Or(Not(a), Not(b)) + }.toSet[TestSolver.TestSolver.Prop]) + } + + @Test + def testAtMostOne() { + val dummySym = sym("dummy") + val syms = "pqrstu".map(c => sym(c.toString)).toList + // expand unassigned variables + // (otherwise solutions can not be compared) + val expected = TestSolver.TestSolver.findAllModelsFor(propToSolvable(And(dummySym, pairWiseEncoding(syms)))).flatMap(expandUnassigned) + val actual = TestSolver.TestSolver.findAllModelsFor(propToSolvable(And(dummySym, AtMostOne(syms)))).flatMap(expandUnassigned) + assertEquals(expected.toSet, actual.toSet) + } } diff --git a/test/junit/scala/util/SortingTest.scala b/test/junit/scala/util/SortingTest.scala new file mode 100644 index 0000000000..15a00c8903 --- /dev/null +++ b/test/junit/scala/util/SortingTest.scala @@ -0,0 +1,69 @@ +package scala.util + +import org.junit.Test +import org.junit.Assert._ +import scala.math.{ Ordered, Ordering } +import scala.reflect.ClassTag + +class SortingTest { + case class N(i: Int, j: Int) extends Ordered[N] { def compare(n: N) = if (i < n.i) -1 else if (i > n.i) 1 else 0 } + + def mkA(n: Int, max: Int) = Array.tabulate(n)(i => N(util.Random.nextInt(max), i)) + + def isStable(a: Array[N]): Boolean = { var i = 1; while (i < a.length) { if (a(i).i < a(i-1).i || (a(i).i == a(i-1).i && a(i).j < a(i-1).j)) return false; i += 1 }; true } + + def isAntistable(a: Array[N]): Boolean = + { var i = 1; while (i < a.length) { if (a(i).i > a(i-1).i || (a(i).i == a(i-1).i && a(i).j < a(i-1).j)) return false; i += 1 }; true } + + def isSorted(a: Array[N]): Boolean = { var i = 1; while (i < a.length) { if (a(i).i < a(i-1).i) return false; i += 1 }; true } + + def isAntisorted(a: Array[N]): Boolean = { var i = 1; while (i < a.length) { if (a(i).i > a(i-1).i) return false; i += 1 }; true } + + val sizes = Seq.range(0, 65) ++ Seq(256, 1024, 9121, 65539) + val variety = Seq(1, 2, 10, 100, 1000, Int.MaxValue) + val workLimit = 1e6 + val rng = new util.Random(198571) + + val backwardsN = Ordering by ((n: N) => -n.i) + + def runOneTest(size: Int, variety: Int): Unit = { + val xs = Array.tabulate(size)(i => N(rng.nextInt(variety), i)) + val ys = Array.range(0, xs.length) + val zs = { val temp = xs.clone; java.util.Arrays.sort(temp, new java.util.Comparator[N] { def compare(a: N, b: N) = a.compare(b) }); temp } + val qxs = { val temp = xs.clone; Sorting.quickSort(temp); temp } + val pxs = { val temp = xs.clone; Sorting.quickSort(temp)(backwardsN); temp } + val sxs = { val temp = xs.clone; Sorting.stableSort(temp); temp } + val rxs = { val temp = xs.clone; Sorting.stableSort(temp)(implicitly[ClassTag[N]], backwardsN); temp } + val sys = Sorting.stableSort(ys.clone: Seq[Int], (i: Int) => xs(i)) + + assertTrue("Quicksort should be in order", isSorted(qxs)) + assertTrue("Quicksort should be in reverse order", isAntisorted(pxs)) + assertTrue("Stable sort should be sorted and stable", isStable(sxs)) + assertTrue("Stable sort should be reverse sorted but stable", isAntistable(rxs)) + assertTrue("Stable sorting by proxy should produce sorted stable list", isStable(sys.map(i => xs(i)))) + assertTrue("Quicksort should produce canonical ordering", (qxs zip zs).forall{ case (a,b) => a.i == b.i }) + assertTrue("Reverse quicksort should produce canonical ordering", (pxs.reverse zip zs).forall{ case (a,b) => a.i == b.i }) + assertTrue("Stable sort should produce exact ordering", (sxs zip zs).forall{ case (a,b) => a == b }) + assertTrue("Reverse stable sort should produce canonical ordering", (rxs.reverse zip zs).forall{ case (a,b) => a.i == b.i }) + assertTrue("Proxy sort and direct sort should produce exactly the same thing", (sxs zip sys.map(i => xs(i))).forall{ case (a,b) => a == b }) + } + + @Test def testSortConsistency: Unit = { + for { + size <- sizes + v <- variety + i <- 0 until math.min(100, math.max(math.min(math.floor(math.pow(v, size)/2), math.ceil(workLimit / (math.log(math.max(2,size))/math.log(2) * size))), 1).toInt) + } runOneTest(size, v) + + for (size <- sizes) { + val b = Array.fill(size)(rng.nextBoolean) + val bfwd = Sorting.stableSort(b.clone: Seq[Boolean]) + val bbkw = Sorting.stableSort(b.clone: Seq[Boolean], (x: Boolean, y: Boolean) => x && !y) + assertTrue("All falses should be first", bfwd.dropWhile(_ == false).forall(_ == true)) + assertTrue("All falses should be last when sorted backwards", bbkw.dropWhile(_ == true).forall(_ == false)) + assertTrue("Sorting booleans should preserve the number of trues", b.count(_ == true) == bfwd.count(_ == true)) + assertTrue("Backwards sorting booleans should preserve the number of trues", b.count(_ == true) == bbkw.count(_ == true)) + assertTrue("Sorting should not change the sizes of arrays", b.length == bfwd.length && b.length == bbkw.length) + } + } +} diff --git a/test/pending/jvm/javasigs.scala b/test/pending/jvm/javasigs.scala index 8da59ab0a0..d18a4e6fb5 100644 --- a/test/pending/jvm/javasigs.scala +++ b/test/pending/jvm/javasigs.scala @@ -32,7 +32,7 @@ object Scalatest { } - /** Execute cmd, wait for the process to end and pipe it's output to stdout */ + /** Execute cmd, wait for the process to end and pipe its output to stdout */ def exec(cmd: String) { val proc = Runtime.getRuntime().exec(cmd) val inp = new BufferedReader(new InputStreamReader(proc.getInputStream)) diff --git a/test/pending/run/delambdafy-lambdametafactory.scala b/test/pending/run/delambdafy-lambdametafactory.scala new file mode 100644 index 0000000000..daea8a39fe --- /dev/null +++ b/test/pending/run/delambdafy-lambdametafactory.scala @@ -0,0 +1,50 @@ +// +// Tests that the static accessor method for lambda bodies +// (generated under -Ydelambdafy:method) are compatible with +// Java 8's LambdaMetafactory. +// +import java.lang.invoke._ + +class C { + def test1: Unit = { + (x: String) => x.reverse + } + def test2: Unit = { + val capture1 = "capture1" + (x: String) => capture1 + " " + x.reverse + } + def test3: Unit = { + (x: String) => C.this + " " + x.reverse + } +} +trait T { + def test4: Unit = { + (x: String) => x.reverse + } +} + +// A functional interface. Function1 contains abstract methods that are filled in by mixin +trait Function1ish[A, B] { + def apply(a: A): B +} + +object Test { + def lambdaFactory[A, B](hostClass: Class[_], instantiatedParam: Class[A], instantiatedRet: Class[B], accessorName: String, + capturedParams: Array[(Class[_], AnyRef)] = Array()) = { + val caller = MethodHandles.lookup + val methodType = MethodType.methodType(classOf[AnyRef], Array[Class[_]](classOf[AnyRef])) + val instantiatedMethodType = MethodType.methodType(instantiatedRet, Array[Class[_]](instantiatedParam)) + val (capturedParamTypes, captured) = capturedParams.unzip + val targetMethodType = MethodType.methodType(instantiatedRet, capturedParamTypes :+ instantiatedParam) + val invokedType = MethodType.methodType(classOf[Function1ish[_, _]], capturedParamTypes) + val target = caller.findStatic(hostClass, accessorName, targetMethodType) + val site = LambdaMetafactory.metafactory(caller, "apply", invokedType, methodType, target, instantiatedMethodType) + site.getTarget.invokeWithArguments(captured: _*).asInstanceOf[Function1ish[A, B]] + } + def main(args: Array[String]) { + println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$1").apply("abc")) + println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$2", Array(classOf[String] -> "capture1")).apply("abc")) + println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$3", Array(classOf[C] -> new C)).apply("abc")) + println(lambdaFactory(Class.forName("T$class"), classOf[String], classOf[String], "accessor$4", Array(classOf[T] -> new T{})).apply("abc")) + } +} diff --git a/test/scaladoc/resources/SI-4476.scala b/test/scaladoc/resources/SI-4476.scala new file mode 100644 index 0000000000..eb35ef45e7 --- /dev/null +++ b/test/scaladoc/resources/SI-4476.scala @@ -0,0 +1,9 @@ +package foo + +@deprecated("","") +class A + +class B { + @deprecated("","") + def bar = 1 +} diff --git a/test/scaladoc/resources/Trac4420.scala b/test/scaladoc/resources/Trac4420.scala index dbe053f3da..d8e207876b 100644 --- a/test/scaladoc/resources/Trac4420.scala +++ b/test/scaladoc/resources/Trac4420.scala @@ -1,7 +1,7 @@ import java.io.File /** - * @define PP This class is an instance of XXX so it's members are not called directly. + * @define PP This class is an instance of XXX so its members are not called directly. * Instead these classes are instantiated via a driver's ''process''. See YYY for more details. */ abstract class test diff --git a/test/scaladoc/run/SI-8210.check b/test/scaladoc/run/SI-8210.check new file mode 100644 index 0000000000..619c56180b --- /dev/null +++ b/test/scaladoc/run/SI-8210.check @@ -0,0 +1 @@ +Done. diff --git a/test/scaladoc/run/SI-8210.scala b/test/scaladoc/run/SI-8210.scala new file mode 100644 index 0000000000..3bd818473f --- /dev/null +++ b/test/scaladoc/run/SI-8210.scala @@ -0,0 +1,24 @@ +import scala.tools.nsc.doc.model._ +import scala.tools.partest.ScaladocModelTest + +object Test extends ScaladocModelTest { + override def code = """ +object Foo { + trait Config { + /** The bar obviously. */ + def bar: Int + } + class ConfigBuilder extends Config { + /** @inheritdoc + * + * The default value is 1234. + */ + var bar: Int = 1234 + } +} + """ + + def scaladocSettings = "" + + def testModel(root: Package) = () +} diff --git a/test/scaladoc/run/t5795.check b/test/scaladoc/run/t5795.check new file mode 100644 index 0000000000..d08ab619ed --- /dev/null +++ b/test/scaladoc/run/t5795.check @@ -0,0 +1,4 @@ +newSource:16: warning: Could not find any member to link for "Exception". + /** + ^ +Done. diff --git a/test/scaladoc/run/t5795.scala b/test/scaladoc/run/t5795.scala new file mode 100644 index 0000000000..767e4f1a72 --- /dev/null +++ b/test/scaladoc/run/t5795.scala @@ -0,0 +1,63 @@ +import scala.tools.nsc.doc.model._ +import scala.tools.partest.ScaladocModelTest + +object Test extends ScaladocModelTest { + + override def code = """ +/** + * Only the 'deprecated' tag should stay. + * + * @author + * @since + * @todo + * @note + * @see + * @version + * @deprecated + * @example + * @constructor + */ +object Test { + /** + * Only the 'throws' tag should stay. + * @param foo + * @param bar + * @param baz + * @return + * @throws Exception + * @tparam T + */ + def foo[T](foo: Any, bar: Any, baz: Any): Int = 1 +} + """ + + def scaladocSettings = "" + + def test(b: Boolean, text: => String): Unit = if (!b) println(text) + + def testModel(root: Package) = { + import access._ + val obj = root._object("Test") + val c = obj.comment.get + + test(c.authors.isEmpty, s"expected no authors, found: ${c.authors}") + test(!c.since.isDefined, s"expected no since tag, found: ${c.since}") + test(c.todo.isEmpty, s"expected no todos, found: ${c.todo}") + test(c.note.isEmpty, s"expected no note, found: ${c.note}") + test(c.see.isEmpty, s"expected no see, found: ${c.see}") + test(!c.version.isDefined, s"expected no version tag, found: ${c.version}") + // deprecated stays + test(c.deprecated.isDefined, s"expected deprecated tag, found none") + test(c.example.isEmpty, s"expected no example, found: ${c.example}") + test(!c.constructor.isDefined, s"expected no constructor tag, found: ${c.constructor}") + + val method = obj._method("foo") + val mc = method.comment.get + + test(mc.valueParams.isEmpty, s"expected empty value params, found: ${mc.valueParams}") + test(mc.typeParams.isEmpty, s"expected empty type params, found: ${mc.typeParams}") + test(!mc.result.isDefined, s"expected no result tag, found: ${mc.result}") + // throws stay + test(!mc.throws.isEmpty, s"expected an exception tag, found: ${mc.throws}") + } +} diff --git a/test/scaladoc/scalacheck/CommentFactoryTest.scala b/test/scaladoc/scalacheck/CommentFactoryTest.scala index ff64a25602..d30b78087c 100644 --- a/test/scaladoc/scalacheck/CommentFactoryTest.scala +++ b/test/scaladoc/scalacheck/CommentFactoryTest.scala @@ -24,8 +24,11 @@ class Factory(val g: Global, val s: doc.Settings) } } + def getComment(s: String): Comment = + parse(s, "", scala.tools.nsc.util.NoPosition, null) + def parseComment(s: String): Option[Inline] = - strip(parse(s, "", scala.tools.nsc.util.NoPosition, null)) + strip(getComment(s)) def createBody(s: String) = parse(s, "", scala.tools.nsc.util.NoPosition, null).body @@ -166,4 +169,19 @@ object Test extends Properties("CommentFactory") { } } + property("Empty parameter text should be empty") = { + // used to fail with + // body == Body(List(Paragraph(Chain(List(Summary(Text('\n'))))))) + factory.getComment( + """ +/** + * @deprecated + */ + """).deprecated match { + case Some(Body(l)) if l.isEmpty => true + case other => + println(other) + false + } + } } diff --git a/test/scaladoc/scalacheck/DeprecatedIndexTest.scala b/test/scaladoc/scalacheck/DeprecatedIndexTest.scala new file mode 100644 index 0000000000..4a5a2001d4 --- /dev/null +++ b/test/scaladoc/scalacheck/DeprecatedIndexTest.scala @@ -0,0 +1,50 @@ +import org.scalacheck._ +import org.scalacheck.Prop._ + +import scala.tools.nsc.doc +import scala.tools.nsc.doc.html.page.DeprecatedIndex +import java.net.{URLClassLoader, URLDecoder} + +object Test extends Properties("IndexScript") { + + def getClasspath = { + // these things can be tricky + // this test previously relied on the assumption that the current thread's classloader is an url classloader and contains all the classpaths + // does partest actually guarantee this? to quote Leonard Nimoy: The answer, of course, is no. + // this test _will_ fail again some time in the future. + // Footnote: java.lang.ClassCastException: org.apache.tools.ant.loader.AntClassLoader5 cannot be cast to java.net.URLClassLoader + val loader = Thread.currentThread.getContextClassLoader.asInstanceOf[URLClassLoader] + val paths = loader.getURLs.map(u => URLDecoder.decode(u.getPath)) + paths mkString java.io.File.pathSeparator + } + + val docFactory = { + val settings = new doc.Settings({Console.err.println(_)}) + settings.scaladocQuietRun = true + settings.nowarn.value = true + settings.classpath.value = getClasspath + val reporter = new scala.tools.nsc.reporters.ConsoleReporter(settings) + new doc.DocFactory(reporter, settings) + } + + val indexModelFactory = doc.model.IndexModelFactory + + def createDeprecatedScript(path: String) = + docFactory.makeUniverse(Left(List(path))) match { + case Some(universe) => { + val index = new DeprecatedIndex(universe, indexModelFactory.makeIndex(universe)) + Some(index) + } + case _ => + None + } + + property("deprecated-list page lists deprecated members") = { + createDeprecatedScript("test/scaladoc/resources/SI-4476.scala") match { + case Some(p) => + p.deprecatedEntries.find(_._1 == "A").isDefined && + p.deprecatedEntries.find(_._1 == "bar").isDefined + case None => false + } + } +} diff --git a/test/scaladoc/scalacheck/HtmlFactoryTest.scala b/test/scaladoc/scalacheck/HtmlFactoryTest.scala index 51633be440..6a6b1f8901 100644 --- a/test/scaladoc/scalacheck/HtmlFactoryTest.scala +++ b/test/scaladoc/scalacheck/HtmlFactoryTest.scala @@ -685,7 +685,7 @@ object Test extends Properties("HtmlFactory") { case node: scala.xml.Node => { val s = node.toString s.contains("<h6>Author:</h6>") && - s.contains("<p>The Only Author\n</p>") + s.contains("<p>The Only Author</p>") } case _ => false } @@ -699,7 +699,7 @@ object Test extends Properties("HtmlFactory") { val s = node.toString s.contains("<h6>Authors:</h6>") && s.contains("<p>The First Author</p>") && - s.contains("<p>The Second Author\n</p>") + s.contains("<p>The Second Author</p>") } case _ => false } diff --git a/test/scaladoc/scalacheck/IndexTest.scala b/test/scaladoc/scalacheck/IndexTest.scala index abc0e5da01..7dbd2103a6 100644 --- a/test/scaladoc/scalacheck/IndexTest.scala +++ b/test/scaladoc/scalacheck/IndexTest.scala @@ -71,7 +71,7 @@ object Test extends Properties("Index") { case None => false } } - property("browser contants a script element") = { + property("browser contains a script element") = { createIndex("src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala") match { case Some(index) => (index.browser \ "script").size == 1 @@ -86,4 +86,10 @@ object Test extends Properties("Index") { case None => false } } + property("index should report if there are deprecated members") = { + createIndex("test/scaladoc/resources/SI-4476.scala") match { + case Some(indexPage) => indexPage.index.hasDeprecatedMembers + case None => false + } + } } diff --git a/tools/binary-repo-lib.sh b/tools/binary-repo-lib.sh index 437c0a0c08..278804e30e 100755 --- a/tools/binary-repo-lib.sh +++ b/tools/binary-repo-lib.sh @@ -2,8 +2,8 @@ # # Library to push and pull binary artifacts from a remote repository using CURL. -remote_urlget="http://repo.typesafe.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap" -remote_urlpush="http://private-repo.typesafe.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap" +remote_urlget="https://dl.bintray.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap" +remote_urlpush="https://dl.bintray.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap" libraryJar="$(pwd)/lib/scala-library.jar" desired_ext=".desired.sha1" push_jar="$(pwd)/tools/push.jar" @@ -56,7 +56,7 @@ curlDownload() { if [[ "$OSTYPE" == *Cygwin* || "$OSTYPE" == *cygwin* ]]; then jar=$(cygpath -m $1) fi - http_code=$(curl --write-out '%{http_code}' --silent --fail --output "$jar" "$url") + http_code=$(curl --write-out '%{http_code}' --silent --fail -L --output "$jar" "$url") if (( $? != 0 )); then echo "Error downloading $jar: response code: $http_code" echo "$url" diff --git a/tools/scaladoc-compare b/tools/scaladoc-compare index 74fbfd1dd4..46e1b75a19 100755 --- a/tools/scaladoc-compare +++ b/tools/scaladoc-compare @@ -7,7 +7,7 @@ if [ $# -ne 2 ] then echo echo "scaladoc-compare will compare the scaladoc-generated pages in two different locations and output the diff" - echo "it's main purpose is to track changes to scaladoc and prevent updates that break things." + echo "its main purpose is to track changes to scaladoc and prevent updates that break things." echo echo "This script is meant to be used with the scaladoc -raw-output option, as it compares .html.raw files " echo "instead of markup-heavy .html files." diff --git a/versions.properties b/versions.properties index 096108a21f..a7ec8caedc 100644 --- a/versions.properties +++ b/versions.properties @@ -3,32 +3,41 @@ # via scala-dist-pom.xml and scala-library-all-pom.xml # when adding new properties that influence a release, # also add them to the update.versions mechanism in build.xml, -# which is used by scala-release-2.11.x in scala/jenkins-scripts +# which is used by the release script scripts/jobs/integrate/bootstrap + +# The scala version used for boostrapping. This has no impact on the final classfiles: +# there are two stages (locker and quick), so compiler and library are always built +# with themselves. Stability is ensured by building a third stage (strap). starr.version=2.11.6 -starr.use.released=1 # These are the versions of the modules that go with this release. # These properties are used during PR validation and in dbuild builds. -# e.g. 2.11.0-RC1, 2.11 +# The scala.binary.version determines how modules are resolved. For example, it +# determines which partest artifact is being used for running the tests. +# It has to be set in the following way: +# - After 2.x.0 is released, the binary version is 2.x. +# - During milestones and RCs, modules are cross-built against the full version. +# So the value is the full version (e.g. 2.12.0-M1). scala.binary.version=2.11 # e.g. 2.11.0-RC1, 2.11.0, 2.11.1-RC1, 2.11.1 # this defines the dependency on scala-continuations-plugin in scala-dist's pom scala.full.version=2.11.6 # external modules shipped with distribution, as specified by scala-library-all's pom -scala-xml.version.number=1.0.3 -scala-parser-combinators.version.number=1.0.3 +scala-xml.version.number=1.0.4 +scala-parser-combinators.version.number=1.0.4 scala-continuations-plugin.version.number=1.0.2 scala-continuations-library.version.number=1.0.2 -scala-swing.version.number=1.0.1 -akka-actor.version.number=2.3.4 +scala-swing.version.number=1.0.2 +akka-actor.version.number=2.3.10 actors-migration.version.number=1.1.0 jline.version=2.12.1 +scala-asm.version=5.0.4-scala-1 # external modules, used internally (not shipped) -partest.version.number=1.0.5 -scalacheck.version.number=1.11.4 +partest.version.number=1.0.7 +scalacheck.version.number=1.11.6 # TODO: modularize the compiler #scala-compiler-doc.version.number=1.0.0-RC1 |