@@ -18,6 +18,11 @@ import collection.mutable
18
18
import java .lang .Character .{isJavaIdentifierPart , isJavaIdentifierStart }
19
19
import java .nio .file .Paths
20
20
21
+ /** Extract symbol references and uses to semanticdb files.
22
+ * See https://scalameta.org/docs/semanticdb/specification.html#symbol-1
23
+ * for a description of the format.
24
+ * TODO: Also extract type information
25
+ */
21
26
class ExtractSemanticDB extends Phase {
22
27
import ast .tpd ._
23
28
@@ -127,35 +132,48 @@ class ExtractSemanticDB extends Phase {
127
132
addSymName(b, sym)
128
133
b.toString
129
134
135
+ private def source (given ctx : Context ) = ctx.compilationUnit.source
136
+
130
137
private def range (span : Span )(given ctx : Context ): Option [Range ] =
131
- val src = ctx.compilationUnit.source
132
- def lineCol (offset : Int ) = (src.offsetToLine(offset), src.column(offset))
138
+ def lineCol (offset : Int ) = (source.offsetToLine(offset), source.column(offset))
133
139
val (startLine, startCol) = lineCol(span.start)
134
140
val (endLine, endCol) = lineCol(span.end)
135
141
Some (Range (startLine, startCol, endLine, endCol))
136
142
137
- private def excluded (sym : Symbol )(given Context ): Boolean =
138
- ! sym.exists || sym.isLocalDummy
143
+ private def excludeDef (sym : Symbol )(given Context ): Boolean =
144
+ ! sym.exists || sym.isLocalDummy || sym.is(Synthetic )
145
+
146
+ private def excludeUse (sym : Symbol , span : Span )(given Context ): Boolean =
147
+ excludeDef(sym) && span.start == span.end
139
148
140
149
private def registerOccurrence (sym : Symbol , span : Span , role : SymbolOccurrence .Role )(given Context ): Unit =
141
- if ! excluded(sym) then
142
- val occ = SymbolOccurrence (symbolName(sym), range(span), role)
143
- if ! generated.contains(occ) then
144
- occurrences += occ
145
- generated += occ
150
+ val occ = SymbolOccurrence (symbolName(sym), range(span), role)
151
+ if ! generated.contains(occ) then
152
+ occurrences += occ
153
+ generated += occ
146
154
147
155
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 )
156
+ if ! excludeUse(sym, span) then
157
+ registerOccurrence(sym, span, SymbolOccurrence .Role .REFERENCE )
151
158
152
159
override def traverse (tree : Tree )(given ctx : Context ): Unit =
160
+ // println(i"reg $tree")
153
161
tree match
154
- case tree : DefTree =>
155
- registerDef (tree.symbol, tree.span)
162
+ case tree : DefTree if ! excludeDef(tree.symbol) =>
163
+ registerOccurrence (tree.symbol, tree.span, SymbolOccurrence . Role . DEFINITION )
156
164
traverseChildren(tree)
157
- case tree : RefTree =>
165
+ case tree : Ident =>
158
166
registerUse(tree.symbol, tree.span)
167
+ case tree : Select =>
168
+ if ! excludeUse(tree.symbol, tree.span) then
169
+ val end = tree.span.end
170
+ val limit = tree.qualifier.span.end
171
+ val start =
172
+ if limit < end then
173
+ val len = tree.name.toString.length
174
+ if source.content()(end - 1 ) == '`' then end - len - 1 else end - len
175
+ else limit
176
+ registerUse(tree.symbol, Span (start max limit, end))
159
177
traverseChildren(tree)
160
178
case tree : Import =>
161
179
for sel <- tree.selectors do
0 commit comments