@@ -2,42 +2,138 @@ package dotty.semanticdb
22
33import scala .tasty .Reflection
44import scala .tasty .file ._
5+ import scala .collection .mutable .HashMap
56
67import org .junit .Test
78import org .junit .Assert ._
89import java .nio .file ._
910import scala .meta .internal .{semanticdb => s }
1011import scala .collection .JavaConverters ._
12+ import java .io .File
13+ import scala .tasty .Reflection
14+ import scala .tasty .file .TastyConsumer
15+ import java .lang .reflect .InvocationTargetException
16+
17+ class TastyInspecter extends TastyConsumer {
18+ var source_path : Option [String ] = None
19+ final def apply (reflect : Reflection )(root : reflect.Tree ): Unit = {
20+ import reflect ._
21+ object ChildTraverser extends TreeTraverser {
22+ override def traverseTree (tree : Tree )(implicit ctx : Context ): Unit =
23+ tree match {
24+ case IsClassDef (cdef) => {
25+ cdef.symbol.annots.foreach { annot =>
26+ annot match {
27+ case Term .Apply (Term .Select (Term .New (t), _, _),
28+ List (Term .Literal (Constant .String (path))))
29+ if t.symbol.name == " SourceFile" =>
30+ // we found the path to a file. In this case, we do not need to
31+ // continue traversing the tree
32+ source_path = Some (path)
33+ case x => super .traverseTree(tree)
34+ }
35+ true
36+ }
37+ }
38+ case _ => {
39+ if (source_path == None )
40+ super .traverseTree(tree)
41+ else
42+ ()
43+ }
44+ }
45+ }
46+ ChildTraverser .traverseTree(root)(reflect.rootContext)
47+ }
48+ }
1149
1250class Tests {
1351
1452 // TODO: update scala-0.10 on version change (or resolve automatically)
15- final def tastyClassDirectory = " out/bootstrap/dotty-semanticdb/scala-0.11/test-classes"
53+ final def tastyClassDirectory =
54+ " out/bootstrap/dotty-semanticdb/scala-0.11/test-classes"
1655 val sourceroot = Paths .get(" semanticdb" , " input" ).toAbsolutePath
1756 val sourceDirectory = sourceroot.resolve(" src/main/scala" )
1857
1958 val semanticdbClassDirectory = sourceroot.resolve(" target/scala-2.12/classes" )
20- val semanticdbLoader = new Semanticdbs .Loader (sourceroot, List (semanticdbClassDirectory))
59+ val semanticdbLoader =
60+ new Semanticdbs .Loader (sourceroot, List (semanticdbClassDirectory))
61+
62+ val source_to_tasty =
63+ getTastyFiles(
64+ Paths .get(" out" , " bootstrap" , " dotty-semanticdb/" ).toAbsolutePath)
65+
2166 /** Returns the SemanticDB for this Scala source file. */
2267 def getScalacSemanticdb (scalaFile : Path ): s.TextDocument = {
2368 semanticdbLoader.resolve(scalaFile).get
2469 }
2570
26- /** TODO: Produce semanticdb from TASTy for this Scala source file. */
27- def getTastySemanticdb (scalaFile : Path ): s.TextDocument = {
28- val scalac = getScalacSemanticdb(scalaFile)
29- val pat = """ (.*)\.scala""" .r
30- val classpath = scalaFile.getParent().toString()
31- val modulename = sourceDirectory.relativize(scalaFile).getParent().getFileName().toString()
71+ /** List all tasty files occuring in the folder f or one of its subfolders */
72+ def recursiveListFiles (f : File ): Array [File ] = {
73+ val pattern = " .*test-classes/example.*\\ .tasty" .r
74+ val files = f.listFiles
75+ val folders = files.filter(_.isDirectory)
76+ val tastyfiles = files.filter(_.toString match {
77+ case pattern(x : _* ) => true
78+ case _ => false
79+ })
80+ tastyfiles ++ folders.flatMap(recursiveListFiles)
81+ }
82+
83+ /** Returns a mapping from *.scala file to a list of tasty files. */
84+ def getTastyFiles (artifactsPath : Path ): HashMap [String , List [Path ]] = {
85+ val source_to_tasty : HashMap [String , List [Path ]] = HashMap ()
86+ val tastyfiles = recursiveListFiles(artifactsPath.toFile())
87+ recursiveListFiles(artifactsPath.toFile()).map(tasty_path => {
88+ val (classpath, classname) = getClasspathClassname(tasty_path.toPath())
89+ // We add an exception here to avoid crashing if we encountered
90+ // a bad tasty file
91+ try {
92+ val inspecter = new TastyInspecter
93+ ConsumeTasty (classpath, classname :: Nil , inspecter)
94+ inspecter.source_path.foreach(
95+ source =>
96+ source_to_tasty +=
97+ (source -> (tasty_path
98+ .toPath() :: source_to_tasty.getOrElse(source, Nil ))))
99+ } catch {
100+ case _ : InvocationTargetException => println(tasty_path)
101+ }
102+ })
103+ source_to_tasty
104+ }
105+
106+ /** Infers a tuple (class path, class name) from a given path */
107+ def getClasspathClassname (file : Path ): (String , String ) = {
108+ val pat = """ (.*)\..*""" .r
109+ val classpath = file.getParent().getParent().toString()
110+ val modulename = file.getParent().getFileName().toString()
32111 val sourcename =
33- scalaFile .toFile().getName().toString() match {
34- case pat(name) => name
35- case _ => " "
112+ file .toFile().getName().toString() match {
113+ case pat(name) => name
114+ case _ => " "
36115 }
37- val sdbconsumer = new SemanticdbConsumer
38- val _ = ConsumeTasty (classpath, (modulename + " ." + sourcename) :: Nil , sdbconsumer)
39- sdbconsumer.toSemanticdb(scalac.text)
116+ return (classpath, modulename + " ." + sourcename)
117+ }
40118
119+ def getTastySemanticdb (scalaFile : Path ): s.TextDocument = {
120+ val scalac = getScalacSemanticdb(scalaFile)
121+
122+ val tasty_files = source_to_tasty.getOrElse(
123+ sourceDirectory.resolve(scalaFile).toString,
124+ Nil )
125+
126+ val tasty_classes = tasty_files.map(getClasspathClassname)
127+ // If we have more than one classpath then something went wrong
128+ if (tasty_classes.groupBy((a, _) => a).size != 1 ) {
129+ scalac
130+ } else {
131+ val (classpaths, classnames) = tasty_classes.unzip
132+ val sdbconsumer = new SemanticdbConsumer
133+
134+ val _ = ConsumeTasty (classpaths.head, classnames, sdbconsumer)
135+ sdbconsumer.toSemanticdb(scalac.text)
136+ }
41137 }
42138
43139 /** Fails the test if the s.TextDocument from tasty and semanticdb-scalac are not the same. */
@@ -61,9 +157,16 @@ class Tests {
61157 val diff =
62158 if (patch.getDeltas.isEmpty) " "
63159 else {
64- difflib.DiffUtils .generateUnifiedDiff(
65- " tasty" , " scala2" , obtainedLines, patch, 1
66- ).asScala.mkString(" \n " )
160+ difflib.DiffUtils
161+ .generateUnifiedDiff(
162+ " tasty" ,
163+ " scala2" ,
164+ obtainedLines,
165+ patch,
166+ 1
167+ )
168+ .asScala
169+ .mkString(" \n " )
67170 }
68171 if (! diff.isEmpty) {
69172 fail(" \n " + diff)
0 commit comments