From bd2f8a6a30f8c03d988aaf100f2dcb8e7986848e Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 17 Jul 2019 17:47:47 +0200 Subject: [PATCH] Fix #6872: Move dotty-semanticdb to the community build --- .drone.yml | 2 +- .gitmodules | 3 + build.sbt | 2 - community-build/community-projects/semanticdb | 1 + .../communitybuild/CommunityBuildTest.scala | 6 + .../test/scala/dotty/communitybuild/readme.md | 1 + project/Build.scala | 24 - semanticdb/input/build.sbt | 3 - semanticdb/input/project/build.properties | 1 - .../input/src/main/scala/example/Access.scala | 27 - .../src/main/scala/example/Advanced.scala | 38 - .../src/main/scala/example/Anonymous.scala | 18 - .../input/src/main/scala/example/Apply.scala | 9 - .../src/main/scala/example/BinaryOp.scala | 7 - .../input/src/main/scala/example/Case.scala | 12 - .../src/main/scala/example/Classes.scala | 56 - .../main/scala/example/DependantModule.scala | 9 - .../src/main/scala/example/DottyPredef.scala | 9 - .../input/src/main/scala/example/Empty.scala | 9 - .../src/main/scala/example/EmptyObject.scala | 3 - .../src/main/scala/example/Example.scala | 22 - .../src/main/scala/example/Example2.scala | 10 - .../src/main/scala/example/Exclude.scala | 4 - .../input/src/main/scala/example/Flags.scala | 23 - .../main/scala/example/IgnoredSymbol.scala | 8 - .../src/main/scala/example/Issue1749.scala | 11 - .../input/src/main/scala/example/Locals.scala | 8 - .../main/scala/example/MacroAnnotations.scala | 20 - .../src/main/scala/example/MethodUsages.scala | 33 - .../src/main/scala/example/Methods.scala | 38 - .../main/scala/example/MultiArguments.scala | 5 - .../input/src/main/scala/example/New.scala | 17 - .../src/main/scala/example/Objects.scala | 5 - .../src/main/scala/example/Overrides.scala | 4 - .../src/main/scala/example/Prefixes.scala | 33 - .../src/main/scala/example/SelfUse.scala | 5 - .../input/src/main/scala/example/Selfs.scala | 26 - .../src/main/scala/example/SemanticDoc.scala | 12 - .../input/src/main/scala/example/Super.scala | 9 - .../src/main/scala/example/Synthetic.scala | 46 - .../input/src/main/scala/example/Traits.scala | 14 - .../src/main/scala/example/TypeBug.scala | 15 - .../input/src/main/scala/example/Types.scala | 120 -- .../main/scala/example/TypesAnnotations.scala | 13 - .../input/src/main/scala/example/Vals.scala | 47 - .../src/main/scala/example/local-file.scala | 8 - semanticdb/readme.md | 50 - semanticdb/src/dotty/semanticdb/Main.scala | 101 -- semanticdb/src/dotty/semanticdb/Scala.scala | 292 ----- .../dotty/semanticdb/SemanticdbConsumer.scala | 1045 ----------------- .../src/dotty/semanticdb/SourceFile.scala | 71 -- .../semanticdb/TastyScalaFileInferrer.scala | 47 - semanticdb/src/dotty/semanticdb/Utils.scala | 83 -- semanticdb/test/dotty/semanticdb/MD5.scala | 29 - .../test/dotty/semanticdb/Semanticdbs.scala | 127 -- semanticdb/test/dotty/semanticdb/Tests.scala | 221 ---- semanticdb/test/tests/SimpleClass.scala | 3 - semanticdb/test/tests/SimpleDef.scala | 5 - 58 files changed, 12 insertions(+), 2858 deletions(-) create mode 160000 community-build/community-projects/semanticdb delete mode 100644 semanticdb/input/build.sbt delete mode 100644 semanticdb/input/project/build.properties delete mode 100644 semanticdb/input/src/main/scala/example/Access.scala delete mode 100644 semanticdb/input/src/main/scala/example/Advanced.scala delete mode 100644 semanticdb/input/src/main/scala/example/Anonymous.scala delete mode 100644 semanticdb/input/src/main/scala/example/Apply.scala delete mode 100644 semanticdb/input/src/main/scala/example/BinaryOp.scala delete mode 100644 semanticdb/input/src/main/scala/example/Case.scala delete mode 100644 semanticdb/input/src/main/scala/example/Classes.scala delete mode 100644 semanticdb/input/src/main/scala/example/DependantModule.scala delete mode 100644 semanticdb/input/src/main/scala/example/DottyPredef.scala delete mode 100644 semanticdb/input/src/main/scala/example/Empty.scala delete mode 100644 semanticdb/input/src/main/scala/example/EmptyObject.scala delete mode 100644 semanticdb/input/src/main/scala/example/Example.scala delete mode 100644 semanticdb/input/src/main/scala/example/Example2.scala delete mode 100644 semanticdb/input/src/main/scala/example/Exclude.scala delete mode 100644 semanticdb/input/src/main/scala/example/Flags.scala delete mode 100644 semanticdb/input/src/main/scala/example/IgnoredSymbol.scala delete mode 100644 semanticdb/input/src/main/scala/example/Issue1749.scala delete mode 100644 semanticdb/input/src/main/scala/example/Locals.scala delete mode 100644 semanticdb/input/src/main/scala/example/MacroAnnotations.scala delete mode 100644 semanticdb/input/src/main/scala/example/MethodUsages.scala delete mode 100644 semanticdb/input/src/main/scala/example/Methods.scala delete mode 100644 semanticdb/input/src/main/scala/example/MultiArguments.scala delete mode 100644 semanticdb/input/src/main/scala/example/New.scala delete mode 100644 semanticdb/input/src/main/scala/example/Objects.scala delete mode 100644 semanticdb/input/src/main/scala/example/Overrides.scala delete mode 100644 semanticdb/input/src/main/scala/example/Prefixes.scala delete mode 100644 semanticdb/input/src/main/scala/example/SelfUse.scala delete mode 100644 semanticdb/input/src/main/scala/example/Selfs.scala delete mode 100644 semanticdb/input/src/main/scala/example/SemanticDoc.scala delete mode 100644 semanticdb/input/src/main/scala/example/Super.scala delete mode 100644 semanticdb/input/src/main/scala/example/Synthetic.scala delete mode 100644 semanticdb/input/src/main/scala/example/Traits.scala delete mode 100644 semanticdb/input/src/main/scala/example/TypeBug.scala delete mode 100644 semanticdb/input/src/main/scala/example/Types.scala delete mode 100644 semanticdb/input/src/main/scala/example/TypesAnnotations.scala delete mode 100644 semanticdb/input/src/main/scala/example/Vals.scala delete mode 100644 semanticdb/input/src/main/scala/example/local-file.scala delete mode 100644 semanticdb/readme.md delete mode 100644 semanticdb/src/dotty/semanticdb/Main.scala delete mode 100644 semanticdb/src/dotty/semanticdb/Scala.scala delete mode 100644 semanticdb/src/dotty/semanticdb/SemanticdbConsumer.scala delete mode 100644 semanticdb/src/dotty/semanticdb/SourceFile.scala delete mode 100644 semanticdb/src/dotty/semanticdb/TastyScalaFileInferrer.scala delete mode 100644 semanticdb/src/dotty/semanticdb/Utils.scala delete mode 100644 semanticdb/test/dotty/semanticdb/MD5.scala delete mode 100644 semanticdb/test/dotty/semanticdb/Semanticdbs.scala delete mode 100644 semanticdb/test/dotty/semanticdb/Tests.scala delete mode 100644 semanticdb/test/tests/SimpleClass.scala delete mode 100644 semanticdb/test/tests/SimpleDef.scala diff --git a/.drone.yml b/.drone.yml index 5daf0744d8d0..0cb43a0aed2e 100644 --- a/.drone.yml +++ b/.drone.yml @@ -40,7 +40,7 @@ steps: depends_on: [ clone ] commands: - cp -R . /tmp/2/ && cd /tmp/2/ - - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test; dotty-semanticdb/compile; dotty-semanticdb/test:compile;sjsSandbox/run;sjsSandbox/test;sjsJUnitTests/test" + - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test ;sjsSandbox/run;sjsSandbox/test;sjsJUnitTests/test" - ./project/scripts/bootstrapCmdTests - name: community_build diff --git a/.gitmodules b/.gitmodules index 84dd7bd8061c..b91368c38612 100644 --- a/.gitmodules +++ b/.gitmodules @@ -47,3 +47,6 @@ [submodule "community-build/community-projects/xml-interpolator"] path = community-build/community-projects/xml-interpolator url = https://github.com/lampepfl/xml-interpolator.git +[submodule "community-build/community-projects/semanticdb"] + path = community-build/community-projects/semanticdb + url = https://github.com/lampepfl/dotty-semanticdb.git diff --git a/build.sbt b/build.sbt index 92703b167726..b413737b86e1 100644 --- a/build.sbt +++ b/build.sbt @@ -13,8 +13,6 @@ val `dotty-sbt-bridge-tests` = Build.`dotty-sbt-bridge-tests` val `dotty-language-server` = Build.`dotty-language-server` val `dotty-bench` = Build.`dotty-bench` val `dotty-bench-bootstrapped` = Build.`dotty-bench-bootstrapped` -val `dotty-semanticdb` = Build.`dotty-semanticdb` -val `dotty-semanticdb-input` = Build.`dotty-semanticdb-input` val `scala-library` = Build.`scala-library` val `scala-compiler` = Build.`scala-compiler` val `scala-reflect` = Build.`scala-reflect` diff --git a/community-build/community-projects/semanticdb b/community-build/community-projects/semanticdb new file mode 160000 index 000000000000..f34172a4e446 --- /dev/null +++ b/community-build/community-projects/semanticdb @@ -0,0 +1 @@ +Subproject commit f34172a4e4463b367003890eb7a04a7a06cfc3aa diff --git a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala index 09b3e36de5f3..073b33682365 100644 --- a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala +++ b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala @@ -183,6 +183,12 @@ class CommunityBuildTest { updateCommand = "update" ) + @Test def semanticdb = test( + project = "semanticdb", + testCommand = "test:compile", + updateCommand = "update" + ) + // TODO @oderky? It got broken by #5458 // @Test def pdbp = test( // project = "pdbp", diff --git a/community-build/test/scala/dotty/communitybuild/readme.md b/community-build/test/scala/dotty/communitybuild/readme.md index a4337d048b5d..f4954c95f80f 100644 --- a/community-build/test/scala/dotty/communitybuild/readme.md +++ b/community-build/test/scala/dotty/communitybuild/readme.md @@ -13,4 +13,5 @@ To add your project to the community build you can follow these steps: 2. Open a PR against this repo that: - Adds your project as a new git submodule + - `git submodule add https://github.com/lampepfl/XYZ.git community-build/community-projects/XYZ` - Adds a test in [CommunityBuildTest.scala](https://github.com/lampepfl/dotty/blob/master/src/test/scala/dotty/community-build/src/test/scala/dotty/communitybuild/CommunityBuildTest.scala) diff --git a/project/Build.scala b/project/Build.scala index 21ca977e6177..d24febb25340 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -335,18 +335,6 @@ object Build { dottyLib + File.pathSeparator + findLib(attList, "scala-library-") } - lazy val semanticdbSettings = Seq( - baseDirectory in (Compile, run) := baseDirectory.value / "..", - baseDirectory in Test := baseDirectory.value / "..", - unmanagedSourceDirectories in Test += baseDirectory.value / "input" / "src" / "main" / "scala", - scalacOptions in Test ++= Seq("-Yno-inline"), - libraryDependencies ++= List( - ("org.scalameta" %% "semanticdb" % "4.0.0").withDottyCompat(scalaVersion.value), - "com.novocode" % "junit-interface" % "0.11", - "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0" - ) - ) - def dottyDocSettings(implicit mode: Mode) = Seq( baseDirectory in (Compile, run) := baseDirectory.value / "..", baseDirectory in Test := baseDirectory.value / "..", @@ -957,13 +945,6 @@ object Build { lazy val `dotty-bench` = project.in(file("bench")).asDottyBench(NonBootstrapped) lazy val `dotty-bench-bootstrapped` = project.in(file("bench")).asDottyBench(Bootstrapped) - lazy val `dotty-semanticdb` = project.in(file("semanticdb")).asDottySemanticdb(Bootstrapped) - lazy val `dotty-semanticdb-input` = project.in(file("semanticdb/input")).settings( - scalaVersion := "2.12.7", - scalacOptions += "-Yrangepos", - addCompilerPlugin("org.scalameta" % "semanticdb-scalac" % "4.0.0" cross CrossVersion.full) - ) - // Depend on dotty-library so that sbt projects using dotty automatically // depend on the dotty-library lazy val `scala-library` = project. @@ -1246,11 +1227,6 @@ object Build { settings(commonBenchmarkSettings). enablePlugins(JmhPlugin) - def asDottySemanticdb(implicit mode: Mode): Project = project.withCommonSettings. - aggregate(`dotty-semanticdb-input`). - dependsOn(dottyCompiler). - settings(semanticdbSettings) - def asDist(implicit mode: Mode): Project = project. enablePlugins(PackPlugin). withCommonSettings. diff --git a/semanticdb/input/build.sbt b/semanticdb/input/build.sbt deleted file mode 100644 index dc3665d9cda8..000000000000 --- a/semanticdb/input/build.sbt +++ /dev/null @@ -1,3 +0,0 @@ -scalaVersion := "2.12.7" -scalacOptions += "-Yrangepos" -addCompilerPlugin("org.scalameta" % "semanticdb-scalac" % "4.0.0" cross CrossVersion.full) diff --git a/semanticdb/input/project/build.properties b/semanticdb/input/project/build.properties deleted file mode 100644 index 0cd8b07982e1..000000000000 --- a/semanticdb/input/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version=1.2.3 diff --git a/semanticdb/input/src/main/scala/example/Access.scala b/semanticdb/input/src/main/scala/example/Access.scala deleted file mode 100644 index eba966f117e4..000000000000 --- a/semanticdb/input/src/main/scala/example/Access.scala +++ /dev/null @@ -1,27 +0,0 @@ -package example - -class Access { - private def m1 = ??? - private[this] def m2 = ??? - private[Access] def m3 = ??? - protected def m4 = ??? - protected[this] def m5 = ??? - protected[example] def m6 = ??? - def m7 = ??? - - private val mv1 = ??? - private[this] val mv2 = ??? - private[Access] val mv3 = ??? - protected val mv4 = ??? - protected[this] val mv5 = ??? - protected[example] val mv6 = ??? - val mv7 = ??? - - private var mr1 = ??? - private[this] var mr2 = ??? - private[Access] var mr3 = ??? - protected var mr4 = ??? - protected[this] var mr5 = ??? - protected[example] var mr6 = ??? - var mr7 = ??? -} diff --git a/semanticdb/input/src/main/scala/example/Advanced.scala b/semanticdb/input/src/main/scala/example/Advanced.scala deleted file mode 100644 index b9aa9c0c8bbc..000000000000 --- a/semanticdb/input/src/main/scala/example/Advanced.scala +++ /dev/null @@ -1,38 +0,0 @@ -package example - -import scala.language.{existentials, higherKinds=>h} -import scala.language.reflectiveCalls - -class AdvC[T] { - def t: T = ??? -} - -class Structural { - def s1: { val x: Int } = ??? - def s2 = new { val x: Int = ??? } - def s3 = new { def m(x: Int): Int = ??? } -} - -class Existential { - def e1: List[_] = ??? -} - -class AdvD[CC[B]] extends AdvC[CC[B]] - -object AdvTest { - val s = new Structural - val s1 = s.s1 - val s2 = s.s2 - val s3 = s.s3 - - val e = new Existential - val e1 = e.e1 - val e1x = e.e1.head - locally { - (??? : Any) match { - case e3: List[_] => - val e3x = e3.head - () - } - } -} diff --git a/semanticdb/input/src/main/scala/example/Anonymous.scala b/semanticdb/input/src/main/scala/example/Anonymous.scala deleted file mode 100644 index e807429f536c..000000000000 --- a/semanticdb/input/src/main/scala/example/Anonymous.scala +++ /dev/null @@ -1,18 +0,0 @@ -package example -import scala.language.higherKinds - -class Anonymous { - this: Anonymous => - - def m1[T[_], B] = ??? - def m2: Map[_, List[_]] = ??? - locally { - ??? match { case _: List[_] => } - } - locally { - val x: Int => Int = _ => ??? - } - - trait Foo - var x = new Foo {} -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/Apply.scala b/semanticdb/input/src/main/scala/example/Apply.scala deleted file mode 100644 index 72f84468ba31..000000000000 --- a/semanticdb/input/src/main/scala/example/Apply.scala +++ /dev/null @@ -1,9 +0,0 @@ -package example - -class TestApply { - object Foo { - def apply(x: Int) : Int = x - } - val z = Foo(1) - val y = Foo.apply(1) -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/BinaryOp.scala b/semanticdb/input/src/main/scala/example/BinaryOp.scala deleted file mode 100644 index 054c87f2b62f..000000000000 --- a/semanticdb/input/src/main/scala/example/BinaryOp.scala +++ /dev/null @@ -1,7 +0,0 @@ -package example - -class BinaryOp { - val y = 1 #:: 2 #:: Stream.empty[Int] - val x = 1 :: 2 :: 3 :: Nil - val z = 1 + 2 -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/Case.scala b/semanticdb/input/src/main/scala/example/Case.scala deleted file mode 100644 index 6aebcb750088..000000000000 --- a/semanticdb/input/src/main/scala/example/Case.scala +++ /dev/null @@ -1,12 +0,0 @@ -package example - -class CaseTest { - def foo (x: Option[Int]) : Int = - x match { - case y @ Some(x) => x - case None => 0 - } -} - -case class CaseClass(x: Int) -case object CaseObject \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/Classes.scala b/semanticdb/input/src/main/scala/example/Classes.scala deleted file mode 100644 index 1d0770e805f3..000000000000 --- a/semanticdb/input/src/main/scala/example/Classes.scala +++ /dev/null @@ -1,56 +0,0 @@ -package example - -class CDep[X] -class CDependenat[X /* This is a comment /* and a nested comment -*/*/](var x1: CDep[X]) -class CVarArg(var x1 : Int) - - -class CDefaultWrapper { - val glob = 3 - class Cdefault(val x1: Int = glob) -} -class C1(val x1: Int) extends AnyVal - -class C2(val x2: Int) extends AnyVal -object C2 - -case class C3[Y ](x: Int) - -case class C4(x: Int) -object C4 { - val foo: Int = 4 -} - -object M { - implicit class C5(x: Int) -} - -case class C6(private val x: Int) - -class C7(x: Int) - -class C8(private[this] val x: Int) - -class C9(private[this] var x: Int) - -object N { - val anonClass = new C7(42) { - val local = ??? - } - val anonFun = List(1).map { i => - val local = 2 - local + 2 - } - - val otheranon = { - var a = 1 - a - } - - val lastanon = { - val a = new CVarArg(4) - a.x1 = 8 - a.x1 - } -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/DependantModule.scala b/semanticdb/input/src/main/scala/example/DependantModule.scala deleted file mode 100644 index 104a0579fec0..000000000000 --- a/semanticdb/input/src/main/scala/example/DependantModule.scala +++ /dev/null @@ -1,9 +0,0 @@ -package example - -class DepTemp { - -} - -abstract class DepAdvD[CC[X[C] <: B], X[Z], C] extends DepTemp { -val foo: List[Option[Option[X[C]]]] -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/DottyPredef.scala b/semanticdb/input/src/main/scala/example/DottyPredef.scala deleted file mode 100644 index 4f9215283fc2..000000000000 --- a/semanticdb/input/src/main/scala/example/DottyPredef.scala +++ /dev/null @@ -1,9 +0,0 @@ -package example - -class PredefsDotty { - locally { - val x: Int => Int = _ => ??? - } - assert(true) - assert(false, "bonjour") -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/Empty.scala b/semanticdb/input/src/main/scala/example/Empty.scala deleted file mode 100644 index eac850705562..000000000000 --- a/semanticdb/input/src/main/scala/example/Empty.scala +++ /dev/null @@ -1,9 +0,0 @@ -package example - -class AdvA { - def b: AdvB = ??? -} - -class AdvB { - def a: AdvA = ??? -} diff --git a/semanticdb/input/src/main/scala/example/EmptyObject.scala b/semanticdb/input/src/main/scala/example/EmptyObject.scala deleted file mode 100644 index 58773e9bd7eb..000000000000 --- a/semanticdb/input/src/main/scala/example/EmptyObject.scala +++ /dev/null @@ -1,3 +0,0 @@ -package example - -object EmptyObject {} diff --git a/semanticdb/input/src/main/scala/example/Example.scala b/semanticdb/input/src/main/scala/example/Example.scala deleted file mode 100644 index 682c0ba7cea6..000000000000 --- a/semanticdb/input/src/main/scala/example/Example.scala +++ /dev/null @@ -1,22 +0,0 @@ -package example - -class Example { - val a: String = "1" - def a( - x: Int - ): String = - x.toString - def a( - x: Int, - y: Int - ): String = - a( - x + - y - ) - var b = 4 -} - -class ExampleInit { - -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/Example2.scala b/semanticdb/input/src/main/scala/example/Example2.scala deleted file mode 100644 index 1135020e76db..000000000000 --- a/semanticdb/input/src/main/scala/example/Example2.scala +++ /dev/null @@ -1,10 +0,0 @@ -package example - -import scala.concurrent.Future - -object OExample { self => - def main(args: Array[String]): Unit = { - println(1) - } - val x = scala.reflect.classTag[Int] -} diff --git a/semanticdb/input/src/main/scala/example/Exclude.scala b/semanticdb/input/src/main/scala/example/Exclude.scala deleted file mode 100644 index 35e085572ff5..000000000000 --- a/semanticdb/input/src/main/scala/example/Exclude.scala +++ /dev/null @@ -1,4 +0,0 @@ -package example - -// This class should be excluded by semanticdb. -class Exclude diff --git a/semanticdb/input/src/main/scala/example/Flags.scala b/semanticdb/input/src/main/scala/example/Flags.scala deleted file mode 100644 index dd96fa6621f8..000000000000 --- a/semanticdb/input/src/main/scala/example/Flags.scala +++ /dev/null @@ -1,23 +0,0 @@ - -package object example { - private lazy val x = 1 - /*protected implicit var y: Int = 2 - def z(pp: Int) = 3 - def m[TT] = ??? - abstract class Cex[+T, -U, V](x: T, y: U, z: V) { - def this() = this(???, ???, ???) - def w: Int - } - type T1 = Int - type T2[T] = S[T] - type U <: Int - type V >: Int - case object X - final class Y - sealed trait Z - class AA(x: Int, val y: Int, var z: Int) - class S[@specialized T] - val List(xs1) = ??? - ??? match { case List(xs2) => ??? } - ??? match { case _: List[t] => ??? }*/ -} diff --git a/semanticdb/input/src/main/scala/example/IgnoredSymbol.scala b/semanticdb/input/src/main/scala/example/IgnoredSymbol.scala deleted file mode 100644 index 13d58ac4132f..000000000000 --- a/semanticdb/input/src/main/scala/example/IgnoredSymbol.scala +++ /dev/null @@ -1,8 +0,0 @@ -package example - -class IgnoredTest { - val _ = 2 - def foo(x: Int): Unit = { - val _ = x - } -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/Issue1749.scala b/semanticdb/input/src/main/scala/example/Issue1749.scala deleted file mode 100644 index 66f35aa00c88..000000000000 --- a/semanticdb/input/src/main/scala/example/Issue1749.scala +++ /dev/null @@ -1,11 +0,0 @@ -// See https://github.com/scalameta/scalameta/issues/1749 -package example - -import scala.math.Ordered.orderingToOrdered - -class Issue1749 { - val x1 = 42 - val x2 = 42 - (x1, x1) - .compare((x2, x2)) -} diff --git a/semanticdb/input/src/main/scala/example/Locals.scala b/semanticdb/input/src/main/scala/example/Locals.scala deleted file mode 100644 index 308a1e713846..000000000000 --- a/semanticdb/input/src/main/scala/example/Locals.scala +++ /dev/null @@ -1,8 +0,0 @@ -package example - -object Test { - val xs = { - val x = 42 - List(x) - } -} diff --git a/semanticdb/input/src/main/scala/example/MacroAnnotations.scala b/semanticdb/input/src/main/scala/example/MacroAnnotations.scala deleted file mode 100644 index 50f8576ecf6f..000000000000 --- a/semanticdb/input/src/main/scala/example/MacroAnnotations.scala +++ /dev/null @@ -1,20 +0,0 @@ -/* -// This text is deactivated for now as macro annotations require to enable -// macro paradise - -package example - - -import scala.annotation.StaticAnnotation -import scala.annotation.compileTimeOnly -import scala.language.experimental.macros - -@compileTimeOnly("enable macro paradise to expand macro annotations") -class MacroAnnotation extends StaticAnnotation { - def macroTransform(annottees: Any*): Any = ??? -} - -@MacroAnnotation -class MacroAnnotations -object MacroAnnotations -*/ \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/MethodUsages.scala b/semanticdb/input/src/main/scala/example/MethodUsages.scala deleted file mode 100644 index ea0b9e93713f..000000000000 --- a/semanticdb/input/src/main/scala/example/MethodUsages.scala +++ /dev/null @@ -1,33 +0,0 @@ -package example - -class MethodUsages { - val m = new Methods[Int] - m.m1 - m.m2() - m.m3(0) - m.m4(0)(0) - m.m5("") - m.m5(0) - m.m6(0) - m.m6(new m.List[Int]) - m.m6(Nil) - m.m7a(m, new m.List[Int]) - m.m7b(new m.List[Int]) - m.`m8().`() - m.m9(null) - m.m10(null) - m.m11(Predef) - m.m11(OExample) - m.m12a(null) - m.m12b(null) - m.m13(0) - m.m15(0) - m.m16(0) - m.m16(0) - m.m17.m() - m.m17(1) - m.m17("") - m.m18.m() - m.m18(1) - m.m18("") -} diff --git a/semanticdb/input/src/main/scala/example/Methods.scala b/semanticdb/input/src/main/scala/example/Methods.scala deleted file mode 100644 index 97af95b3c9c2..000000000000 --- a/semanticdb/input/src/main/scala/example/Methods.scala +++ /dev/null @@ -1,38 +0,0 @@ -package example - -import scala.math.Ordering -import scala.language.existentials - -class Methods[T] { - class List[T] - type AList[T] = List[T] - def m1 = ??? - def m2() = ??? - def m3(x: Int) = ??? - def m4(x: Int)(y: Int) = ??? - def m5(x: String) = ??? - def m5(x: Int) = ??? - def m6(x: Int) = ??? - def m6(x: List[T]) = ??? - def m6(x: scala.List[T]) = ??? - def m7a[U: Ordering](c: Methods[T], l: List[U]) = ??? - def m7b[U <: T](l: List[U]) = ??? - def `m8().`() = ??? - class `m9().` - def m9(x: `m9().`) = ??? - def m10(x: AList[T]) = ??? - def m11(x: Predef.type) = ??? - def m11(x: OExample.type) = ??? - def m12a(x: {}) = ??? - def m12b(x: { val x: Int }) = ??? - def m13(x: Int @unchecked) = ??? - def m15(x: => Int) = ??? - def m16(x: Int*) = ??? - object m17 { def m() = ??? } - def m17(a: Int) = ??? - def m17(b: String) = ??? - val m18 = m17 - def m18(a: Int) = ??? - def m18(b: String) = ??? - def m19(x: Int, y: Int = 2)(z: Int = 3) = ??? -} diff --git a/semanticdb/input/src/main/scala/example/MultiArguments.scala b/semanticdb/input/src/main/scala/example/MultiArguments.scala deleted file mode 100644 index 88d61b83585a..000000000000 --- a/semanticdb/input/src/main/scala/example/MultiArguments.scala +++ /dev/null @@ -1,5 +0,0 @@ -package example - -class Multiple { - def m19(x: Int)(z: Int = 3) = ??? -} diff --git a/semanticdb/input/src/main/scala/example/New.scala b/semanticdb/input/src/main/scala/example/New.scala deleted file mode 100644 index 77f32b0a7c33..000000000000 --- a/semanticdb/input/src/main/scala/example/New.scala +++ /dev/null @@ -1,17 +0,0 @@ -package example - -class Bonjour() { -} - -class Bonjour2(val x:Int) { - def this(x:String) = this(2) -} - -class TestNew extends C { - val b = new B - val c = new Bonjour - val d = new Bonjour() - val e = new Bonjour2(2) - val f = new Bonjour2("a") - val _ = f.x -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/Objects.scala b/semanticdb/input/src/main/scala/example/Objects.scala deleted file mode 100644 index 69fba5dfed3c..000000000000 --- a/semanticdb/input/src/main/scala/example/Objects.scala +++ /dev/null @@ -1,5 +0,0 @@ -package example - -object X { - object Y -} diff --git a/semanticdb/input/src/main/scala/example/Overrides.scala b/semanticdb/input/src/main/scala/example/Overrides.scala deleted file mode 100644 index 3d13cf4823d8..000000000000 --- a/semanticdb/input/src/main/scala/example/Overrides.scala +++ /dev/null @@ -1,4 +0,0 @@ -package example - -trait OveA { def foo: Int } -class OveB() extends OveA { def foo: Int = 2 } diff --git a/semanticdb/input/src/main/scala/example/Prefixes.scala b/semanticdb/input/src/main/scala/example/Prefixes.scala deleted file mode 100644 index 10daaede1937..000000000000 --- a/semanticdb/input/src/main/scala/example/Prefixes.scala +++ /dev/null @@ -1,33 +0,0 @@ -package example - -class PrefC { - type T - def m1: T = ??? - - object N { - type U - } - def k1: N.U = ??? -} - -object PrefM { - type T - def n1: T = ??? -} - -object PrefO extends PrefC { - def o1: T = ??? -} - -object PrefTest { - val c: PrefC = ??? - def m2: c.T = ??? - def k2: c.N.U = ??? - import c.N._ - def k3: U = ??? - - def n2: PrefM.T = ??? - - import PrefM._ - def n3: T = ??? -} diff --git a/semanticdb/input/src/main/scala/example/SelfUse.scala b/semanticdb/input/src/main/scala/example/SelfUse.scala deleted file mode 100644 index db6ee485e586..000000000000 --- a/semanticdb/input/src/main/scala/example/SelfUse.scala +++ /dev/null @@ -1,5 +0,0 @@ -package example - -class SelfUse extends B { a : B => -val c = a.b -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/Selfs.scala b/semanticdb/input/src/main/scala/example/Selfs.scala deleted file mode 100644 index 6226250d5452..000000000000 --- a/semanticdb/input/src/main/scala/example/Selfs.scala +++ /dev/null @@ -1,26 +0,0 @@ -package example - -class B { - val b = 4 -} - -class AC1 extends B { self => -} - -class AC2 extends B { self: B => -} - -abstract class AC3 extends B { self: B with Int => -} - -class AC4 extends B { a => -} - -class AC5 extends B { a : B => -} - -class AC6 extends B { this: B => -} - -abstract class AC7 { a: B => -} diff --git a/semanticdb/input/src/main/scala/example/SemanticDoc.scala b/semanticdb/input/src/main/scala/example/SemanticDoc.scala deleted file mode 100644 index 56e19d4118c7..000000000000 --- a/semanticdb/input/src/main/scala/example/SemanticDoc.scala +++ /dev/null @@ -1,12 +0,0 @@ -package example - -abstract class Ctest(val xp: Int, val xe : AnyRef) { - val xm: Int = ??? - val xam: Int - private[this] val xlm: Int = ??? - def m = { - val xl: Int = ??? - type S = { val xs: Int } - type E = xe.type - } -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/Super.scala b/semanticdb/input/src/main/scala/example/Super.scala deleted file mode 100644 index c052b9113769..000000000000 --- a/semanticdb/input/src/main/scala/example/Super.scala +++ /dev/null @@ -1,9 +0,0 @@ -package example - -class SuperA { - def a(x:Int) = x -} - -class SuperB extends SuperA { - override def a(x:Int) = super.a(x) -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/Synthetic.scala b/semanticdb/input/src/main/scala/example/Synthetic.scala deleted file mode 100644 index c0aaea853eff..000000000000 --- a/semanticdb/input/src/main/scala/example/Synthetic.scala +++ /dev/null @@ -1,46 +0,0 @@ -package example - -class Synthetic { - List(1).map(_ + 2) - Array.empty[Int].headOption - "fooo".stripPrefix("o") - - // See https://github.com/scalameta/scalameta/issues/977 - val Name = "name:(.*)".r - val x #:: xs = Stream(1, 2) - val Name(name) = "name:foo" - 1 #:: 2 #:: Stream.empty - - val lst = 1 #:: 2 #:: Stream.empty - lst + "foo" - - for (x <- 1 to 10; y <- 0 until 10) println(x -> x) - for (i <- 1 to 10; j <- 0 until 10) yield (i, j) - for (i <- 1 to 10; j <- 0 until 10 if i % 2 == 0) yield (i, j) - - object s { - def apply() = 2 - s() - s.apply() - case class Bar() - Bar() - null.asInstanceOf[Int => Int](2) - } - - class J[T: Manifest] { val arr = Array.empty[T] } - - class F - implicit val ordering: Ordering[F] = ??? - val f: Ordered[F] = new F - - import scala.concurrent.ExecutionContext.Implicits.global - for { - a <- scala.concurrent.Future.successful(1) - b <- scala.concurrent.Future.successful(2) - } println(a) - for { - a <- scala.concurrent.Future.successful(1) - b <- scala.concurrent.Future.successful(2) - if a < b - } yield a -} diff --git a/semanticdb/input/src/main/scala/example/Traits.scala b/semanticdb/input/src/main/scala/example/Traits.scala deleted file mode 100644 index fe857fbf7be3..000000000000 --- a/semanticdb/input/src/main/scala/example/Traits.scala +++ /dev/null @@ -1,14 +0,0 @@ -package example - -trait T { - def x = 2 -} - -sealed trait U -object U { - def u: U = new U {} -} - -class C -trait V { self: C => -} diff --git a/semanticdb/input/src/main/scala/example/TypeBug.scala b/semanticdb/input/src/main/scala/example/TypeBug.scala deleted file mode 100644 index 9b8226502269..000000000000 --- a/semanticdb/input/src/main/scala/example/TypeBug.scala +++ /dev/null @@ -1,15 +0,0 @@ -package example - -import scala.language.existentials -import scala.language.higherKinds - -object TypBug { - class M { - def m: Int = ??? - } - class C extends M { - case class RepeatedType(s: String*) { - def m1(x: Int*): Int = s.length - } - } -} diff --git a/semanticdb/input/src/main/scala/example/Types.scala b/semanticdb/input/src/main/scala/example/Types.scala deleted file mode 100644 index 904da9dbce76..000000000000 --- a/semanticdb/input/src/main/scala/example/Types.scala +++ /dev/null @@ -1,120 +0,0 @@ -package example - -import scala.language.existentials -import scala.language.higherKinds - -class TypeM { - def m: Int = ??? -} - -class TypeC extends TypeM { - val superType = super[TypeM].m -} - -class TypB - -class TypC - -class TypP { - class C - class X - val x = new X -} - -class TypT { - class C - class X - val x = new X -} - -object TypTest { - class M { - def m: Int = ??? - } - - trait N { - def n: Int = ??? - } - - class B { - def x:Int = 4 - } - - class C extends M { - val p = new TypP - val x = p.x - - val typeRef1: C = ??? - val typeRef2: p.C = ??? - val typeRef3: TypT#C = ??? - val typeRef4: List[Int] = ??? - - val singleType1: x.type = ??? - val singleType2: p.x.type = ??? - val Either = scala.util.Either - - val thisType1: this.type = ??? - val thisType2: C.this.type = ??? - - val superType1 = super.m - val superType2 = super[M].m - val superType3 = C.super[M].m - - val compoundType1: { def k: Int } = ??? - val compoundType2: M with N = ??? - val compoundType3: M with N { def k: Int } = ??? - val compoundType4 = new { def k: Int = ??? } - val compoundType5 = new M with N - val compoundType6 = new M with N { def k: Int = ??? } - - val existentialType2: List[_] = ??? - val existentialType3 = Class.forName("foo.Bar") - val existentialType4 = Class.forName("foo.Bar") - - def typeLambda1[M[_]] = ??? - typeLambda1[({ type L[T] = List[T] })#L] - - object ClassInfoType1 - class ClassInfoType2 extends B { override def x = 42 } - trait ClassInfoType3[T] - - object MethodType { - def x1: Int = ??? - def x2: Int = ??? - def m3: Int = ??? - def m4(): Int = ??? - def m5(x: Int): Int = ??? - def m6[T](x: T): T = ??? - } - - object ByNameType { - def m1(x: => Int): Int = ??? - } - - case class RepeatedType(s: String*) { - def m1(x: Int*): Int = s.length - } - - object TypeType { - type T1 - def m2[T2 >: C <: C] = ??? - def m3[M3[_]] = ??? - type T4 = C - type T5[U] = U - } - } - - object Literal { - final val int = 1 - final val long = 1L - final val float = 1f - final val double = 2d - final val nil = null - final val char = 'a' - final val string = "a" - final val bool = true - final val unit = () - final val javaEnum = java.nio.file.LinkOption.NOFOLLOW_LINKS - final val clazzOf = classOf[Option[Int]] - } -} \ No newline at end of file diff --git a/semanticdb/input/src/main/scala/example/TypesAnnotations.scala b/semanticdb/input/src/main/scala/example/TypesAnnotations.scala deleted file mode 100644 index c4ef702686fc..000000000000 --- a/semanticdb/input/src/main/scala/example/TypesAnnotations.scala +++ /dev/null @@ -1,13 +0,0 @@ -package example - -import scala.language.existentials -import scala.language.higherKinds - -class ann[T](x: T) extends scala.annotation.StaticAnnotation -class ann1 extends scala.annotation.StaticAnnotation -class ann2 extends scala.annotation.StaticAnnotation - -object TypTestAnnots { - val annType1: T @ann(42) = ??? - val annType2: T @ann1 @ann2 = ??? -} diff --git a/semanticdb/input/src/main/scala/example/Vals.scala b/semanticdb/input/src/main/scala/example/Vals.scala deleted file mode 100644 index 64e8026448bc..000000000000 --- a/semanticdb/input/src/main/scala/example/Vals.scala +++ /dev/null @@ -1,47 +0,0 @@ -package example - -abstract class Vals(p: Int, val xp: Int, var yp: Int) { - val xm: Int = ??? - val xam: Int - private[this] val xlm: Int = ??? - lazy val xzm: Int = ??? - private[this] lazy val xzlm: Int = ??? - final val xfm: Int = ??? - implicit val xim: Int = ??? - var ym: Int = ??? - var yam: Int - private[this] var ylm: Int = ??? - // NOTE: lazy not allowed here. Only vals can be lazy - // lazy var xzm: Int = ??? - // private[this] lazy var yzlm: Int = ??? - final var yfm: Int = ??? - implicit var yim: Int = ??? - def m = { - val xl: Int = ??? - lazy val xzl: Int = ??? - // NOTE: local values cannot be final - // final val xfl: Int = ??? - implicit val xil: Int = ??? - var yl: Int = ??? - // NOTE: lazy not allowed here. Only vals can be lazy - // lazy var yzl: Int = ??? - // NOTE: local variables cannot be final - // final var yfl: Int = ??? - implicit var yil: Int = ??? - yl = xl + yl - println(xzl) - yil = xil + yil - } - println(xzlm) - ylm = xlm + ylm -} - -object ValUsages { - val v: Vals = ??? - v.yp = v.xp + v.yp - v.ym = v.xm + v.ym - v.yam = v.xam + v.yam - println(v.xzm) - v.yfm = v.xfm + v.yfm - v.yim = v.xim + v.yim -} diff --git a/semanticdb/input/src/main/scala/example/local-file.scala b/semanticdb/input/src/main/scala/example/local-file.scala deleted file mode 100644 index ea699bdfff57..000000000000 --- a/semanticdb/input/src/main/scala/example/local-file.scala +++ /dev/null @@ -1,8 +0,0 @@ -package example - -class `local-file` { - locally { - val local = 42 - local + 4 - } -} diff --git a/semanticdb/readme.md b/semanticdb/readme.md deleted file mode 100644 index f93d37a3d009..000000000000 --- a/semanticdb/readme.md +++ /dev/null @@ -1,50 +0,0 @@ -# SemanticDB - -To run the tests use two terminals. In the first terminal compile the -`semanticdb/input` project whenever sources change in -`semanticdb/input/src/main/scala/**.scala`. - -``` -cd semanticdb/input -sbt -> compile -``` - -In the second terminal, run `sbt dotty-semanticdb/test` from the main dotty -build - -``` -sbt -> dotty-semanticdb/test -``` - -The tests assert that the TASTy to SemanticDB converter produces the same output -as the semanticdb-scalac compiler plugin. Test failures result in diffs like -this - -```diff -Test dotty.semanticdb.Tests.testExample failed: java.lang.AssertionError: ---- tasty -+++ scala2 --class Example { -- val a: String = "1" -+class Example /*example/Example#*/ { -+ val a /*example/Example#a.*/ : String /*scala/Predef.String#*/ = "1" -``` - -The lines starting with `-` are the output from the TASTy converter and the -lines starting with `+` are the output from the semanticdb-scalac compiler -plugin. - -Once the TASTy converter is updated to emit correct `SymbolOccurrence` -(https://scalameta.org/docs/semanticdb/specification.html#symboloccurrence) then -the "tasty" output should become identical to "scala2" and include inline -comments `class Example /* pkg/Example# */`. The inline comments are read as: -"the symbol `pkg/Example#` was resolved next to the class name `Example`". - -The spec for SemanticDB symbols can be found here: - -- Scala symbols: - https://scalameta.org/docs/semanticdb/specification.html#scala-symbol -- Java symbols: - https://scalameta.org/docs/semanticdb/specification.html#java-symbol diff --git a/semanticdb/src/dotty/semanticdb/Main.scala b/semanticdb/src/dotty/semanticdb/Main.scala deleted file mode 100644 index b3a47d5becb8..000000000000 --- a/semanticdb/src/dotty/semanticdb/Main.scala +++ /dev/null @@ -1,101 +0,0 @@ -package dotty.semanticdb - -import scala.tasty.file._ -import scala.NotImplementedError - -import dotty.tools.dotc.Driver -import dotty.tools.dotc.reporting.Reporter - -import java.io.File -import java.nio.file._ - -object Main { - val userHome = System.getProperty("user.home") - val classpaths = - userHome + "/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.12.8.jar" :: - "out/bootstrap/dotty-library-bootstrapped/scala-0.12/dotty-library_0.12-0.12.0-bin-SNAPSHOT.jar" :: Nil - - val help = """Usage semanticdb [options] [file] - |Generate semanticdb's information related to the source file [file] - |Options are: - | -h,--help Show help - | -o , --out Place the output into (default: out.semanticdb) - | -t , --temp Use as the temp directory to store build artifacts - """.stripMargin - - type CliArgs = Map[String, String] - - def parseArguments(args: Array[String]): Option[CliArgs] = { - val optRegex = "$-.*".r - def nextArgument(optionMap: CliArgs, args: List[String]): Option[CliArgs] = args match { - case "--out" :: file :: tail => nextArgument(optionMap + ("out" -> file), tail) - case "-o" :: file :: tail => nextArgument(optionMap + ("out" -> file), tail) - case "--help" :: tail => nextArgument(optionMap + ("help" -> ""), tail) - case "-h" :: tail => nextArgument(optionMap + ("help" -> ""), tail) - case "--classpath" :: folder :: tail => nextArgument(optionMap + ("classpath" -> folder), tail) - case "-c" :: folder :: tail => nextArgument(optionMap + ("classpath" -> folder), tail) - case optRegex(_) :: _=> None - case file :: tail => nextArgument(optionMap + ("input" -> file), tail) - case Nil => Some(optionMap) - } - - nextArgument(Map(), args.toList) match { - case Some(args : CliArgs) => { - var cleanedArgs = args - cleanedArgs += "out" -> cleanedArgs.getOrElse("out", "out.semanticdb") - if (cleanedArgs.contains("help") || !cleanedArgs.contains("input")) { - None - } else { - cleanedArgs += "classpath" -> cleanedArgs.getOrElse("classpath", Files.createTempDirectory("semanticdb").toString) - val tempFolder = new File(cleanedArgs("classpath")); - if (!tempFolder.exists()){ - tempFolder.mkdir(); - } - Some(cleanedArgs) - } - } - case None => None - } - } - - def compile(cliArgs : CliArgs) : Reporter - = { - val driver = new Driver - val compilerParams : List[String] = - "-classpath" :: classpaths.mkString(":") :: - "-Yno-inline" :: - "-d" :: cliArgs("classpath") :: - cliArgs("input") :: - Nil - - driver.process(compilerParams.toArray) - } - - - def main(args: Array[String]): Unit = { - val extraClasspath = "." // TODO allow to set it from the args with -classpath XYZ - val classes = args.toList - - - parseArguments(args) match { - case None => println(help) - case Some(cliArgs) => { - val reporter = compile(cliArgs) - - if (reporter.hasErrors) { - println("Compile error:") - println(reporter) - } else { - val scalaFile = Paths.get(cliArgs("input")).toAbsolutePath - val classNames = Utils.getClassNames(Paths.get(cliArgs("classpath")), scalaFile) - val sdbconsumer = new SemanticdbConsumer(scalaFile) - val _ = ConsumeTasty(cliArgs("classpath"), classNames, sdbconsumer) - val textDocument = sdbconsumer.toSemanticdb() - val os = Files.newOutputStream(Paths.get(cliArgs("out"))) - try textDocument.writeTo(os) - finally os.close() - } - } - } - } -} diff --git a/semanticdb/src/dotty/semanticdb/Scala.scala b/semanticdb/src/dotty/semanticdb/Scala.scala deleted file mode 100644 index 2d752e8b3c0d..000000000000 --- a/semanticdb/src/dotty/semanticdb/Scala.scala +++ /dev/null @@ -1,292 +0,0 @@ -package dotty.semanticdb - -import scala.compat.Platform.EOL -import dotty.semanticdb.Scala.{Descriptor => d} -import dotty.semanticdb.Scala.{Names => n} - -object Scala { - object Symbols { - val None: String = "" - val RootPackage: String = "_root_/" - val EmptyPackage: String = "_empty_/" - def Global(owner: String, desc: Descriptor): String = - if (owner != RootPackage) owner + desc.toString - else desc.toString - def Local(suffix: String): String = { - if (suffix.indexOf("/") == -1 && suffix.indexOf(";") == -1) "local" + suffix - else throw new IllegalArgumentException(suffix) - } - def Multi(symbols: List[String]): String = { - symbols.distinct match { - case List(symbol) => - symbol - case symbols => - val sb = new StringBuilder - symbols.foreach { symbol => - if (!symbol.isMulti) { - sb.append(';') - } - sb.append(symbol) - } - sb.toString() - } - } - } - - implicit class ScalaSymbolOps(symbol: String) { - def isNone: Boolean = - symbol == Symbols.None - def isRootPackage: Boolean = - symbol == Symbols.RootPackage - def isEmptyPackage: Boolean = - symbol == Symbols.EmptyPackage - def isGlobal: Boolean = - !isNone && !isMulti && (symbol.last match { - case '.' | '#' | '/' | ')' | ']' => true - case _ => false - }) - def isLocal: Boolean = - symbol.startsWith("local") - def isMulti: Boolean = - symbol.startsWith(";") - def asMulti: List[String] = { - if (!isMulti) symbol :: Nil - else { - val buf = List.newBuilder[String] - def loop(begin: Int, i: Int): Unit = - if (i >= symbol.length) { - buf += symbol.substring(begin, symbol.length) - } else { - symbol.charAt(i) match { - case ';' => - buf += symbol.substring(begin, i) - loop(i + 1, i + 1) - case '`' => - var j = i + 1 - while (symbol.charAt(j) != '`') j += 1 - loop(begin, j + 1) - case _ => - loop(begin, i + 1) - } - } - loop(1, 1) - buf.result() - } - } - def isTerm: Boolean = - !isNone && !isMulti && symbol.last == '.' - def isType: Boolean = - !isNone && !isMulti && symbol.last == '#' - def isPackage: Boolean = - !isNone && !isMulti && symbol.last == '/' - def isParameter: Boolean = - !isNone && !isMulti && symbol.last == ')' - def isTypeParameter: Boolean = - !isNone && !isMulti && symbol.last == ']' - def ownerChain: List[String] = { - val buf = List.newBuilder[String] - def loop(symbol: String): Unit = { - if (!symbol.isNone) { - loop(symbol.owner) - buf += symbol - } - } - loop(symbol) - buf.result - } - def owner: String = { - if (isGlobal) { - if (isRootPackage) Symbols.None - else { - val rest = DescriptorParser(symbol)._2 - if (rest.nonEmpty) rest - else Symbols.RootPackage - } - } else { - Symbols.None - } - } - def desc: Descriptor = { - if (isGlobal) { - DescriptorParser(symbol)._1 - } else { - d.None - } - } - } - - sealed trait Descriptor { - def isNone: Boolean = this == d.None - def isTerm: Boolean = this.isInstanceOf[d.Term] - def isMethod: Boolean = this.isInstanceOf[d.Method] - def isType: Boolean = this.isInstanceOf[d.Type] - def isPackage: Boolean = this.isInstanceOf[d.Package] - def isParameter: Boolean = this.isInstanceOf[d.Parameter] - def isTypeParameter: Boolean = this.isInstanceOf[d.TypeParameter] - def value: String - def name: n.Name = { - this match { - case d.None => n.TermName(value) - case d.Term(value) => n.TermName(value) - case d.Method(value, disambiguator) => n.TermName(value) - case d.Type(value) => n.TypeName(value) - case d.Package(value) => n.TermName(value) - case d.Parameter(value) => n.TermName(value) - case d.TypeParameter(value) => n.TypeName(value) - } - } - override def toString: String = { - this match { - case d.None => sys.error("unsupported descriptor") - case d.Term(value) => s"${n.encode(value)}." - case d.Method(value, disambiguator) => s"${n.encode(value)}${disambiguator}." - case d.Type(value) => s"${n.encode(value)}#" - case d.Package(value) => s"${n.encode(value)}/" - case d.Parameter(value) => s"(${n.encode(value)})" - case d.TypeParameter(value) => s"[${n.encode(value)}]" - } - } - } - object Descriptor { - case object None extends Descriptor { def value: String = "" } - final case class Term(value: String) extends Descriptor - final case class Method(value: String, disambiguator: String) extends Descriptor - final case class Type(value: String) extends Descriptor - final case class Package(value: String) extends Descriptor - final case class Parameter(value: String) extends Descriptor - final case class TypeParameter(value: String) extends Descriptor - } - - object Names { - // NOTE: This trait is defined inside Names to support the idiom of importing - // scala.meta.internal.semanticdb.Scala._ and not being afraid of name conflicts. - sealed trait Name { - def value: String - override def toString: String = value - } - final case class TermName(value: String) extends Name - final case class TypeName(value: String) extends Name - - val RootPackage: TermName = TermName("_root_") - val EmptyPackage: TermName = TermName("_empty_") - val PackageObject: TermName = TermName("package") - val Constructor: TermName = TermName("") - - private[semanticdb] def encode(value: String): String = { - if (value == "scalaShadowing") { - "scala" - } else if (value == "") { - "``" - } else { - val (start, parts) = (value.head, value.tail) - val isStartOk = Character.isJavaIdentifierStart(start) - val isPartsOk = parts.forall(Character.isJavaIdentifierPart) - if (isStartOk && isPartsOk) value - else "`" + value + "`" - } - } - } - - object DisplayNames { - val RootPackage: String = "_root_" - val EmptyPackage: String = "_empty_" - val Constructor: String = "" - val Anonymous: String = "_" - } - - private class DescriptorParser(s: String) { - var i = s.length - def fail() = { - val message = "invalid symbol format" - val caret = " " * i + "^" - sys.error(s"$message$EOL$s$EOL$caret") - } - - val BOF = '\u0000' - val EOF = '\u001A' - var currChar = EOF - def readChar(): Char = { - if (i <= 0) { - if (i == 0) { - i -= 1 - currChar = BOF - currChar - } else { - fail() - } - } else { - i -= 1 - currChar = s(i) - currChar - } - } - - def parseValue(): String = { - if (currChar == '`') { - val end = i - while (readChar() != '`') {} - readChar() - s.substring(i + 2, end) - } else { - val end = i + 1 - if (!Character.isJavaIdentifierPart(currChar)) fail() - while (Character.isJavaIdentifierPart(readChar()) && currChar != BOF) {} - s.substring(i + 1, end) - } - } - - def parseDisambiguator(): String = { - val end = i + 1 - if (currChar != ')') fail() - while (readChar() != '(') {} - readChar() - s.substring(i + 1, end) - } - - def parseDescriptor(): Descriptor = { - if (currChar == '.') { - readChar() - if (currChar == ')') { - val disambiguator = parseDisambiguator() - val value = parseValue() - d.Method(value, disambiguator) - } else { - d.Term(parseValue()) - } - } else if (currChar == '#') { - readChar() - d.Type(parseValue()) - } else if (currChar == '/') { - readChar() - d.Package(parseValue()) - } else if (currChar == ')') { - readChar() - val value = parseValue() - if (currChar != '(') fail() - else readChar() - d.Parameter(value) - } else if (currChar == ']') { - readChar() - val value = parseValue() - if (currChar != '[') fail() - else readChar() - d.TypeParameter(value) - } else { - fail() - } - } - - def entryPoint(): (Descriptor, String) = { - readChar() - val desc = parseDescriptor() - (desc, s.substring(0, i + 1)) - } - } - - private[semanticdb] object DescriptorParser { - def apply(symbol: String): (Descriptor, String) = { - val parser = new DescriptorParser(symbol) - parser.entryPoint() - } - } -} diff --git a/semanticdb/src/dotty/semanticdb/SemanticdbConsumer.scala b/semanticdb/src/dotty/semanticdb/SemanticdbConsumer.scala deleted file mode 100644 index 87ca647b2a86..000000000000 --- a/semanticdb/src/dotty/semanticdb/SemanticdbConsumer.scala +++ /dev/null @@ -1,1045 +0,0 @@ -package dotty.semanticdb - -import scala.tasty.Reflection -import scala.tasty.file.TastyConsumer - -import dotty.tools.dotc.tastyreflect -import dotty.tools.dotc.core.StdNames._ -import scala.collection.mutable.HashMap -import scala.collection.mutable.Set -import scala.meta.internal.{semanticdb => s} -import dotty.semanticdb.Scala.{Descriptor => d} -import dotty.semanticdb.Scala._ - - -class SemanticdbConsumer(sourceFilePath: java.nio.file.Path) extends TastyConsumer { - var stack: List[String] = Nil - - val semantic: s.TextDocument = s.TextDocument() - var occurrences: Seq[s.SymbolOccurrence] = Seq() - - def toSemanticdb(): s.TextDocument = { - s.TextDocument(text = sourceCode.content(), occurrences = occurrences) - } - - // Caching for package definitions (as they are shared accross different class files) - val packageDefinitions: Set[(String, Int)] = Set() - // Caching for symbol paths to avoid regenerating some of them - // (as computing a symbol path from a symbol is deterministic) - val symbolsCache: HashMap[(Any, s.Range), String] = HashMap() - // Offset for local symbol - var localOffset: Int = 0 - - val sourceCode = new SourceFile(sourceFilePath) - - final def apply(reflect: Reflection)(root: reflect.Tree): Unit = { - import reflect._ - - // To avoid adding symbol paths duplicates inside a same class - val symbolPathsMap: Set[(String, s.Range)] = Set() - - object ChildTraverser extends TreeTraverser { - var children: List[Tree] = Nil - var childrenType: List[Tree /*TypeTree | TypeBoundsTree*/] = Nil - override def traverseTree(tree: Tree)(implicit ctx: Context): Unit = tree match { - case IsTypeTree(tree) => - traverseTypeTree(tree) - case IsTypeBoundsTree(tree) => - traverseTypeTree(tree) - case _ => children = tree :: children - } - override def traversePattern(pattern: Pattern)( - implicit ctx: Context): Unit = () - def traverseTypeTree(tree: Tree /*TypeTree | TypeBoundsTree*/)( - implicit ctx: Context): Unit = - childrenType = tree :: childrenType - - def getChildren(tree: Tree)(implicit ctx: Context): List[Tree] = { - children = Nil - traverseTreeChildren(tree)(ctx) - return children - } - def getChildrenType(tree: Tree /*TypeTree | TypeBoundsTree*/)(implicit ctx: Context): List[Tree /*TypeTree | TypeBoundsTree*/] = { - childrenType = Nil - traverseTreeChildren(tree)(ctx) - return childrenType - } - } - - /* The (==) operator does not work correctly on two positions, - we redefine our one */ - def arePositionEqual(p1 : Position, p2 : Position) : Boolean = { - p1.start == p2.start && - p1.end == p2.end && - p1.sourceFile == p2.sourceFile - } - - object Traverser extends TreeTraverser { - implicit class TreeExtender(tree: Tree) { - def isUserCreated: Boolean = { - val children: List[Position] = - ChildTraverser.getChildren(tree)(reflect.rootContext).map(_.pos) - return !((tree.pos.exists && tree.pos.start == tree.pos.end && children == Nil) || - children.exists(arePositionEqual(tree.pos, _))) - } - } - - implicit class TypeTreeExtender(tree: TypeTree) { - def isUserCreated: Boolean = { - val children: List[Position] = - ChildTraverser.getChildrenType(tree)(reflect.rootContext).collect(_ match { - case IsTypeTree(tt) => tt.pos}) - return !((tree.pos.exists && tree.pos.start == tree.pos.end && children == Nil) || - children.exists(arePositionEqual(tree.pos, _))) - } - } - - implicit class TypeOrBoundsTreeExtender(tree: Tree /*TypeTree | TypeBoundsTree*/) { - def typetree: TypeTree = tree match { - case IsTypeTree(t) => t - } - } - - implicit class PatternExtender(tree: Pattern) { - def isUserCreated: Boolean = { - return !(tree.pos.exists && tree.pos.start == tree.pos.end) - } - } - - implicit class SymbolExtender(symbol: Symbol) { - def exists = !(symbol.name == "" || symbol == NoSymbol) - /* Return true if symbol represents the definition of a var setter, false otherwise. - We return true if the extract of source code corresponding to the position of the symbol is the same as the symbol name. - Ex: - var m = ??? - -> there is a defdef for `m_=` with position "m =". As "m =" != "m_=", we return false - */ - def isMutableSetterExplicit(role : s.SymbolOccurrence.Role) = { - if (role == s.SymbolOccurrence.Role.DEFINITION && - symbol.pos.exists && - symbol.flags.is(Flags.Mutable) && symbol.isMethod && - symbol.trueName.endsWith("_=")) - (sourceCode.peek(symbol.pos.start, symbol.pos.end) == symbol.trueName) - else - true - } - - // The name of a symbol can contain special chars. This will replace them with the correct char. - def trueName: String = { - val prohibitedChars = '.' :: ';' :: '[' :: '/' :: '<' :: '>' :: Nil - prohibitedChars.foldLeft(symbol.name)((old, chr) => - old.replaceAll("\\$u%04X".format(chr.toInt), chr.toString) - ) - } - - - def isClass: Boolean = symbol match { - case IsClassDefSymbol(_) => true - case _ => false - } - - def isTypeParameter: Boolean = symbol.isParameter && symbol.isType - - def isType: Boolean = symbol match { - case IsTypeDefSymbol(_) => true - case _ => false - } - - def isTerm: Boolean = !symbol.isType - - def isMethod: Boolean = symbol match { - case IsDefDefSymbol(_) => true - case _ => false - } - - def isVal: Boolean = symbol match { - case IsValDefSymbol(_) => true - case _ => false - } - - def isPackage: Boolean = symbol match { - case IsPackageDefSymbol(_) => true - case _ => false - } - - def isDefaultGetter: Boolean = - symbol.name.contains(tpnme.DEFAULT_GETTER.toString) - - def isReservedName : Boolean = { - val keywords = - List("ev$", "evidence$", "$_lazy_implicit_$", "$lzy", "$lzyINIT", - "$OFFSET", "bitmap$", "_$", "$tailLocal", "tmp", "$doc", - "$superArg$", "$scrutinee", "$elem") - return keywords.exists(symbol.name.contains(_)) - } - - def isParameter: Boolean = symbol.flags.is(Flags.Param) - - def isObject: Boolean = symbol.flags.is(Flags.Object) - - def isTrait: Boolean = symbol.flags.is(Flags.Trait) - - def isConstructor(implicit ctx: Context): Boolean = - symbol.name == "" - - def isVarAccessor(implicit ctx: Context): Boolean = { - symbol.isVal && symbol.flags.is(Flags.Mutable) - } - - def isValMethod(implicit ctx: Context): Boolean = { - symbol.isMethod && { - (symbol.flags.is(Flags.FieldAccessor) && symbol.flags.is(Flags.StableRealizable) ) || - (symbol.isUsefulField && !symbol.flags.is(Flags.Mutable) ) - } - } - - def isAnonymousClassConstructor(implicit ctx: Context): Boolean = { - symbol.isConstructor && symbol.owner.isAnonymousClass - } - - def isAnonymousSelfParameter(implicit ctx: Context): Boolean = { - symbol.isSelfParameter && { - symbol.name == tpnme.this_.toString || // hardlinked in ClassSignature.self - symbol.name.startsWith("x$") // wildcards can't be referenced: class A { _: B => } - } - } - - def isWildCard(implicit ctx: Context): Boolean = { - symbol.name.startsWith(tpnme.WILDCARD.toString) && - symbol.name != tpnme.THIS.toString - } - - def isAnonymousInit(implicit ctx: Context): Boolean = { - return symbol.exists && symbol.owner.exists && - (symbol.owner.isAnonymousFunction || symbol.owner.isAnonymousClass) && - symbol.name == "" - } - - /* The following methods are directly extracted from the scala - implementation of SemanticDB (scalameta/semanticdb/scalac/library/src/main/scala/scala/meta/internal/semanticdb/scalac/SymbolOps.scala) - */ - def isValueParameter: Boolean = symbol.isParameter && !symbol.isType && !symbol.flags.is(Flags.ParamAccessor) - - def isJavaClass: Boolean = (symbol.isClass || symbol.isObject) && symbol.flags.is(Flags.JavaDefined) - - def isSelfParameter(implicit ctx: Context): Boolean = - symbol.exists && symbol.owner == symbol - - def isSemanticdbLocal(implicit ctx: Context): Boolean = { - def definitelyGlobal = symbol.isPackage - def definitelyLocal = - !symbol.exists || - (symbol.owner.isTerm && !symbol.isParameter) || - ((symbol.owner.isAliasType || symbol.owner.isAbstractType) && !symbol.isParameter) || - symbol.isSelfParameter || - symbol.isLocalDummy || - symbol.isRefinementClass || - symbol.isAnonymousClass || - symbol.isAnonymousFunction /*|| - symbol.isExistential*/ - def ownerLocal = symbol.owner.isSemanticdbLocal - !definitelyGlobal && (definitelyLocal || ownerLocal) - } - - def isSyntheticConstructor(implicit ctx: Context): Boolean = { - val isObjectConstructor = symbol.isConstructor && symbol.owner.exists && symbol.owner.flags.is(Flags.Object) - val isModuleConstructor = symbol.isConstructor && symbol.owner.isClass - val isTraitConstructor = symbol.isConstructor && symbol.owner.isTrait - val isInterfaceConstructor = symbol.isConstructor && symbol.owner.flags.is(Flags.JavaDefined) && symbol.owner.isTrait - val isEnumConstructor = symbol.isConstructor && symbol.owner.flags.is(Flags.JavaDefined) && symbol.owner.flags.is(Flags.Enum) - /*val isStaticConstructor = symbol.name == g.TermName("")*/ - //val isClassfileAnnotationConstructor = symbol.owner.isClassfileAnnotation - /*isModuleConstructor || */ - isTraitConstructor || isInterfaceConstructor || isObjectConstructor || - isEnumConstructor /*|| isStaticConstructor || isClassfileAnnotationConstructor*/ - } - def isLocalChild(implicit ctx: Context): Boolean = - symbol.name == tpnme.LOCAL_CHILD.toString - - def isSyntheticValueClassCompanion(implicit ctx: Context): Boolean = { - if (symbol.isClass) { - if (symbol.flags.is(Flags.Object)) { - symbol.asClassDef.moduleClass.fold(false)(c => - c.isSyntheticValueClassCompanion) - } else { - symbol.flags.is(Flags.ModuleClass) && - symbol.flags.is(Flags.Synthetic) && - symbol.asClassDef.methods.isEmpty - } - } else { - false - } - } - - /* the `isFieldForPrivateThis` is commented out otherwise class members of the form - "private[this] val foo" are not converted to symbol occurences. - In the original semanticdb this line is commented out. - */ - def isScalacField(implicit ctx: Context): Boolean = { - //val isFieldForPrivateThis = symbol.flags.is(Flags.PrivateLocal) && symbol.isTerm && !symbol.isMethod && !symbol.isObject - val isFieldForOther = false //symbol.name.endsWith(g.nme.LOCAL_SUFFIX_STRING) - val isJavaDefined = symbol.flags.is(Flags.JavaDefined) - (/*isFieldForPrivateThis ||*/ isFieldForOther) && !isJavaDefined - } - def isUselessField(implicit ctx: Context): Boolean = { - symbol.isScalacField && symbol.owner.exists - } - def isUsefulField(implicit ctx: Context): Boolean = { - symbol.isScalacField && !symbol.isUselessField - } - def isSyntheticCaseAccessor(implicit ctx: Context): Boolean = { - symbol.flags.is(Flags.CaseAcessor) && symbol.trueName.contains("$") - } - def isSyntheticJavaModule(implicit ctx: Context): Boolean = { - val resolved = symbol match { - case IsClassDefSymbol(c) => resolveClass(c) - case _ => symbol - } - !resolved.flags.is(Flags.Package) && resolved.flags.is(Flags.JavaDefined) && resolved.flags.is(Flags.Object) - } - def isSyntheticAbstractType(implicit ctx: Context): Boolean = { - symbol.flags.is(Flags.Synthetic) && symbol.isAbstractType // these are hardlinked to TypeOps - } - def isEtaExpandedParameter(implicit ctx: Context): Boolean = { - // Term.Placeholder occurrences are not persisted so we don't persist their symbol information. - // We might want to revisit this decision https://github.com/scalameta/scalameta/issues/1657 - symbol.isParameter && - symbol.name.startsWith("x$") && - symbol.owner.isAnonymousFunction - } - def isStaticMember(implicit ctx: Context): Boolean = - symbol.exists && - (symbol.flags.is(Flags.Static) || - /*symbol.annots.find(_ == ctx.definitions.ScalaStaticAnnot)*/ false) - - def isStaticConstructor(implicit ctx: Context): Boolean = { - (symbol.isStaticMember && symbol.isClassConstructor) || (symbol.name == tpnme.STATIC_CONSTRUCTOR.toString) - } - - /* End of methods imported from the scala version of SemanticDB */ - - def isInitChild(implicit ctx: Context): Boolean = { - if (symbol.exists && symbol.owner.exists) { - return symbol.owner.name == "" || symbol.owner.isInitChild - } else { - return false - } - } - - def isUseless(implicit ctx: Context): Boolean = { - !symbol.exists || - symbol.isReservedName || - symbol.isAnonymousInit || - symbol.isDefaultGetter || - symbol.isWildCard || - symbol.isAnonymousClass || - symbol.isAnonymousFunction || - symbol.isSyntheticConstructor || - symbol.isStaticConstructor || - symbol.isLocalChild || - symbol.isSyntheticValueClassCompanion || - symbol.isUselessField || - symbol.isSyntheticCaseAccessor || - symbol.isRefinementClass || - symbol.isSyntheticJavaModule - } - def isUseful(implicit ctx: Context): Boolean = !symbol.isUseless - def isUselessOccurrence(implicit ctx: Context): Boolean = { - symbol.isUseless && - !symbol.isSyntheticJavaModule // references to static Java inner classes should have occurrences - } - } - - def resolveClass(symbol: ClassDefSymbol): Symbol = - (symbol.companionClass, symbol.companionModule) match { - case (Some(c), _) => c - case (_, Some(module)) if symbol.flags.is(Flags.Object) => module - case _ => symbol - } - - def disimbiguate(symbolPath: String, symbol: Symbol): String = { - try { - val symbolcl = resolveClass(symbol.owner.asClassDef) - symbolcl match { - case IsClassDefSymbol(classsymbol) => { - val methods = classsymbol.method(symbol.name) - val (methods_count, method_pos) = - methods.foldLeft((0, -1))((x: Tuple2[Int, Int], m: Symbol) => { - if (m == symbol) - (x._1 + 1, x._1) - else - (x._1 + 1, x._2) - }) - val real_pos = methods_count - method_pos - 1 - - if (real_pos == 0) { - "()" - } else { - "(+" + real_pos + ")" - } - } - case _ => { - "()" - } - } - } catch { - case _ => "()" - } - } - - def iterateParent(symbol: Symbol, isMutableAssignement:Boolean=false): String = { - if (!symbol.exists || symbol.name == "") then { - "" - } else { - val rsymbol = symbol match { - case IsClassDefSymbol(c) => resolveClass(c) - case _ => symbol - } - val previous_symbol = - /* When we consider snipper of the form: `abstract class DepAdvD[CC[X[C] <: B], X[Z], C] extends DepTemp`, - The symbol for C will be something like example/DepAdvD#``().[CC].[X].[C]. - This is illogic: a init method can't have any child. Thus, when the current symbol is - a typeparameter, and the owner is an init, we can just "jump" over the init. */ - if (rsymbol.owner.name == "" && rsymbol.isType) - iterateParent(rsymbol.owner.owner) - else - iterateParent(rsymbol.owner) - - - val isdef = rsymbol match {case IsDefDefSymbol(_) => true case _ => false} - val symbolName = if (isMutableAssignement) rsymbol.trueName + "_=" else rsymbol.trueName - val next_atom = - if (rsymbol.isPackage) { - d.Package(symbolName) - } else if (rsymbol.isObject && !rsymbol.isJavaClass) { - d.Term(symbolName) - } else if (rsymbol.isValMethod && !rsymbol.isVarAccessor) { - d.Term(symbolName) - } else if (rsymbol.isMethod || rsymbol.isUsefulField || rsymbol.isVarAccessor) { - d.Method(symbolName, - disimbiguate(previous_symbol + symbolName, rsymbol)) - } else if (rsymbol.isTypeParameter) { - d.TypeParameter(symbolName) - } else if (rsymbol.isValueParameter) { - d.Parameter(symbolName) - } else if (rsymbol.isType || rsymbol.isJavaClass) { - d.Type(symbolName) - } else { - d.Term(symbolName) - } - - Symbols.Global(previous_symbol, next_atom) - } - } - - def symbolToSymbolString(symbol: Symbol, isMutableAssignement:Boolean = false): (String, Boolean) = { - if (symbol.isSemanticdbLocal) { - var localsymbol = Symbols.Local(localOffset.toString) - localOffset += 1 - (localsymbol, false) - } else { - (iterateParent(symbol, isMutableAssignement), true) - } - } - - def addOccurence(symbol: Symbol, - typeSymbol: s.SymbolOccurrence.Role, - range: s.Range, - isMutableAssignement:Boolean = false): Unit = { - if (!symbol.exists) return - - val symbolName = if (isMutableAssignement) symbol.trueName + "_=" else symbol.trueName - val (symbolPath, isGlobal) = - if (symbol.pos.exists) { - val keyRange = createRange(symbol.pos) - if (symbolsCache.contains((symbolName, keyRange))) - (symbolsCache((symbolName, keyRange)), symbol.isSemanticdbLocal) - else { - val (sp, ig) = symbolToSymbolString(symbol, isMutableAssignement) - symbolsCache += ((symbolName, keyRange) -> sp) - (sp, ig) - } - } else { - symbolToSymbolString(symbol) - } - - if (symbolPath == "") return - if (symbol.flags.is(Flags.Synthetic) && typeSymbol == s.SymbolOccurrence.Role.DEFINITION) return - - val key = (symbolPath, range) // this is to avoid duplicates symbols - // For example, when we define a class as: `class foo(x: Int)`, - // dotty will generate a ValDef for the x, but the x will also - // be present in the constructor, thus making a double definition - if (!symbolPathsMap.contains(key)) { - symbolPathsMap += key - occurrences = - occurrences :+ - s.SymbolOccurrence( - Some(range), - symbolPath, - typeSymbol - ) - } - } - - def addOccurencePredef(parent: String, name: String, range: s.Range): Unit = { - occurrences = - occurrences :+ - s.SymbolOccurrence( - Some(range), - parent + name + "().", - s.SymbolOccurrence.Role.DEFINITION - ) - } - - def addSelfDefinition(name: String, range: s.Range): Unit = { - var localsymbol = Symbols.Local(localOffset.toString) - localOffset += 1 - symbolsCache += ((name, range) -> localsymbol) - occurrences = - occurrences :+ - s.SymbolOccurrence( - Some(range), - localsymbol, - s.SymbolOccurrence.Role.DEFINITION - ) - } - - def addOccurenceTree(tree: Tree, - typeSymbol: s.SymbolOccurrence.Role, - range: s.Range, - forceAdd: Boolean = false, - isMutableAssignement: Boolean = false): Unit = { - if (!tree.symbol.isUselessOccurrence && - tree.symbol.isMutableSetterExplicit(typeSymbol) && - (tree.isUserCreated || forceAdd)) { - addOccurence(tree.symbol, typeSymbol, range, isMutableAssignement) - } - } - - def addOccurenceTypeTree(typetree: TypeTree, - typeSymbol: s.SymbolOccurrence.Role, - range: s.Range): Unit = { - if (!typetree.symbol.isUselessOccurrence && typetree.isUserCreated) { - addOccurence(typetree.symbol, typeSymbol, range) - } - } - - def addOccurencePatternTree(tree: Pattern, - typeSymbol: s.SymbolOccurrence.Role, - range: s.Range): Unit = { - if (!tree.symbol.isUselessOccurrence && tree.isUserCreated) { - addOccurence(tree.symbol, typeSymbol, range) - } - } - - def addOccurenceId(parentPath: String, id: Id): Unit = { - val symbolPath = Symbols.Global(parentPath, d.Term(id.name)) - occurrences = - occurrences :+ - s.SymbolOccurrence( - Some(createRange(id.pos)), - symbolPath, - s.SymbolOccurrence.Role.REFERENCE - ) - } - - def createRange(pos: Position): s.Range = - createRange(pos.startLine, pos.startColumn, pos.endLine, pos.endColumn) - - def createRange(startLine : Int, startColumn : Int, length : Int) : s.Range = { - createRange(startLine, startColumn, startLine, startColumn + length) - } - - def createRange(startLine: Int, startColumn: Int, endLine: Int, endColumn: Int): s.Range = { - /* This aux function is to make sure every generated range are coherent, - meaning they all have a valid startLine and startColumn (meaning startColumn is - a number of byte from the start of the line, not the start of the file)*/ - def aux(l : Int, c : Int) : (Int, Int) = { - if (l == 0) { - val line = sourceCode.offsetToLine(l) - (line, c - sourceCode.lineToOffset(line)) - } else { - (l, c) - } - } - - val (sl, sc) = aux(startLine, startColumn) - val (el, ec) = aux(endLine, endColumn) - s.Range(sl, sc, el, ec) - } - - /* Create a "point range" (a range refering to a point position) */ - def createRange(line: Int, column: Int) : s.Range = { - createRange(line, column, line, column) - } - - def rangeSelect(name: String, range: Position): s.Range = { - if (name == "") { - return createRange(range) - } else - /* The position of a select is the position of the whole select expression, - from the start to the end. - To get the position of only the selected operand, we distinguish two cases: - - either we are selecting an operator ending with a ':' (for those the execution - order is reversed), so the selected expression is at the start. - Ex: A #:: B -> the position of the select is the range "#:: B", so we pick the range "#::" - - either the select is in normal order, in this case we select the end of it. - Ex: A + B -> the position of the select is the range "A +", so we pick the range "+" - */ - if (name.endsWith(":")) { - return createRange(range.startLine, range.startColumn, name.length) - } else { - return createRange(range.endLine, range.endColumn - name.length, name.length) - } - } - - def getImportPath(pathTerm: Term): String = { - val range = pathTerm match { - case Select(qualifier, selected) => { - getImportPath(qualifier) - rangeSelect(selected, pathTerm.pos) - } - case Ident(x) => { - createRange(pathTerm.pos.startLine, pathTerm.pos.startColumn, pathTerm.symbol.trueName.length) - } - } - addOccurenceTree(pathTerm, - s.SymbolOccurrence.Role.REFERENCE, - range) - iterateParent(pathTerm.symbol) - } - - - /* A known bug with import path is that we are not able to determine the nature of the - imported symbol (or to append several of them if we are importing both a class - and its companionmodule for exemple) */ - def getImportSelectors(parentPath: String, - selectors: List[ImportSelector]): Unit = { - selectors.foreach(selector => - selector match { - case SimpleSelector(id) if id.name != "_" => { - addOccurenceId(parentPath, id) - } - case RenameSelector(id, _) if id.name != "_" => { - addOccurenceId(parentPath, id) - } - case OmitSelector(id) if id.name != "_" => { - addOccurenceId(parentPath, id) - } - case _ => - }) - } - - def traverseTypeTree(tree: Tree /*TypeTree | TypeBoundsTree*/)( - implicit ctx: Context): Unit = { - tree match { - case TypeIdent(_) => { - val typetree = tree.typetree - addOccurenceTypeTree(typetree, - s.SymbolOccurrence.Role.REFERENCE, - createRange(typetree.pos)) - } - case TypeSelect(qualifier, _) => { - val typetree = tree.typetree - val range = rangeSelect(typetree.symbol.trueName, typetree.pos) - addOccurenceTypeTree(typetree, - s.SymbolOccurrence.Role.REFERENCE, - range) - super.traverseTree(typetree) - } - - case Projection(qualifier, x) => { - val typetree = tree.typetree - val range = rangeSelect(typetree.symbol.trueName, typetree.pos) - addOccurenceTypeTree(typetree, - s.SymbolOccurrence.Role.REFERENCE, - range) - super.traverseTree(typetree) - } - - case Inferred() => { - /* In theory no inferred types should be put in the semanticdb file. - However, take the case where a typed is refered from an imported class: - class PrefC { - object N { - type U - } - } - - object PrefTest { - val c: PrefC = ??? - import c.N._ - def k3: U = ??? - } - - The type corresponding to U in the definition of k3 is marked as - inferred even though it is present in the source code. We use a - workaround for this specific case, by checking if the name of the - inferred type corresponds to the one put in the source code at this - position - */ - - val typetree = tree.typetree - val start = typetree.pos.start - val end = typetree.pos.end - if (sourceCode.peek(start, end) == typetree.symbol.name) { - addOccurenceTypeTree(typetree, - s.SymbolOccurrence.Role.REFERENCE, - createRange(typetree.pos)) - } - } - - case _ => { - super.traverseTree(tree) - } - } - } - - override def traversePattern(tree: Pattern)(implicit ctx: Context): Unit = { - tree match { - case Pattern.Bind(name, _) => { - addOccurencePatternTree( - tree, - s.SymbolOccurrence.Role.REFERENCE, - createRange(tree.symbol.pos.startLine, tree.symbol.pos.startColumn, name.length) - ) - super.traversePattern(tree) - } - case _ => - super.traversePattern(tree) - } - } - - - /* Finding the range of init symbols is not intuitive. We can determine it on a classdef. - [fittedInitClassRange] is used to transmit this information to the corresponding symbol */ - var fittedInitClassRange: Option[s.Range] = None - - /* At each point of the traversal [classStacks] is the list of classes currently being defined - Ex: - class Foo { - class Bar { - ??? // classStacks = Bar :: Foo :: Nil - } - ??? // classStacks = Foo :: Nil - } - */ - var classStacks : List[Symbol] = Nil - - /* Is the term we are currently seeing the rhs of an assignement? */ - var isAssignedTerm = false - - /* Create a mapping from parameter name to parameter position */ - def generateParamsPosMapping(cdef: DefDef)(implicit ctx: Context): Map[String, s.Range] = { - val DefDef(_, _, params, _, _) = cdef - val start = Map[String, s.Range]() - params.foldLeft(start)((old, statements) => { - statements.foldLeft(old)((old, cval) => { - old + (cval.name -> createRange(cval.symbol.pos.startLine, cval.symbol.pos.startColumn, cval.symbol.trueName.length)) - }) - } - ) - } - - override def traverseTree(tree: Tree)(implicit ctx: Context): Unit = { - tree match { - case Import(_, path, selectors) => - val key = (tree.symbol.trueName, tree.pos.start) - if (!packageDefinitions(key)) { - packageDefinitions += key - getImportSelectors(getImportPath(path), selectors) - } - case New(ty) => { - super.traverseTree(tree) - } - case Apply(_, _) => { - super.traverseTree(tree) - } - case ClassDef(classname, constr, parents, derived, selfopt, statements) => { - val offsetSymbolClass = - if(tree.symbol.flags.is(Flags.Object)) -1 - else 0 - - // we first add the class to the symbol list - addOccurenceTree(tree, - s.SymbolOccurrence.Role.DEFINITION, - createRange(tree.symbol.pos.startLine, - tree.symbol.pos.startColumn + offsetSymbolClass, - tree.symbol.trueName.length)) - - /* Before adding the constructor symbol, we must find its position. Two options here: - - we've got no type parameters: `class Foo {...}` -> the symbol is put after `Foo` - - we've got some typeparameters: `class Foo[X] {...}` -> the symbol is put after [X] - In order to find the correct position in the last case, we put ourself on the rightmost bound - of all type parameters, that means before the last ']'. Then, we move one character right to - pass the ']' while making sure to skip whitespaces and comments */ - - /* The position is put in [fittedInitClassRange] to be transmitted to the defdef of */ - val DefDef(_, typesParameters, _, _, _) = constr - if (typesParameters.isEmpty) { - fittedInitClassRange = Some( - createRange(tree.symbol.pos.startLine, - tree.symbol.pos.startColumn + classname.length)) - } else { - val rightmost = typesParameters.reverse.head.pos.end - val end_ = sourceCode.nextCharacterSkipComments(rightmost) + 1 - fittedInitClassRange = Some(createRange(0, end_)) - } - - traverseTree(constr) - - fittedInitClassRange = None - - // we add the parents to the symbol list - parents.foreach(traverseTree) - - selfopt match { - case Some(vdef @ ValDef(name, type_, _)) => { - // If name is "_" then it means it is in fact "this". We don't - // want to had a symbol for it in semanticdb - if (name != "_") { - // The tree does not include a position to the overloaded version of - // this. We find it heuristically by "parsing" the source code. - // The process is done in three steps: - // 1) Find a position before the '{' of the self but after any - // non related '{'. Here, it will be the largest end pos of a parent - // 2) Find the first '{' - // 3) Iterate until the character we are seeing is a letter - val startPosSearch: Int = parents.foldLeft(tree.pos.end)( - (old: Int, ct: Tree) => - ct match { - case IsTerm(t) if t.pos.end < old => t.pos.end - case _ => old - }) - - var posColumn = if (startPosSearch == tree.pos.end) tree.pos.start else startPosSearch - posColumn = sourceCode.firstOccurrenceLetter('{', posColumn) - posColumn = sourceCode.nextCharacterSkipComments(posColumn+1) - - addSelfDefinition(name, createRange(0, posColumn, name.length)) - } - traverseTypeTree(type_) - } - case _ => - } - - derived.foreach(traverseTypeTree) - - /* The last part is to go through every statements. - As usual, we must take care of how we do it as some statements are - accessors for parameters and we don't want to add duplicate information. - If a statement is a parameter accessor we add the corresponding occurence as it - wasn't done when we saw the symbol. - If it's only a parameter (meaning a type parameter) we already added it - before, so we do nothing. - Otherwise we proceed a usual - */ - classStacks = tree.symbol :: classStacks - - val paramsPosMapping = generateParamsPosMapping(constr) - - statements.foreach(statement => { - if (statement.symbol.flags.is(Flags.ParamAccessor)) { - if (paramsPosMapping.contains(statement.symbol.name)) { - addOccurenceTree(statement, s.SymbolOccurrence.Role.DEFINITION, paramsPosMapping(statement.symbol.name)) - } - } else if (!statement.symbol.flags.is(Flags.Param)) { - traverseTree(statement) - } - }) - - classStacks = classStacks.tail - } - - // If we have a symbol with a [fittedInitClassRange] we are sure it is a primary constructor - // We only record symbols correponding to types as symbols for value parameters will be added - // by traversing the class statements. - // Statement should be in this case - case DefDef("", typeparams, valparams, type_, statements) if fittedInitClassRange != None => { - addOccurenceTree(tree, - s.SymbolOccurrence.Role.DEFINITION, - fittedInitClassRange.get, - true) - valparams.foreach(params => - params.foreach(param => { - val ValDef(_, tpt, _) = param - traverseTypeTree(tpt) - }) - ) - traverseTypeTree(type_) - typeparams.foreach(traverseTree) - } - - // An object should have no init symbols - case DefDef("", _, _, _, _) if tree.symbol.owner.flags.is(Flags.Object) => { - } - - case Assign(lhs, rhs) => { - // We make sure to set [isAssignedTerm] to true on the lhs - isAssignedTerm = true - traverseTree(lhs) - isAssignedTerm = false - traverseTree(rhs) - } - - case IsDefinition(cdef) => { - // For a definition we must deal the special case of protected and private - // definitions - if (cdef.symbol.flags.is(Flags.Protected)) { - cdef.symbol.protectedWithin match { - case Some(within) => { - val startColumn = cdef.pos.startColumn + "protected[".length - addOccurence( - within.typeSymbol, - s.SymbolOccurrence.Role.REFERENCE, - createRange(cdef.pos.startLine, startColumn, within.typeSymbol.trueName.length) - ) - } - case _ => - } - } else { - cdef.symbol.privateWithin match { - case Some(within) => { - val startColumn = cdef.pos.startColumn + "private[".length - addOccurence( - within.typeSymbol, - s.SymbolOccurrence.Role.REFERENCE, - createRange(cdef.pos.startLine, startColumn, within.typeSymbol.trueName.length) - ) - } - case _ => - } - } - - if (tree.symbol.exists) { - val pos = tree.symbol.pos - var rangeSymbol = createRange(pos.startLine, pos.startColumn, tree.symbol.trueName.length) - - // In dotty definition of auxilliary constructors (ex def this(xxxx)) are represented - // by a DefDef("", ..). This conditions finds such patterns and set a correct rangeSymbol for them. - if (tree.symbol.trueName == "" && sourceCode.peek(pos.start, pos.start + 4) == "this") { - rangeSymbol = createRange(pos.startLine, pos.startColumn, 4) - } - addOccurenceTree(tree, - s.SymbolOccurrence.Role.DEFINITION, - rangeSymbol) - - } - super.traverseTree(cdef) - } - - case This(Some(id)) => { - /* We've got two options here: - - either the this is explicit: eg C.this.XXX. In this case, the position is [C.this], but - we want to put the symbol on the C, so around id - - either it is not explicit (eg a.foo). We want to put the symbol only around the a. - Distinguishing between the two is easy. If the sourcecode between [pos.start; pos.end] ends - with a 'this', then we're in the first case, otherwise the second - */ - var rangeThis = createRange(tree.pos) - if (sourceCode.peek(tree.pos.start, tree.pos.end).endsWith("this")) { - rangeThis = createRange(tree.pos.startLine, tree.pos.startColumn, tree.symbol.trueName.length) - } - addOccurenceTree(tree, - s.SymbolOccurrence.Role.REFERENCE, - rangeThis) - } - - case Super(_, Some(id)) => { - addOccurence(classStacks.head, - s.SymbolOccurrence.Role.DEFINITION, - createRange(id.pos)) - super.traverseTree(tree) - } - - case Select(qualifier, _) => { - var range = rangeSelect(tree.symbol.trueName, tree.pos) - - /* This branch deals with select of a `this`. Their is two options: - - The select of this is explicit (`C.this`). To know if we are in this case we - check if the end of our position in the sourceCode corresponds to a "this". - - The select is implicit and was compiler generated. We will force to add it if and only if - the qualifier itself was user created - */ - var shouldForceAdd = false - if (tree.symbol.trueName == "") { - if (tree.pos.start == tree.pos.end && sourceCode.peek(tree.pos.start - 5, tree.pos.start - 1) == "this") { - range = createRange(0, tree.pos.start - 5, 4) - shouldForceAdd = true - } else { - range = createRange(tree.pos.endLine, tree.pos.endColumn) - shouldForceAdd = qualifier.isUserCreated - } - } - /* We do not forget to disable the [isAssignedTerm] flag when exploring the qualifier - of our select*/ - val temp = isAssignedTerm - isAssignedTerm = false - super.traverseTree(tree) - isAssignedTerm = temp - - /* If we selected a term x which is a mutable variable without a private local flag we want - to record a call to the function x_= instead. We set the corresponding flag on*/ - val isMutableAssignement = isAssignedTerm && tree.symbol.flags.is(Flags.Mutable) && !tree.symbol.flags.is(Flags.PrivateLocal) - addOccurenceTree(tree, s.SymbolOccurrence.Role.REFERENCE, range, shouldForceAdd, isMutableAssignement) - } - - case Ident(name) => { - addOccurenceTree(tree, - s.SymbolOccurrence.Role.REFERENCE, - createRange(tree.pos.startLine, tree.pos.startColumn, tree.symbol.trueName.length)) - - super.traverseTree(tree) - } - - case Inlined(Some(c), b, d) => { - /* In theory files should be compiled with -Yno-inline before running semanticdb. - If this is not the case, here is a fallback to heuristically determine which predefFunction - corresponds to an inlined term. - - We peek the character below the inline node. - If it is an "l" (for locally), then we have a locally predef call - If it is an "i" (for implicitly") then it is an implicitly call - If it is an "a" it is an assert - */ - def getPredefFunction(pos: Int): String = { - sourceCode.peek(pos, pos+1) match { - case "l" => "locally" - case "i" => "implicitly" - case "a" => "assert" - } - } - val parentSymbol = iterateParent(c.symbol) - if (parentSymbol == "dotty/DottyPredef.") { - val pos = c.pos - val function = getPredefFunction(pos.start) - val range = createRange(pos.startLine, pos.startColumn, pos.startLine, function.length) - addOccurencePredef(parentSymbol, function, range) - } - - super.traverseTree(tree) - } - - case PackageClause(_) => - val key = (tree.symbol.trueName, tree.pos.start) - if (!packageDefinitions(key)) { - addOccurenceTree(tree, - s.SymbolOccurrence.Role.DEFINITION, - createRange(tree.pos.startLine, tree.pos.startColumn + "package ".length, tree.symbol.trueName.length)) - packageDefinitions += key - } - super.traverseTree(tree) - - case tree => - super.traverseTree(tree) - } - } - - } - Traverser.traverseTree(root)(reflect.rootContext) - } - - def println(x: Any): Unit = Predef.println(x) - -} diff --git a/semanticdb/src/dotty/semanticdb/SourceFile.scala b/semanticdb/src/dotty/semanticdb/SourceFile.scala deleted file mode 100644 index c53579b6e338..000000000000 --- a/semanticdb/src/dotty/semanticdb/SourceFile.scala +++ /dev/null @@ -1,71 +0,0 @@ -package dotty.semanticdb - -import scala.io.Source -import scala.math._ -import dotty.tools.dotc.util.SourceFile - -class SourceFile(path: java.nio.file.Path) { - private val sourceCode = Source.fromFile(path.toFile).mkString - private val sourceFile = SourceFile.virtual(path.toString, sourceCode) - - def content() = sourceCode - - def offsetToLine(offset: Int): Int = sourceFile.offsetToLine(offset) - - def lineToOffset(offset: Int): Int = sourceFile.lineToOffset(offset) - - def peek(start: Int, end: Int) : String = - sourceCode.substring(max(start, 0), min(end, sourceCode.length - 1)) - - def firstOccurrenceLetter(letter: Char, start : Int) : Int = { - var pos = start - while (pos < sourceCode.length && sourceCode(pos) != letter) { - val nextPos = nextCharacterSkipComments(pos) - if (nextPos == pos) - pos = nextPos + 1 - else - pos = nextPos - } - return pos - } - - def nextCharacterSkipComments(start : Int): Int = { - def aux(start : Int) : Int = { - var i = start - if (i+2 <= sourceCode.length && sourceCode.substring(i, i+2) == "//") { - while (i < sourceCode.length && sourceCode(i) != '\n') - i += 1 - return i+1 - } else if (i+2 <= sourceCode.length && sourceCode.substring(i, i+2) == "/*") { - var nestedCount = 0 - i += 2 - while (i + 2 <= sourceCode.length && - !(sourceCode.substring(i, i+2) == "*/" && - nestedCount == 0)) { - val s = sourceCode.substring(i, i+2) - if (s == "/*") { - nestedCount += 1 - i += 1 - } - if (s == "*/") { - nestedCount -= 1 - i += 1 - } - i += 1 - } - return i+2 - } else { - while (i < sourceCode.length && sourceCode(i).isWhitespace) - i += 1 - return i - } - } - var previous = start - var next = aux(previous) - while (previous != next) { - previous = next - next = aux(previous) - } - return previous - } -} \ No newline at end of file diff --git a/semanticdb/src/dotty/semanticdb/TastyScalaFileInferrer.scala b/semanticdb/src/dotty/semanticdb/TastyScalaFileInferrer.scala deleted file mode 100644 index 809397729c90..000000000000 --- a/semanticdb/src/dotty/semanticdb/TastyScalaFileInferrer.scala +++ /dev/null @@ -1,47 +0,0 @@ -package dotty.semanticdb - -import scala.meta.internal.{semanticdb => s} -import scala.tasty.Reflection -import scala.tasty.file.TastyConsumer -import java.lang.reflect.InvocationTargetException - -class TastyScalaFileInferrer extends TastyConsumer { - /* Visitor over a tasty tree. - Aims at finding the scala file from where this tree originated. - */ - - /* If a scala file was found sourcePath is Some(scalaFile), - Otherwise None */ - var sourcePath: Option[String] = None - final def apply(reflect: Reflection)(root: reflect.Tree): Unit = { - import reflect._ - object ChildTraverser extends TreeTraverser { - override def traverseTree(tree: Tree)(implicit ctx: Context): Unit = - tree match { - case IsClassDef(cdef) => { - cdef.symbol.annots.foreach { annot => - annot match { - case Apply(Select(New(t), _), - List(Literal(Constant(path: String)))) - if t.symbol.name == "SourceFile" => - // we found the path to a file. In this case, we do not need to - // continue traversing the tree - sourcePath = Some(path) - case x => super.traverseTree(tree) - } - true - } - } - case _ => { - // If we already found a sourcePath in this tasty file, - // we abort our search here to avoid spending too much time here - if (sourcePath == None) - super.traverseTree(tree) - else - () - } - } - } - ChildTraverser.traverseTree(root)(reflect.rootContext) - } -} diff --git a/semanticdb/src/dotty/semanticdb/Utils.scala b/semanticdb/src/dotty/semanticdb/Utils.scala deleted file mode 100644 index 1484eda68e2c..000000000000 --- a/semanticdb/src/dotty/semanticdb/Utils.scala +++ /dev/null @@ -1,83 +0,0 @@ -package dotty.semanticdb - - -import scala.tasty.file._ -import scala.collection.mutable.HashMap - -import org.junit.Test -import org.junit.Assert._ -import java.nio.file._ -import scala.meta.internal.{semanticdb => s} -import scala.collection.JavaConverters._ -import java.io.File -import scala.tasty.file.TastyConsumer -import java.lang.reflect.InvocationTargetException - -object Utils { - /** Infers a tuple (class path, class name) from a given path */ - def getClasspathClassname(file: Path): (String, String) = { - val pat = """(.*)\..*""".r - val classpath = file.getParent().getParent().toString() - val modulename = file.getParent().getFileName().toString() - val sourcename = - file.toFile().getName().toString() match { - case pat(name) => name - case _ => "" - } - return (classpath, modulename + "." + sourcename) - } - - /** List all tasty files occuring in the folder f or one of its subfolders */ - def recursiveListFiles(f: File, prefix : String = ""): Array[File] = { - val pattern = (".*" + prefix + ".*\\.tasty").r - val files = f.listFiles - val folders = files.filter(_.isDirectory) - val tastyfiles = files.filter(_.toPath.toString match { - case pattern(x: _*) => true - case _ => false - }) - tastyfiles ++ folders.flatMap(recursiveListFiles(_, prefix)) - } - - /** Returns a mapping from *.scala file to a list of tasty files. */ - def getTastyFiles(classPath: Path, prefix : String = ""): HashMap[String, List[Path]] = { - val sourceToTasty: HashMap[String, List[Path]] = HashMap() - val tastyfiles = recursiveListFiles(classPath.toFile(), prefix) - tastyfiles.map(tastyPath => { - val (classpath, classname) = getClasspathClassname(tastyPath.toPath()) - // We add an exception here to avoid crashing if we encountered - // a bad tasty file - try { - val inspecter = new TastyScalaFileInferrer - ConsumeTasty(classpath, classname :: Nil, inspecter) - inspecter.sourcePath.foreach( - source => - sourceToTasty += - (source -> (tastyPath - .toPath().toAbsolutePath :: sourceToTasty.getOrElse(source, Nil)))) - } catch { - case _: InvocationTargetException => () - } - }) - sourceToTasty - } - - /* - Returns the list of names of class defined inside the scala file [scalaFile] - extracted from the compilation artifacts found in [classPath]. - */ - def getClassNames(classPath: Path, scalaFile: Path, prefix : String = ""): List[String] = { - val tastyFiles = getTastyFiles(classPath.toAbsolutePath, prefix) - getClassNamesCached(scalaFile, tastyFiles) - } - - def getClassNamesCached(scalaFile: Path, allFiles : HashMap[String, List[Path]]): List[String] = { - val tastyFiles = - allFiles - .getOrElse(scalaFile.toString, Nil) - - val tastyClasses = tastyFiles.map(getClasspathClassname) - val (_, classnames) = tastyClasses.unzip - return classnames - } -} \ No newline at end of file diff --git a/semanticdb/test/dotty/semanticdb/MD5.scala b/semanticdb/test/dotty/semanticdb/MD5.scala deleted file mode 100644 index 4cd0f508b3c5..000000000000 --- a/semanticdb/test/dotty/semanticdb/MD5.scala +++ /dev/null @@ -1,29 +0,0 @@ -package dotty.semanticdb - -import java.nio.ByteBuffer -import java.nio.charset.StandardCharsets -import java.security.MessageDigest - -object MD5 { - /** Returns the MD5 finger print for this string */ - def compute(string: String): String = { - compute(ByteBuffer.wrap(string.getBytes(StandardCharsets.UTF_8))) - } - def compute(buffer: ByteBuffer): String = { - val md = MessageDigest.getInstance("MD5") - md.update(buffer) - bytesToHex(md.digest()) - } - private val hexArray = "0123456789ABCDEF".toCharArray - private def bytesToHex(bytes: Array[Byte]): String = { - val hexChars = new Array[Char](bytes.length * 2) - var j = 0 - while (j < bytes.length) { - val v: Int = bytes(j) & 0xFF - hexChars(j * 2) = hexArray(v >>> 4) - hexChars(j * 2 + 1) = hexArray(v & 0x0F) - j += 1 - } - new String(hexChars) - } -} \ No newline at end of file diff --git a/semanticdb/test/dotty/semanticdb/Semanticdbs.scala b/semanticdb/test/dotty/semanticdb/Semanticdbs.scala deleted file mode 100644 index 762673222ff5..000000000000 --- a/semanticdb/test/dotty/semanticdb/Semanticdbs.scala +++ /dev/null @@ -1,127 +0,0 @@ -package dotty.semanticdb - -import java.nio.file._ -import java.nio.charset.StandardCharsets -import scala.meta.internal.{semanticdb => s} -import scala.collection.JavaConverters._ -import dotty.tools.dotc.util.SourceFile - -object Semanticdbs { - private val buildSubFolder = "semanticdb/input/" - /** - * Utility to load SemanticDB for Scala source files. - * - * @param sourceroot The workspace root directory, by convention matches the directory of build.sbt - * @param classpath The classpath for this project, can be a combination of jars and directories. - * Matches the `fullClasspath` task key from sbt but can be only `classDirectory` - * if you only care about reading SemanticDB files from a single project. - */ - class Loader(sourceroot: Path, classpath: List[Path]) { - private val META_INF = Paths.get("META-INF", "semanticdb").resolve(buildSubFolder) - private val classLoader = new java.net.URLClassLoader(classpath.map(_.toUri.toURL).toArray) - /** Returns a SemanticDB for a single Scala source file, if any. The path must be absolute. */ - def resolve(scalaAbsolutePath: Path): Option[s.TextDocument] = { - val scalaRelativePath = sourceroot.relativize(scalaAbsolutePath) - val filename = scalaRelativePath.getFileName.toString - val semanticdbRelativePath = scalaRelativePath.resolveSibling(filename + ".semanticdb") - val metaInfPath = META_INF.resolve(semanticdbRelativePath).toString - Option(classLoader.findResource(metaInfPath)).map { url => - val semanticdbAbsolutePath = Paths.get(url.toURI) - Semanticdbs.loadTextDocument(scalaAbsolutePath, scalaRelativePath, semanticdbAbsolutePath) - } - } - } - - /** Load SemanticDB TextDocument for a single Scala source file - * - * @param scalaAbsolutePath Absolute path to a Scala source file. - * @param scalaRelativePath scalaAbsolutePath relativized by the sourceroot. - * @param semanticdbAbsolutePath Absolute path to the SemanticDB file. - */ - def loadTextDocument( - scalaAbsolutePath: Path, - scalaRelativePath: Path, - semanticdbAbsolutePath: Path - ): s.TextDocument = { - val reluri = buildSubFolder + scalaRelativePath.iterator.asScala.mkString("/") - val sdocs = parseTextDocuments(semanticdbAbsolutePath) - sdocs.documents.find(_.uri == reluri) match { - case None => throw new NoSuchElementException(reluri) - case Some(document) => - val text = new String(Files.readAllBytes(scalaAbsolutePath), StandardCharsets.UTF_8) - // Assert the SemanticDB payload is in-sync with the contents of the Scala file on disk. - val md5FingerprintOnDisk = MD5.compute(text) - if (document.md5 != md5FingerprintOnDisk) { - throw new IllegalArgumentException("stale semanticdb: " + reluri) - } else { - // Update text document to include full text contents of the file. - document.withText(text) - } - } - } - - /** Parses SemanticDB text documents from an absolute path to a `*.semanticdb` file. */ - def parseTextDocuments(path: Path): s.TextDocuments = { - // NOTE: a *.semanticdb file is of type s.TextDocuments, not s.TextDocument - val in = Files.newInputStream(path) - try s.TextDocuments.parseFrom(in) - finally in.close() - } - - - /** Prettyprint a text document with symbol occurrences next to each resolved identifier. - * - * Useful for testing purposes to ensure that SymbolOccurrence values make sense and are correct. - * Example output (NOTE, slightly modified to avoid "unclosed comment" errors): - * {{{ - * class Example *example/Example#* { - * val a *example/Example#a.* : String *scala/Predef.String#* = "1" - * } - * }}} - **/ - def printTextDocument(doc: s.TextDocument): String = { - val sb = new StringBuilder - val sourceFile = SourceFile.virtual(doc.uri, doc.text) - implicit val occurrenceOrdering: Ordering[s.SymbolOccurrence] = - buildOccurrenceOrdering(sourceFile) - val occurrences = doc.occurrences.sorted - var offset = 0 - occurrences.foreach { occ => - val range = occ.range.get - val end = sourceFile.lineToOffset(range.endLine) + range.endCharacter - sb.append(doc.text.substring(offset, end)) - sb.append(" /* ") - .append(occ.symbol) - .append(" */ ") - offset = end - } - sb.append(doc.text.substring(offset)) - sb.toString() - } - - /** Sort symbol occurrences by their start position. */ - def buildOccurrenceOrdering(sourceFile: SourceFile): Ordering[s.SymbolOccurrence] = { - new Ordering[s.SymbolOccurrence] { - def rangeToTuple(r : s.Range): (Int, Int) = { - val start = sourceFile.lineToOffset(r.startLine) + r.startCharacter - val end = sourceFile.lineToOffset(r.endLine) + r.endCharacter - (start, end) - } - - override def compare(x: s.SymbolOccurrence, y: s.SymbolOccurrence): Int = { - if (x.range.isEmpty) 0 - else if (y.range.isEmpty) 0 - else { - val (as, ae) = rangeToTuple(x.range.get) - val (bs, be) = rangeToTuple(y.range.get) - val byStart = Integer.compare(as, bs) - if (byStart != 0) { - byStart - } else { - Integer.compare(ae, be) - } - } - } - } - } -} diff --git a/semanticdb/test/dotty/semanticdb/Tests.scala b/semanticdb/test/dotty/semanticdb/Tests.scala deleted file mode 100644 index b412e45db6ec..000000000000 --- a/semanticdb/test/dotty/semanticdb/Tests.scala +++ /dev/null @@ -1,221 +0,0 @@ -package dotty.semanticdb - -import scala.tasty.file._ -import scala.collection.mutable.HashMap - -import org.junit.Test -import org.junit.Assert._ -import java.nio.file._ -import scala.meta.internal.{semanticdb => s} -import scala.collection.JavaConverters._ -import java.io.File -import scala.tasty.file.TastyConsumer -import java.lang.reflect.InvocationTargetException - -import dotty.semanticdb.Scala._ -import dotty.tools.dotc.util.SourceFile -import scala.math._ - -class Tests { - - def distance(r1: s.Range, sourceFile: SourceFile)(r2: s.Range): Int = { - val s1 = sourceFile.lineToOffset(max(r1.startLine, 0)) + r1.startCharacter - val s2 = sourceFile.lineToOffset(max(r2.startLine, 0)) + r2.startCharacter - val e1 = sourceFile.lineToOffset(max(r1.endLine, 0)) + r1.endCharacter - val e2 = sourceFile.lineToOffset(max(r2.endLine, 0)) + r2.endCharacter - max(abs(s1 - s2), abs(e1 - e2)) - } - - /* This is a most powerfull way to compare two lists of occurences - than just to print the diff. The diff will fail local symbols have not - the same numer (even if their is no conflicts) and will also fail for symbols - with small differences. - The goal here is to have a method returning true if the tasty occurences and - the scala occurences are the "same" (no local conflicts, positions can be slightly - different). */ - def compareOccurrences(tastyOccurrences: Seq[s.SymbolOccurrence], - scalaOccurrences: Seq[s.SymbolOccurrence], - sourceCode: String): Boolean = { - val sourceFile = SourceFile.virtual("", sourceCode) - val symbols = tastyOccurrences.groupBy(_.symbol) - val localTastyToScala = HashMap[String, String]() - val localScalaToTasty = HashMap[String, String]() - val translator = HashMap[(s.Range, String), s.SymbolOccurrence]() - - /* Check if we can translate the symbol [from] to the symbol [to] - True if their is no local clash (ex if we know local2 -> local3 then local2 clash with local4) - [from] is in tasty space, [to] in scala space - */ - def checkIfTranslatableSymbol(from: String, to: String): Boolean = { - if (from.isLocal != to.isLocal) { - false - } else { - if (from.isLocal) { - if (localTastyToScala.getOrElse(from, to) == to && - localScalaToTasty.getOrElse(to, from) == from) { - localTastyToScala += (from -> to) - localScalaToTasty += (to -> from) - true - } else { - false - } - } else { - true - } - } - } - - /* If we do not have the same number of occurrences in both lists we know we failed - the test */ - if (tastyOccurrences.length != scalaOccurrences.length) { - false - } else { - /* We associate every scala occurrence to the nearest tasty occurence with the - same name (if it is a global symbol) or local symbol */ - scalaOccurrences.forall(occurrence => { - if (occurrence.symbol.isLocal || - symbols.contains(localScalaToTasty.getOrElse(occurrence.symbol, - occurrence.symbol))) { - val siblings = - if (occurrence.symbol.isLocal) tastyOccurrences - else symbols(occurrence.symbol) - - val nearest = siblings.minBy(c => - distance(occurrence.range.get, sourceFile)(c.range.get)) - - /* If these two symbols can be translated, meaning: - - [nearest] was not associated with any other scala occurrence - - if [occurrence] is a local symbol it does not clash with [nearest] - - they are "near" in the source code */ - if (!checkIfTranslatableSymbol(nearest.symbol, occurrence.symbol) || - translator.contains((nearest.range.get, nearest.symbol)) || - distance(occurrence.range.get, sourceFile)(nearest.range.get) > 5) { - println( - checkIfTranslatableSymbol(nearest.symbol, occurrence.symbol)) - false - } else { - if (!occurrence.symbol.isLocal) - translator += ((nearest.range.get, nearest.symbol) -> occurrence) - true - } - } else { - false - } - }) - } - } - - final def tastyClassDirectory = { - val root = "out/bootstrap/dotty-semanticdb/" - val files = Paths.get(root).toFile().listFiles - val scalaFolderReg = """scala-(\d+)\.(\d+)""".r - val (_, _, path) = files - .collect(file => - file.getName match { - case scalaFolderReg(major, minor) => (major, minor, file.getName) - }) - .max - Paths.get(root, path, "test-classes") - } - - val sourceroot = Paths.get("semanticdb/input").toAbsolutePath - val sourceDirectory = sourceroot.resolve("src/main/scala") - val semanticdbClassDirectory = sourceroot.resolve("target/scala-2.12/classes") - val semanticdbLoader = - new Semanticdbs.Loader(sourceroot, List(semanticdbClassDirectory)) - - /** Returns the SemanticDB for this Scala source file. */ - def getScalacSemanticdb(scalaFile: Path): s.TextDocument = { - semanticdbLoader.resolve(scalaFile).get - } - - final def allTastyFiles = Utils.getTastyFiles(tastyClassDirectory, "example") - - /** Returns the SemanticDB for this Scala source file. */ - def getTastySemanticdb(classPath: Path, scalaFile: Path): s.TextDocument = { - val classNames = Utils.getClassNamesCached(scalaFile, allTastyFiles) - val sdbconsumer = new SemanticdbConsumer(scalaFile) - - val _ = ConsumeTasty(classPath.toString, classNames, sdbconsumer) - sdbconsumer.toSemanticdb() - } - - /** Fails the test if the s.TextDocument from tasty and semanticdb-scalac are not the same. */ - def checkFile(filename: String): Unit = { - val path = sourceDirectory.resolve(filename) - val scalac = getScalacSemanticdb(path) - val tasty = getTastySemanticdb(tastyClassDirectory, path) - val obtained = Semanticdbs.printTextDocument(tasty) - val expected = Semanticdbs.printTextDocument(scalac) - if (!compareOccurrences(tasty.occurrences, scalac.occurrences, scalac.text)) - assertNoDiff(obtained, expected) - } - - /** Fails the test with a pretty diff if there obtained is not the same as expected */ - def assertNoDiff(obtained: String, expected: String): Unit = { - if (obtained.isEmpty && !expected.isEmpty) fail("obtained empty output") - def splitLines(string: String): java.util.List[String] = - string.trim.replace("\r\n", "\n").split("\n").toSeq.asJava - val obtainedLines = splitLines(obtained) - val b = splitLines(expected) - val patch = difflib.DiffUtils.diff(obtainedLines, b) - val diff = - if (patch.getDeltas.isEmpty) "" - else { - difflib.DiffUtils - .generateUnifiedDiff( - "tasty", - "scala2", - obtainedLines, - patch, - 1 - ) - .asScala - .mkString("\n") - } - if (!diff.isEmpty) { - fail("\n" + diff) - } - } - - @Test def testAccess(): Unit = checkFile("example/Access.scala") - @Test def testAdvanced(): Unit = checkFile("example/Advanced.scala") - @Test def testAnonymous(): Unit = checkFile("example/Anonymous.scala") - @Test def testClasses(): Unit = checkFile("example/Classes.scala") - @Test def testEmpty(): Unit = checkFile("example/Empty.scala") - @Test def testEmptyObject(): Unit = checkFile("example/EmptyObject.scala") - @Test def testExample(): Unit = checkFile("example/Example.scala") - @Test def testExample2(): Unit = checkFile("example/Example2.scala") - @Test def testExclude(): Unit = checkFile("example/Exclude.scala") - @Test def testFlags(): Unit = checkFile("example/Flags.scala") - @Test def testIssue1749(): Unit = checkFile("example/Issue1749.scala") - @Test def testLocalFile(): Unit = checkFile("example/local-file.scala") - @Test def testLocals(): Unit = checkFile("example/Locals.scala") - //deactivated @Test def testMacroAnnotations(): Unit = checkFile("example/MacroAnnotations.scala") - @Test def testMethods(): Unit = checkFile("example/Methods.scala") - @Test def testMultiArguments(): Unit = - checkFile("example/MultiArguments.scala") - @Test def testObjects(): Unit = checkFile("example/Objects.scala") - @Test def testOverrides(): Unit = checkFile("example/Overrides.scala") - @Test def testPrefixes(): Unit = checkFile("example/Prefixes.scala") - @Test def testSelfs(): Unit = checkFile("example/Selfs.scala") - @Test def testSelfUse(): Unit = checkFile("example/SelfUse.scala") - @Test def testTraits(): Unit = checkFile("example/Traits.scala") - @Test def testTypes(): Unit = checkFile("example/Types.scala") - @Test def testTypesAnnotations(): Unit = - checkFile("example/TypesAnnotations.scala") - @Test def testVals(): Unit = checkFile("example/Vals.scala") - @Test def testDependantModule(): Unit = - checkFile("example/DependantModule.scala") - @Test def testNew(): Unit = checkFile("example/New.scala") - @Test def testIgnoredSymbol(): Unit = checkFile("example/IgnoredSymbol.scala") - @Test def testCase(): Unit = checkFile("example/Case.scala") - @Test def testApply(): Unit = checkFile("example/Apply.scala") - @Test def testMethodUsages(): Unit = checkFile("example/MethodUsages.scala") - @Test def testSuper(): Unit = checkFile("example/Super.scala") - @Test def testTypeBug(): Unit = checkFile("example/TypeBug.scala") - @Test def testSynthetic(): Unit = checkFile("example/Synthetic.scala") - @Test def testBinaryOp(): Unit = checkFile("example/BinaryOp.scala") - @Test def testDottyPredef(): Unit = checkFile("example/DottyPredef.scala") - -} diff --git a/semanticdb/test/tests/SimpleClass.scala b/semanticdb/test/tests/SimpleClass.scala deleted file mode 100644 index 6827e19bf8d6..000000000000 --- a/semanticdb/test/tests/SimpleClass.scala +++ /dev/null @@ -1,3 +0,0 @@ -package tests - -class SimpleClass diff --git a/semanticdb/test/tests/SimpleDef.scala b/semanticdb/test/tests/SimpleDef.scala deleted file mode 100644 index 15afc0d77be6..000000000000 --- a/semanticdb/test/tests/SimpleDef.scala +++ /dev/null @@ -1,5 +0,0 @@ -package tests - -class SimpleDef { - def foo(): Int = 0 -}