@@ -28,28 +28,30 @@ class ExtractSemanticDB extends Phase {
28
28
// Check not needed since it does not transform trees
29
29
override def isCheckable : Boolean = false
30
30
31
- // def genInfo(unit: CompilationUnit, occurrences: List[SymbolOccurrence])
32
-
33
31
override def run (implicit ctx : Context ): Unit = {
34
32
val extract = Extractor ()
35
33
val unit = ctx.compilationUnit
36
34
extract.traverse(unit.tpdTree)
37
35
ExtractSemanticDB .write(unit.source, extract.occurrences.toList)
38
36
}
39
37
38
+ /** Extractor of symbol occurrences from trees */
40
39
class Extractor extends TreeTraverser {
41
40
42
- private val locals = mutable. HashMap [ Symbol , Int ]()
41
+ private var nextLocalIdx : Int = 0
43
42
44
- val occurrences = new mutable.ListBuffer [SymbolOccurrence ]()
43
+ /** The index of a local symbol */
44
+ private val locals = mutable.HashMap [Symbol , Int ]()
45
45
46
- val localIndex = mutable.HashMap [Int , Int ]()
46
+ /** The local symbol(s) starting at given offset */
47
+ private val symsAtOffset = new mutable.HashMap [Int , Set [Symbol ]]() {
48
+ override def default (key : Int ) = Set [Symbol ]()
49
+ }
47
50
48
- private var myLocalIdx : Int = - 1
49
- private def nextLocalIdx () =
50
- myLocalIdx += 1
51
- myLocalIdx
51
+ /** The extracted symbol occurrences */
52
+ val occurrences = new mutable.ListBuffer [SymbolOccurrence ]()
52
53
54
+ /** The semanticdb name of the given symbol */
53
55
private def symbolName (sym : Symbol )(given ctx : Context ): String =
54
56
55
57
def isJavaIdent (str : String ) =
@@ -59,6 +61,7 @@ class ExtractSemanticDB extends Phase {
59
61
val str = name.toString
60
62
if isJavaIdent(str) then str else " `" + str + " `"
61
63
64
+ /** Is symbol global? Non-global symbols get localX names */
62
65
def isGlobal (sym : Symbol ): Boolean =
63
66
sym.is(Package )
64
67
|| (sym.is(Param ) || sym.owner.isClass) && isGlobal(sym.owner)
@@ -87,8 +90,21 @@ class ExtractSemanticDB extends Phase {
87
90
else if sym.isTerm then str + " ."
88
91
else throw new AssertionError (i " unhandled symbol: $sym: ${sym.info} with ${sym.flagsString}" )
89
92
90
- def localIdx (sym : Symbol )(given Context ): Int =
91
- localIndex.getOrElseUpdate(sym.span.start, nextLocalIdx())
93
+ /** The index of local symbol `sym`. Symbols with the same name and
94
+ * the same starting position have the same index.
95
+ */
96
+ def localIdx (sym : Symbol )(given Context ): Int = {
97
+ def computeLocalIdx (): Int =
98
+ symsAtOffset(sym.span.start).find(_.name == sym.name) match
99
+ case Some (other) => localIdx(other)
100
+ case None =>
101
+ val idx = nextLocalIdx
102
+ nextLocalIdx += 1
103
+ locals(sym) = idx
104
+ symsAtOffset(sym.span.start) += sym
105
+ idx
106
+ locals.getOrElseUpdate(sym, computeLocalIdx())
107
+ }
92
108
93
109
if sym.isRoot then " _root_"
94
110
else if sym.isEmptyPackage then " _empty_"
@@ -108,7 +124,6 @@ class ExtractSemanticDB extends Phase {
108
124
109
125
private def registerOccurrence (sym : Symbol , pos : SourcePosition , role : SymbolOccurrence .Role )(given Context ): Unit =
110
126
if ! excluded(sym) then
111
- // println(i"register: ${symbolName(sym)}")
112
127
occurrences += SymbolOccurrence (symbolName(sym), range(pos), role)
113
128
114
129
private def registerUse (sym : Symbol , pos : SourcePosition )(given Context ) =
0 commit comments