Skip to content

Commit 9cb1d0a

Browse files
committed
inspect inside definitions with a numbered empty name
1 parent b31542b commit 9cb1d0a

File tree

6 files changed

+168
-105
lines changed

6 files changed

+168
-105
lines changed

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ object Trees {
342342
* a calling chain from `viewExists`), in that case the return position is NoSpan.
343343
* Overridden in Bind
344344
*/
345-
def nameSpan: Span =
345+
def nameSpan: Span =
346346
if (span.exists) {
347347
val point = span.point
348348
if (rawMods.is(Synthetic) || name.toTermName == nme.ERROR) Span(point)

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

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import StdNames.nme
1313
import util.Spans.Span
1414
import util.{SourceFile, SourcePosition}
1515
import collection.mutable
16-
import java.lang.Character.{isJavaIdentifierPart, isJavaIdentifierStart}
1716
import java.nio.file.Paths
1817

1918
import ast.untpd.given
@@ -112,7 +111,8 @@ class ExtractSemanticDB extends Phase with
112111

113112
tree match
114113
case tree: PackageDef =>
115-
if !excludeDef(tree.pid.symbol) && tree.pid.span.hasLength
114+
if !excludeDef(tree.pid.symbol)
115+
&& tree.pid.span.hasLength
116116
tree.pid match
117117
case tree @ Select(qual, name) =>
118118
registerDefinition(tree.symbol, adjustSpanToName(tree.span, qual.span, name), Set.empty)
@@ -122,26 +122,31 @@ class ExtractSemanticDB extends Phase with
122122
case tree: NamedDefTree =>
123123
if tree.symbol.isAllOf(ModuleValCreationFlags)
124124
return
125-
if !excludeDef(tree.symbol) && tree.span.hasLength
125+
if !excludeDef(tree.symbol)
126+
&& tree.span.hasLength
126127
registerDefinition(tree.symbol, tree.nameSpan, symbolKinds(tree))
127128
val privateWithin = tree.symbol.privateWithin
128129
if privateWithin.exists
129130
registerUse(privateWithin, spanOfSymbol(privateWithin, tree.span))
130131
else if !excludeSymbolStrict(tree.symbol)
131132
registerSymbol(tree.symbol, symbolName(tree.symbol), symbolKinds(tree))
132133
tree match
133-
case tree: ValDef if tree.symbol.isAllOf(EnumValue) =>
134+
case tree: ValDef
135+
if tree.symbol.isAllOf(EnumValue) =>
134136
tree.rhs match
135137
case Block(TypeDef(_, template: Template) :: _, _) => // simple case with specialised extends clause
136138
template.parents.foreach(traverse)
137139
case _ => // calls $new
138-
case tree: ValDef if tree.symbol.isSelfSym =>
140+
case tree: ValDef
141+
if tree.symbol.isSelfSym =>
139142
if tree.tpt.span.hasLength
140143
traverse(tree.tpt)
141-
case tree: DefDef if tree.symbol.isConstructor => // ignore typeparams for secondary ctors
144+
case tree: DefDef
145+
if tree.symbol.isConstructor => // ignore typeparams for secondary ctors
142146
tree.vparamss.foreach(_.foreach(traverse))
143147
traverse(tree.rhs)
144-
case tree: (DefDef | ValDef) if tree.symbol.isSyntheticWithIdent =>
148+
case tree: (DefDef | ValDef)
149+
if tree.symbol.isSyntheticWithIdent =>
145150
tree match
146151
case tree: DefDef =>
147152
tree.tparams.foreach(tparam => registerSymbolSimple(tparam.symbol))
@@ -211,19 +216,11 @@ class ExtractSemanticDB extends Phase with
211216
/** Add semanticdb name of the given symbol to string builder */
212217
private def addSymName(b: StringBuilder, sym: Symbol)(given ctx: Context): Unit =
213218

214-
def isJavaIdent(str: String) =
215-
isJavaIdentifierStart(str.head) && str.tail.forall(isJavaIdentifierPart)
216-
217219
def addName(name: Name) =
218220
val str = name.toString.unescapeUnicode
219-
if isJavaIdent(str) then b append str
221+
if str.isJavaIdent then b append str
220222
else b append '`' append str append '`'
221223

222-
/** Is symbol global? Non-global symbols get localNå names */
223-
def isGlobal(sym: Symbol): Boolean =
224-
sym.is(Package)
225-
|| !sym.isSelfSym && (sym.is(Param) || sym.owner.isClass) && isGlobal(sym.owner)
226-
227224
def addOwner(owner: Symbol): Unit =
228225
if !owner.isRoot then addSymName(b, owner)
229226

@@ -280,7 +277,7 @@ class ExtractSemanticDB extends Phase with
280277
locals.getOrElseUpdate(sym, computeLocalIdx())
281278

282279
if sym.exists then
283-
if isGlobal(sym) then
280+
if sym.isGlobal then
284281
addOwner(sym.owner); addDescriptor(sym)
285282
else
286283
b.append(Symbols.LocalPrefix).append(localIdx(sym))
@@ -301,10 +298,6 @@ class ExtractSemanticDB extends Phase with
301298
val (endLine, endCol) = lineCol(span.end)
302299
Some(Range(startLine, startCol, endLine, endCol))
303300

304-
private inline def (name: Name) isEmptyNumbered: Boolean = name match
305-
case NameKinds.AnyNumberedName(nme.EMPTY, _) => true
306-
case _ => false
307-
308301
private def symbolKind(sym: Symbol, symkinds: Set[SymbolKind])(given Context): SymbolInformation.Kind =
309302
if sym.isTypeParam
310303
SymbolInformation.Kind.TYPE_PARAMETER
@@ -457,7 +450,7 @@ class ExtractSemanticDB extends Phase with
457450
case Nil => Nil
458451

459452
private def (sym: Symbol) adjustIfCtorTyparam(given Context) =
460-
if sym.isType && sym.owner.isConstructor
453+
if sym.isType && sym.owner.exists && sym.owner.isConstructor
461454
matchingMemberType(sym, sym.owner.owner)
462455
else
463456
sym

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

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
package dotty.tools.dotc.semanticdb
22

3-
import dotty.tools.dotc.core.Symbols.{ Symbol , defn }
4-
import dotty.tools.dotc.core.Contexts.Context
5-
import dotty.tools.dotc.core.Names
6-
import dotty.tools.dotc.core.Names.Name
7-
import dotty.tools.dotc.core.Types.Type
8-
import dotty.tools.dotc.core.Flags._
9-
import dotty.tools.dotc.core.NameKinds
10-
import dotty.tools.dotc.core.NameOps
11-
import dotty.tools.dotc.core.StdNames.nme
3+
import dotty.tools.dotc.core
4+
import core.Symbols.{ Symbol , defn }
5+
import core.Contexts.Context
6+
import core.Names
7+
import core.Names.Name
8+
import core.Types.Type
9+
import core.Flags._
10+
import core.NameKinds
11+
import core.StdNames.nme
12+
13+
import java.lang.Character.{isJavaIdentifierPart, isJavaIdentifierStart}
1214

1315
import scala.annotation.internal.sharable
1416
import scala.annotation.switch
1517

1618
object Scala3 with
1719
import Symbols._
18-
import NameOps.given
20+
import core.NameOps.given
1921

2022
@sharable private val unicodeEscape = raw"\$$u(\p{XDigit}{4})".r
2123
@sharable private val locals = raw"local(\d+)".r
@@ -44,7 +46,6 @@ object Scala3 with
4446

4547
object Symbols with
4648

47-
val NoSymbol: String = ""
4849
val RootPackage: String = "_root_/"
4950
val EmptyPackage: String = "_empty_/"
5051
val LocalPrefix: String = "local"
@@ -66,7 +67,7 @@ object Scala3 with
6667

6768
end Symbols
6869

69-
given nameOps: (name: Name) with
70+
given NameOps: (name: Name) with
7071

7172
def isWildcard = name match
7273
case nme.WILDCARD | WILDCARDTypeName => true
@@ -79,9 +80,16 @@ object Scala3 with
7980
case NameKinds.ModuleClassName(original) => original.isScala2PackageObjectName
8081
case _ => false
8182

82-
end nameOps
83+
def isEmptyNumbered: Boolean =
84+
!name.is(NameKinds.WildcardParamName)
85+
&& { name match
86+
case NameKinds.AnyNumberedName(nme.EMPTY, _) => true
87+
case _ => false
88+
}
8389

84-
given symbolOps: (sym: Symbol) with
90+
end NameOps
91+
92+
given SymbolOps: (sym: Symbol) with
8593

8694
def isScala2PackageObject(given Context): Boolean =
8795
sym.name.isScala2PackageObjectName && sym.owner.is(Package) && sym.is(Module)
@@ -101,54 +109,64 @@ object Scala3 with
101109

102110
sym.owner.info.decls.find(s => s.name == setterName && s.info.matchingType)
103111

112+
/** Is symbol global? Non-global symbols get localN names */
113+
def isGlobal(given Context): Boolean =
114+
sym.is(Package)
115+
|| !sym.isSelfSym && (sym.is(Param) || sym.owner.isClass) && sym.owner.isGlobal
116+
117+
def isLocalWithinSameName(given Context): Boolean =
118+
sym.exists && !sym.isGlobal && sym.name == sym.owner.name
104119

120+
/** Synthetic symbols that are not anonymous or numbered empty ident */
105121
def isSyntheticWithIdent(given Context): Boolean =
106-
sym.is(Synthetic) && !sym.isAnonymous
122+
sym.is(Synthetic) && !sym.isAnonymous && !sym.name.isEmptyNumbered
107123

108-
end symbolOps
124+
end SymbolOps
109125

110126
object LocalSymbol with
111-
def unapply(symbolInfo: SymbolInformation): Option[Int] =
112-
symbolInfo.symbol match
113127

114-
case locals(ints) =>
115-
val bi = BigInt(ints)
116-
if bi.isValidInt
117-
Some(bi.toInt)
118-
else
119-
None
128+
def unapply(symbolInfo: SymbolInformation): Option[Int] = symbolInfo.symbol match
129+
case locals(ints) =>
130+
val bi = BigInt(ints)
131+
if bi.isValidInt
132+
Some(bi.toInt)
133+
else
134+
None
120135

121-
case _ => None
136+
case _ => None
122137

123138
end LocalSymbol
124139

125140
private inline def (char: Char) `is/.#])` = (char: @switch) match
126141
case '/' | '.' | '#' | ']' | ')' => true
127142
case _ => false
128143

129-
given stringOps: (symbol: String) with
144+
given StringOps: (symbol: String) with
130145

131-
def isNoSymbol: Boolean = NoSymbol == symbol
146+
def isSymbol: Boolean = !symbol.isEmpty
132147
def isRootPackage: Boolean = RootPackage == symbol
133148
def isEmptyPackage: Boolean = EmptyPackage == symbol
134149

135-
def isGlobal: Boolean = !symbol.isNoSymbol && !symbol.isMulti && symbol.last.`is/.#])`
136-
def isLocal: Boolean = !symbol.isNoSymbol && !symbol.isMulti && !symbol.last.`is/.#])`
150+
def isGlobal: Boolean = !symbol.isEmpty && !symbol.isMulti && symbol.last.`is/.#])`
151+
def isLocal: Boolean = !symbol.isEmpty && !symbol.isMulti && !symbol.last.`is/.#])`
137152
def isMulti: Boolean = symbol startsWith ";"
138153

139154
def isConstructor: Boolean = ctor matches symbol
140-
def isPackage: Boolean = !symbol.isNoSymbol && !symbol.isMulti && symbol.last == '/'
141-
def isTerm: Boolean = !symbol.isNoSymbol && !symbol.isMulti && symbol.last == '.'
142-
def isType: Boolean = !symbol.isNoSymbol && !symbol.isMulti && symbol.last == '#'
143-
def isTypeParameter: Boolean = !symbol.isNoSymbol && !symbol.isMulti && symbol.last == ']'
144-
def isParameter: Boolean = !symbol.isNoSymbol && !symbol.isMulti && symbol.last == ')'
155+
def isPackage: Boolean = !symbol.isEmpty && !symbol.isMulti && symbol.last == '/'
156+
def isTerm: Boolean = !symbol.isEmpty && !symbol.isMulti && symbol.last == '.'
157+
def isType: Boolean = !symbol.isEmpty && !symbol.isMulti && symbol.last == '#'
158+
def isTypeParameter: Boolean = !symbol.isEmpty && !symbol.isMulti && symbol.last == ']'
159+
def isParameter: Boolean = !symbol.isEmpty && !symbol.isMulti && symbol.last == ')'
145160

146161
def unescapeUnicode =
147162
unicodeEscape.replaceAllIn(symbol, m => String.valueOf(Integer.parseInt(m.group(1), 16).toChar))
148163

149-
end stringOps
164+
def isJavaIdent =
165+
isJavaIdentifierStart(symbol.head) && symbol.tail.forall(isJavaIdentifierPart)
166+
167+
end StringOps
150168

151-
given infoOps: (info: SymbolInformation) with
169+
given InfoOps: (info: SymbolInformation) with
152170

153171
def isAbstract: Boolean = (info.properties & SymbolInformation.Property.ABSTRACT.value) != 0
154172
def isFinal: Boolean = (info.properties & SymbolInformation.Property.FINAL.value) != 0
@@ -182,6 +200,6 @@ object Scala3 with
182200
def isTrait: Boolean = info.kind.isTrait
183201
def isInterface: Boolean = info.kind.isInterface
184202

185-
end infoOps
203+
end InfoOps
186204

187205
end Scala3

tests/semanticdb/expect/Synthetic.expect.scala

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ class Synthetic/*<-example::Synthetic#*/ {
99

1010
// See https://github.com/scalameta/scalameta/issues/977
1111
val Name/*<-example::Synthetic#Name.*/ = /*->scala::Predef.augmentString().*/"name:(.*)".r/*->scala::collection::StringOps#r().*/
12-
/*->scala::Tuple2#_1.*//*->scala::Tuple2#_2.*/val x/*<-example::Synthetic#x.*/ #:: xs/*<-example::Synthetic#xs.*/ = LazyList(1, 2)
13-
val Name/*->example::Synthetic#Name.*//*->scala::util::matching::Regex#unapplySeq().*/(name/*<-example::Synthetic#name.*//*<-local0*/)/*->local0*/ = "name:foo"
12+
/*->scala::Tuple2#_1.*//*->scala::Tuple2#_2.*/val x/*<-local0*//*<-example::Synthetic#x.*/ #::/*->scala::package.`#::`.*//*->scala::package.`#::`.unapply().*/ xs/*<-local1*//*<-example::Synthetic#xs.*//*->local0*//*->local1*/ = LazyList/*->scala::package.LazyList.*//*->scala::collection::IterableFactory#apply().*/(1, 2)
13+
val Name/*->example::Synthetic#Name.*//*->scala::util::matching::Regex#unapplySeq().*/(name/*<-example::Synthetic#name.*//*<-local2*/)/*->local2*/ = "name:foo"
1414
1 #:: /*->scala::collection::immutable::LazyList.toDeferrer().*/2 #:: /*->scala::collection::immutable::LazyList.toDeferrer().*/LazyList/*->scala::package.LazyList.*/.empty/*->scala::collection::immutable::LazyList.empty().*//*->scala::collection::immutable::LazyList.Deferrer#`#::`().*/
1515

1616
val lst/*<-example::Synthetic#lst.*/ = 1 #:: /*->scala::collection::immutable::LazyList.toDeferrer().*/2 #:: /*->scala::collection::immutable::LazyList.toDeferrer().*/LazyList/*->scala::package.LazyList.*/.empty/*->scala::collection::immutable::LazyList.empty().*//*->scala::collection::immutable::LazyList.Deferrer#`#::`().*/
1717

18-
for (x/*<-local1*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/1 to/*->scala::runtime::RichInt#to().*/ 10/*->scala::collection::immutable::Range#foreach().*/; y/*<-local2*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/0 until/*->scala::runtime::RichInt#until().*/ 10/*->scala::collection::immutable::Range#foreach().*/) println/*->scala::Predef.println(+1).*/(x/*->local1*/ ->/*->scala::Predef.ArrowAssoc#`->`().*/ x/*->local1*/)
19-
for (i/*<-local3*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/1 to/*->scala::runtime::RichInt#to().*/ 10/*->scala::collection::StrictOptimizedIterableOps#flatMap().*/; j/*<-local4*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/0 until/*->scala::runtime::RichInt#until().*/ 10/*->scala::collection::immutable::Range#map().*/) yield (i/*->local3*/, j/*->local4*/)
20-
for (i/*<-local5*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/1 to/*->scala::runtime::RichInt#to().*/ 10/*->scala::collection::StrictOptimizedIterableOps#flatMap().*/; j/*<-local6*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/0 until/*->scala::runtime::RichInt#until().*/ 10/*->scala::collection::IterableOps#withFilter().*/ if i/*->local5*/ %/*->scala::Int#`%`(+3).*/ 2 ==/*->scala::Int#`==`(+3).*/ 0/*->scala::collection::WithFilter#map().*/) yield (i/*->local5*/, j/*->local6*/)
18+
for (x/*<-local3*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/1 to/*->scala::runtime::RichInt#to().*/ 10/*->scala::collection::immutable::Range#foreach().*/; y/*<-local4*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/0 until/*->scala::runtime::RichInt#until().*/ 10/*->scala::collection::immutable::Range#foreach().*/) println/*->scala::Predef.println(+1).*/(x/*->local3*/ ->/*->scala::Predef.ArrowAssoc#`->`().*/ x/*->local3*/)
19+
for (i/*<-local5*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/1 to/*->scala::runtime::RichInt#to().*/ 10/*->scala::collection::StrictOptimizedIterableOps#flatMap().*/; j/*<-local6*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/0 until/*->scala::runtime::RichInt#until().*/ 10/*->scala::collection::immutable::Range#map().*/) yield (i/*->local5*/, j/*->local6*/)
20+
for (i/*<-local7*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/1 to/*->scala::runtime::RichInt#to().*/ 10/*->scala::collection::StrictOptimizedIterableOps#flatMap().*/; j/*<-local8*/ <- /*->scala::LowPriorityImplicits#intWrapper().*/0 until/*->scala::runtime::RichInt#until().*/ 10/*->scala::collection::IterableOps#withFilter().*/ if i/*->local7*/ %/*->scala::Int#`%`(+3).*/ 2 ==/*->scala::Int#`==`(+3).*/ 0/*->scala::collection::WithFilter#map().*/) yield (i/*->local7*/, j/*->local8*/)
2121

2222
object s/*<-example::Synthetic#s.*/ {
2323
def apply/*<-example::Synthetic#s.apply().*/() = 2
@@ -36,13 +36,13 @@ class Synthetic/*<-example::Synthetic#*/ {
3636

3737
import scala.concurrent.ExecutionContext/*->scala::concurrent::ExecutionContext.*/.Implicits/*->scala::concurrent::ExecutionContext.Implicits.*/.global/*->scala::concurrent::ExecutionContext.Implicits.global().*/
3838
for {
39-
a/*<-local7*/ <- scala.concurrent.Future/*->scala::concurrent::Future.*/.successful/*->scala::concurrent::Future.successful().*/(1)/*->scala::concurrent::Future#foreach().*/
40-
b/*<-local8*/ <- scala.concurrent.Future/*->scala::concurrent::Future.*/.successful/*->scala::concurrent::Future.successful().*/(2)/*->scala::concurrent::Future#foreach().*/
41-
} println/*->scala::Predef.println(+1).*/(a/*->local7*/)/*->scala::concurrent::ExecutionContext.Implicits.global().*/
39+
a/*<-local9*/ <- scala.concurrent.Future/*->scala::concurrent::Future.*/.successful/*->scala::concurrent::Future.successful().*/(1)/*->scala::concurrent::Future#foreach().*/
40+
b/*<-local10*/ <- scala.concurrent.Future/*->scala::concurrent::Future.*/.successful/*->scala::concurrent::Future.successful().*/(2)/*->scala::concurrent::Future#foreach().*/
41+
} println/*->scala::Predef.println(+1).*/(a/*->local9*/)/*->scala::concurrent::ExecutionContext.Implicits.global().*/
4242
for {
43-
a/*<-local9*/ <- scala.concurrent.Future/*->scala::concurrent::Future.*/.successful/*->scala::concurrent::Future.successful().*/(1)/*->scala::concurrent::Future#flatMap().*/
44-
b/*<-local10*/ <- scala.concurrent.Future/*->scala::concurrent::Future.*/.successful/*->scala::concurrent::Future.successful().*/(2)/*->scala::concurrent::Future#withFilter().*/
45-
if a/*->local9*/ </*->scala::Int#`<`(+3).*/ b/*->local10*//*->scala::concurrent::Future#map().*//*->scala::concurrent::ExecutionContext.Implicits.global().*/
46-
} yield a/*->local9*//*->scala::concurrent::ExecutionContext.Implicits.global().*/
43+
a/*<-local11*/ <- scala.concurrent.Future/*->scala::concurrent::Future.*/.successful/*->scala::concurrent::Future.successful().*/(1)/*->scala::concurrent::Future#flatMap().*/
44+
b/*<-local12*/ <- scala.concurrent.Future/*->scala::concurrent::Future.*/.successful/*->scala::concurrent::Future.successful().*/(2)/*->scala::concurrent::Future#withFilter().*/
45+
if a/*->local11*/ </*->scala::Int#`<`(+3).*/ b/*->local12*//*->scala::concurrent::Future#map().*//*->scala::concurrent::ExecutionContext.Implicits.global().*/
46+
} yield a/*->local11*//*->scala::concurrent::ExecutionContext.Implicits.global().*/
4747

4848
}

0 commit comments

Comments
 (0)