@@ -12,6 +12,7 @@ import Flags._
12
12
import Decorators ._
13
13
import Names .Name
14
14
import StdNames .nme
15
+ import util .Spans .Span
15
16
import util .{SourceFile , SourcePosition }
16
17
import collection .mutable
17
18
import java .lang .Character .{isJavaIdentifierPart , isJavaIdentifierStart }
@@ -48,52 +49,57 @@ class ExtractSemanticDB extends Phase {
48
49
override def default (key : Int ) = Set [Symbol ]()
49
50
}
50
51
52
+ private val generated = new mutable.HashSet [SymbolOccurrence ]
53
+
51
54
/** The extracted symbol occurrences */
52
55
val occurrences = new mutable.ListBuffer [SymbolOccurrence ]()
53
56
54
- /** The semanticdb name of the given symbol */
55
- private def symbolName ( sym : Symbol )(given ctx : Context ): String =
57
+ /** Add semanticdb name of the given symbol to string builder */
58
+ private def addSymName ( b : StringBuilder , sym : Symbol )(given ctx : Context ): Unit =
56
59
57
60
def isJavaIdent (str : String ) =
58
61
isJavaIdentifierStart(str.head) && str.tail.forall(isJavaIdentifierPart)
59
62
60
- def nameToString (name : Name ) =
63
+ def addName (name : Name ) =
61
64
val str = name.toString
62
- if isJavaIdent(str) then str else " `" + str + " `"
65
+ if isJavaIdent(str) then b.append(str)
66
+ else b.append('`' ).append(str).append('`' )
63
67
64
68
/** Is symbol global? Non-global symbols get localX names */
65
69
def isGlobal (sym : Symbol ): Boolean =
66
70
sym.is(Package )
67
71
|| (sym.is(Param ) || sym.owner.isClass) && isGlobal(sym.owner)
68
72
69
- def ownerString (owner : Symbol ): String =
70
- if owner.isRoot || owner.isEmptyPackage then " " else symbolName( owner)
73
+ def addOwner (owner : Symbol ): Unit =
74
+ if ! owner.isRoot && ! owner.isEmptyPackage then addSymName(b, owner)
71
75
72
- def overloadIdx (sym : Symbol ): String =
76
+ def addOverloadIdx (sym : Symbol ): Unit =
73
77
val alts = sym.owner.info.decls.lookupAll(sym.name).toList
74
- if alts.tail.isEmpty then " "
75
- else
78
+ if alts.tail.nonEmpty then
76
79
val idx = alts.indexOf(sym)
77
80
assert(idx >= 0 )
78
- " + " + idx.toString
81
+ b.append( '+' ).append( idx.toString)
79
82
80
- def descriptor (sym : Symbol ): String =
83
+ def addDescriptor (sym : Symbol ): Unit =
81
84
if sym.is(ModuleClass ) then
82
- descriptor(sym.sourceModule)
85
+ addDescriptor(sym.sourceModule)
86
+ else if sym.is(Param ) || sym.is(ParamAccessor ) then
87
+ b.append('(' ); addName(sym.name); b.append(')' )
88
+ else if sym.is(TypeParam ) then
89
+ b.append('[' ); addName(sym.name); b.append(']' )
83
90
else
84
- val str = nameToString(sym.name)
85
- if sym.is(Package ) then str + " /"
86
- else if sym.isType then str + " #"
87
- else if sym.isRealMethod then str + " (" + overloadIdx(sym) + " )"
88
- else if sym.is(TermParam ) || sym.is(ParamAccessor ) then " (" + str + " )"
89
- else if sym.is(TypeParam ) then " [" + str + " ]"
90
- else if sym.isTerm then str + " ."
91
+ addName(sym.name)
92
+ if sym.is(Package ) then b.append('/' )
93
+ else if sym.isType then b.append('#' )
94
+ else if sym.isRealMethod then
95
+ b.append('(' ); addOverloadIdx(sym); b.append(" )." )
96
+ else if sym.isTerm then b.append('.' )
91
97
else throw new AssertionError (i " unhandled symbol: $sym: ${sym.info} with ${sym.flagsString}" )
92
98
93
99
/** The index of local symbol `sym`. Symbols with the same name and
94
100
* the same starting position have the same index.
95
101
*/
96
- def localIdx (sym : Symbol )(given Context ): Int = {
102
+ def localIdx (sym : Symbol )(given Context ): Int =
97
103
def computeLocalIdx (): Int =
98
104
symsAtOffset(sym.span.start).find(_.name == sym.name) match
99
105
case Some (other) => localIdx(other)
@@ -104,47 +110,61 @@ class ExtractSemanticDB extends Phase {
104
110
symsAtOffset(sym.span.start) += sym
105
111
idx
106
112
locals.getOrElseUpdate(sym, computeLocalIdx())
107
- }
108
113
109
- if sym.isRoot then " _root_"
110
- else if sym.isEmptyPackage then " _empty_"
111
- else if isGlobal(sym) then ownerString(sym.owner) + descriptor(sym)
112
- else " local" + localIdx(sym)
113
- end symbolName
114
+ if sym.isRoot then
115
+ b.append(" _root_" )
116
+ else if sym.isEmptyPackage then
117
+ b.append(" _empty_" )
118
+ else if isGlobal(sym) then
119
+ addOwner(sym.owner); addDescriptor(sym)
120
+ else
121
+ b.append(" local" ).append(localIdx(sym))
122
+ end addSymName
123
+
124
+ /** The semanticdb name of the given symbol */
125
+ private def symbolName (sym : Symbol )(given ctx : Context ): String =
126
+ val b = StringBuilder ()
127
+ addSymName(b, sym)
128
+ b.toString
114
129
115
- private def range (pos : SourcePosition )(given Context ): Option [Range ] =
116
- val src = pos .source
130
+ private def range (span : Span )(given ctx : Context ): Option [Range ] =
131
+ val src = ctx.compilationUnit .source
117
132
def lineCol (offset : Int ) = (src.offsetToLine(offset), src.column(offset))
118
- val (startLine, startCol) = lineCol(pos. span.start)
119
- val (endLine, endCol) = lineCol(pos. span.end)
133
+ val (startLine, startCol) = lineCol(span.start)
134
+ val (endLine, endCol) = lineCol(span.end)
120
135
Some (Range (startLine, startCol, endLine, endCol))
121
136
122
137
private def excluded (sym : Symbol )(given Context ): Boolean =
123
138
! sym.exists || sym.isLocalDummy
124
139
125
- private def registerOccurrence (sym : Symbol , pos : SourcePosition , role : SymbolOccurrence .Role )(given Context ): Unit =
140
+ private def registerOccurrence (sym : Symbol , span : Span , role : SymbolOccurrence .Role )(given Context ): Unit =
126
141
if ! excluded(sym) then
127
- occurrences += SymbolOccurrence (symbolName(sym), range(pos), role)
142
+ val occ = SymbolOccurrence (symbolName(sym), range(span), role)
143
+ if ! generated.contains(occ) then
144
+ occurrences += occ
145
+ generated += occ
128
146
129
- private def registerUse (sym : Symbol , pos : SourcePosition )(given Context ) =
130
- registerOccurrence(sym, pos , SymbolOccurrence .Role .REFERENCE )
131
- private def registerDef (sym : Symbol , pos : SourcePosition )(given Context ) =
132
- registerOccurrence(sym, pos , SymbolOccurrence .Role .DEFINITION )
147
+ private def registerUse (sym : Symbol , span : Span )(given Context ) =
148
+ registerOccurrence(sym, span , SymbolOccurrence .Role .REFERENCE )
149
+ private def registerDef (sym : Symbol , span : Span )(given Context ) =
150
+ registerOccurrence(sym, span , SymbolOccurrence .Role .DEFINITION )
133
151
134
152
override def traverse (tree : Tree )(given ctx : Context ): Unit =
135
153
tree match
136
154
case tree : DefTree =>
137
- registerDef(tree.symbol, tree.sourcePos )
155
+ registerDef(tree.symbol, tree.span )
138
156
traverseChildren(tree)
139
157
case tree : RefTree =>
140
- registerUse(tree.symbol, tree.sourcePos )
158
+ registerUse(tree.symbol, tree.span )
141
159
traverseChildren(tree)
142
160
case tree : Import =>
143
161
for sel <- tree.selectors do
144
162
val imported = sel.imported.name
145
163
if imported != nme.WILDCARD then
146
164
for alt <- tree.expr.tpe.member(imported).alternatives do
147
- registerUse(alt.symbol, sel.imported.sourcePos)
165
+ registerUse(alt.symbol, sel.imported.span)
166
+ case tree : Inlined =>
167
+ traverse(tree.call)
148
168
case _ =>
149
169
traverseChildren(tree)
150
170
}
0 commit comments