@@ -2,42 +2,138 @@ package dotty.semanticdb
2
2
3
3
import scala .tasty .Reflection
4
4
import scala .tasty .file ._
5
+ import scala .collection .mutable .HashMap
5
6
6
7
import org .junit .Test
7
8
import org .junit .Assert ._
8
9
import java .nio .file ._
9
10
import scala .meta .internal .{semanticdb => s }
10
11
import 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
+ }
11
49
12
50
class Tests {
13
51
14
52
// 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"
16
55
val sourceroot = Paths .get(" semanticdb" , " input" ).toAbsolutePath
17
56
val sourceDirectory = sourceroot.resolve(" src/main/scala" )
18
57
19
58
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
+
21
66
/** Returns the SemanticDB for this Scala source file. */
22
67
def getScalacSemanticdb (scalaFile : Path ): s.TextDocument = {
23
68
semanticdbLoader.resolve(scalaFile).get
24
69
}
25
70
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()
32
111
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 _ => " "
36
115
}
37
- val sdbconsumer = new SemanticdbConsumer
38
- val _ = ConsumeTasty (classpath, (modulename + " ." + sourcename) :: Nil , sdbconsumer)
39
- sdbconsumer.toSemanticdb(scalac.text)
116
+ return (classpath, modulename + " ." + sourcename)
117
+ }
40
118
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
+ }
41
137
}
42
138
43
139
/** Fails the test if the s.TextDocument from tasty and semanticdb-scalac are not the same. */
@@ -61,9 +157,16 @@ class Tests {
61
157
val diff =
62
158
if (patch.getDeltas.isEmpty) " "
63
159
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 " )
67
170
}
68
171
if (! diff.isEmpty) {
69
172
fail(" \n " + diff)
0 commit comments