Skip to content

Commit 7ae7356

Browse files
committed
Use buiders instead of String +
Using builders avoids temporary copies
1 parent bec1394 commit 7ae7356

File tree

1 file changed

+59
-39
lines changed

1 file changed

+59
-39
lines changed

compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Flags._
1212
import Decorators._
1313
import Names.Name
1414
import StdNames.nme
15+
import util.Spans.Span
1516
import util.{SourceFile, SourcePosition}
1617
import collection.mutable
1718
import java.lang.Character.{isJavaIdentifierPart, isJavaIdentifierStart}
@@ -48,52 +49,57 @@ class ExtractSemanticDB extends Phase {
4849
override def default(key: Int) = Set[Symbol]()
4950
}
5051

52+
private val generated = new mutable.HashSet[SymbolOccurrence]
53+
5154
/** The extracted symbol occurrences */
5255
val occurrences = new mutable.ListBuffer[SymbolOccurrence]()
5356

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 =
5659

5760
def isJavaIdent(str: String) =
5861
isJavaIdentifierStart(str.head) && str.tail.forall(isJavaIdentifierPart)
5962

60-
def nameToString(name: Name) =
63+
def addName(name: Name) =
6164
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('`')
6367

6468
/** Is symbol global? Non-global symbols get localX names */
6569
def isGlobal(sym: Symbol): Boolean =
6670
sym.is(Package)
6771
|| (sym.is(Param) || sym.owner.isClass) && isGlobal(sym.owner)
6872

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)
7175

72-
def overloadIdx(sym: Symbol): String =
76+
def addOverloadIdx(sym: Symbol): Unit =
7377
val alts = sym.owner.info.decls.lookupAll(sym.name).toList
74-
if alts.tail.isEmpty then ""
75-
else
78+
if alts.tail.nonEmpty then
7679
val idx = alts.indexOf(sym)
7780
assert(idx >= 0)
78-
"+" + idx.toString
81+
b.append('+').append(idx.toString)
7982

80-
def descriptor(sym: Symbol): String =
83+
def addDescriptor(sym: Symbol): Unit =
8184
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(']')
8390
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('.')
9197
else throw new AssertionError(i"unhandled symbol: $sym: ${sym.info} with ${sym.flagsString}")
9298

9399
/** The index of local symbol `sym`. Symbols with the same name and
94100
* the same starting position have the same index.
95101
*/
96-
def localIdx(sym: Symbol)(given Context): Int = {
102+
def localIdx(sym: Symbol)(given Context): Int =
97103
def computeLocalIdx(): Int =
98104
symsAtOffset(sym.span.start).find(_.name == sym.name) match
99105
case Some(other) => localIdx(other)
@@ -104,47 +110,61 @@ class ExtractSemanticDB extends Phase {
104110
symsAtOffset(sym.span.start) += sym
105111
idx
106112
locals.getOrElseUpdate(sym, computeLocalIdx())
107-
}
108113

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
114129

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
117132
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)
120135
Some(Range(startLine, startCol, endLine, endCol))
121136

122137
private def excluded(sym: Symbol)(given Context): Boolean =
123138
!sym.exists || sym.isLocalDummy
124139

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 =
126141
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
128146

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)
133151

134152
override def traverse(tree: Tree)(given ctx: Context): Unit =
135153
tree match
136154
case tree: DefTree =>
137-
registerDef(tree.symbol, tree.sourcePos)
155+
registerDef(tree.symbol, tree.span)
138156
traverseChildren(tree)
139157
case tree: RefTree =>
140-
registerUse(tree.symbol, tree.sourcePos)
158+
registerUse(tree.symbol, tree.span)
141159
traverseChildren(tree)
142160
case tree: Import =>
143161
for sel <- tree.selectors do
144162
val imported = sel.imported.name
145163
if imported != nme.WILDCARD then
146164
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)
148168
case _ =>
149169
traverseChildren(tree)
150170
}

0 commit comments

Comments
 (0)