Skip to content

Commit 0bf31a9

Browse files
committed
Support named arguments
1 parent bfbe08d commit 0bf31a9

File tree

7 files changed

+52
-17
lines changed

7 files changed

+52
-17
lines changed

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ class ExtractSemanticDB extends Phase with
5353
/** The index of a local symbol */
5454
private val locals = mutable.HashMap[Symbol, Int]()
5555

56+
/** The bodies of synthetic localså */
57+
private val localBodies = mutable.HashMap[Symbol, Tree]()
58+
5659
/** The local symbol(s) starting at given offset */
5760
private val symsAtOffset = new mutable.HashMap[Int, Set[Symbol]]() with
5861
override def default(key: Int) = Set[Symbol]()
@@ -162,6 +165,8 @@ class ExtractSemanticDB extends Phase with
162165
tree.tparams.foreach(tparam => registerSymbolSimple(tparam.symbol))
163166
tree.vparamss.foreach(_.foreach(vparam => registerSymbolSimple(vparam.symbol)))
164167
case _ =>
168+
if !tree.symbol.isGlobal
169+
localBodies(tree.symbol) = tree.rhs
165170
// ignore rhs
166171
case PatternValDef(pat, rhs) =>
167172
traverse(rhs)
@@ -183,6 +188,15 @@ class ExtractSemanticDB extends Phase with
183188
tree.body.foreachUntilImport(traverse).foreach(traverse) // the first import statement
184189
else
185190
tree.body.foreach(traverse)
191+
case tree: Apply =>
192+
@tu lazy val genParamSymbol: Name => String = funParamSymbol(tree.fun.symbol)
193+
traverse(tree.fun)
194+
for arg <- tree.args do
195+
arg match
196+
case arg @ NamedArg(name, value) =>
197+
registerUse(genParamSymbol(name), arg.span.startPos.withEnd(arg.span.start + name.toString.length))
198+
traverse(localBodies.get(value.symbol).getOrElse(value))
199+
case _ => traverse(arg)
186200
case tree: Assign =>
187201
val qualSym = condOpt(tree.lhs) { case Select(qual, _) if qual.symbol.exists => qual.symbol }
188202
if !excludeUse(qualSym, tree.lhs.symbol)
@@ -222,6 +236,14 @@ class ExtractSemanticDB extends Phase with
222236

223237
end traverse
224238

239+
private def funParamSymbol(funSym: Symbol)(given Context): Name => String =
240+
if funSym.isGlobal then
241+
val funSymbol = symbolName(funSym)
242+
name => s"$funSymbol($name)"
243+
else
244+
name => locals.keys.find(local => local.isTerm && local.owner == funSym && local.name == name)
245+
.fold("<?>")(Symbols.LocalPrefix + _)
246+
225247
private object PatternValDef with
226248

227249
def unapply(tree: ValDef)(given Context): Option[(Tree, Tree)] = tree.rhs match
@@ -442,8 +464,11 @@ class ExtractSemanticDB extends Phase with
442464
if !excludeUse(qualSym, sym) then
443465
registerUse(sym, span)
444466

445-
private def registerUse(sym: Symbol, span: Span)(given Context) =
446-
registerOccurrence(symbolName(sym), span, SymbolOccurrence.Role.REFERENCE)
467+
private def registerUse(sym: Symbol, span: Span)(given Context): Unit =
468+
registerUse(symbolName(sym), span)
469+
470+
private def registerUse(symbol: String, span: Span)(given Context): Unit =
471+
registerOccurrence(symbol, span, SymbolOccurrence.Role.REFERENCE)
447472

448473
private def registerDefinition(sym: Symbol, span: Span, symkinds: Set[SymbolKind])(given Context) =
449474
val symbol = symbolName(sym)

tests/semanticdb/expect/NamedApplyBlock.expect.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ package example
33
object NamedApplyBlockMethods/*<-example::NamedApplyBlockMethods.*/ {
44
val local/*<-example::NamedApplyBlockMethods.local.*/ = 1
55
def foo/*<-example::NamedApplyBlockMethods.foo().*/(a/*<-example::NamedApplyBlockMethods.foo().(a)*/: Int/*->scala::Int#*/ = 1, b/*<-example::NamedApplyBlockMethods.foo().(b)*/: Int/*->scala::Int#*/ = 2, c/*<-example::NamedApplyBlockMethods.foo().(c)*/: Int/*->scala::Int#*/ = 3): Int/*->scala::Int#*/ = a/*->example::NamedApplyBlockMethods.foo().(a)*/ +/*->scala::Int#`+`(+4).*/ b/*->example::NamedApplyBlockMethods.foo().(b)*/ +/*->scala::Int#`+`(+4).*/ c/*->example::NamedApplyBlockMethods.foo().(c)*/
6-
def baseCase/*<-example::NamedApplyBlockMethods.baseCase().*/ = foo/*->example::NamedApplyBlockMethods.foo().*//*->local0*/(local/*->example::NamedApplyBlockMethods.local.*/, c = 3) // as named apply is desugared, it would take more work to inspect within the body of the setter
7-
def recursive/*<-example::NamedApplyBlockMethods.recursive().*/ = foo/*->example::NamedApplyBlockMethods.foo().*//*->local2*/(local/*->example::NamedApplyBlockMethods.local.*/, c = /*->local1*/foo(local, c = 3)) // as named apply is desugared, it would take more work to inspect within the body of the setter
6+
def baseCase/*<-example::NamedApplyBlockMethods.baseCase().*/ = foo/*->example::NamedApplyBlockMethods.foo().*//*->local0*/(local/*->example::NamedApplyBlockMethods.local.*/, c/*->example::NamedApplyBlockMethods.foo().(c)*/ = 3)
7+
def recursive/*<-example::NamedApplyBlockMethods.recursive().*/ = foo/*->example::NamedApplyBlockMethods.foo().*//*->local2*/(local/*->example::NamedApplyBlockMethods.local.*/, c/*->example::NamedApplyBlockMethods.foo().(c)*/ = foo/*->example::NamedApplyBlockMethods.foo().*//*->local3*/(local/*->example::NamedApplyBlockMethods.local.*/, c/*->example::NamedApplyBlockMethods.foo().(c)*/ = 3))
88
}
99

1010
object NamedApplyBlockCaseClassConstruction/*<-example::NamedApplyBlockCaseClassConstruction.*/ {
1111
case class Msg/*<-example::NamedApplyBlockCaseClassConstruction.Msg#*/(body/*<-example::NamedApplyBlockCaseClassConstruction.Msg#body.*/: String/*->scala::Predef.String#*/, head/*<-example::NamedApplyBlockCaseClassConstruction.Msg#head.*/: String/*->scala::Predef.String#*/ = "default", tail/*<-example::NamedApplyBlockCaseClassConstruction.Msg#tail.*/: String/*->scala::Predef.String#*/)
1212
val bodyText/*<-example::NamedApplyBlockCaseClassConstruction.bodyText.*/ = "body"
13-
val msg/*<-example::NamedApplyBlockCaseClassConstruction.msg.*/ = Msg/*->example::NamedApplyBlockCaseClassConstruction.Msg.*//*->local3*//*->example::NamedApplyBlockCaseClassConstruction.Msg.apply().*/(bodyText/*->example::NamedApplyBlockCaseClassConstruction.bodyText.*/, tail = "tail")
13+
val msg/*<-example::NamedApplyBlockCaseClassConstruction.msg.*/ = Msg/*->example::NamedApplyBlockCaseClassConstruction.Msg.*//*->local4*//*->example::NamedApplyBlockCaseClassConstruction.Msg.apply().*/(bodyText/*->example::NamedApplyBlockCaseClassConstruction.bodyText.*/, tail/*->example::NamedApplyBlockCaseClassConstruction.Msg.apply().(tail)*/ = "tail")
1414
}

tests/semanticdb/expect/NamedApplyBlock.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package example
33
object NamedApplyBlockMethods {
44
val local = 1
55
def foo(a: Int = 1, b: Int = 2, c: Int = 3): Int = a + b + c
6-
def baseCase = foo(local, c = 3) // as named apply is desugared, it would take more work to inspect within the body of the setter
7-
def recursive = foo(local, c = foo(local, c = 3)) // as named apply is desugared, it would take more work to inspect within the body of the setter
6+
def baseCase = foo(local, c = 3)
7+
def recursive = foo(local, c = foo(local, c = 3))
88
}
99

1010
object NamedApplyBlockCaseClassConstruction {

tests/semanticdb/expect/NamedArguments.expect.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ package example
22

33
class NamedArguments/*<-example::NamedArguments#*/ {
44
case class User/*<-example::NamedArguments#User#*/(name/*<-example::NamedArguments#User#name.*/: String/*->scala::Predef.String#*/)
5-
User/*->example::NamedArguments#User.*//*->example::NamedArguments#User.apply().*/(name = "John") // as there is no API to get the symbols of method arguments, this proposes a problem for how to generate references from a NamedArg
6-
User/*->example::NamedArguments#User.*/.apply/*->example::NamedArguments#User.apply().*/(name = "John") // as there is no API to get the symbols of method arguments, this proposes a problem for how to generate references from a NamedArg
5+
User/*->example::NamedArguments#User.*//*->example::NamedArguments#User.apply().*/(name/*->example::NamedArguments#User.apply().(name)*/ = "John")
6+
User/*->example::NamedArguments#User.*/.apply/*->example::NamedArguments#User.apply().*/(name/*->example::NamedArguments#User.apply().(name)*/ = "John")
77
}

tests/semanticdb/expect/NamedArguments.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ package example
22

33
class NamedArguments {
44
case class User(name: String)
5-
User(name = "John") // as there is no API to get the symbols of method arguments, this proposes a problem for how to generate references from a NamedArg
6-
User.apply(name = "John") // as there is no API to get the symbols of method arguments, this proposes a problem for how to generate references from a NamedArg
5+
User(name = "John")
6+
User.apply(name = "John")
77
}

tests/semanticdb/metac.expect

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,8 +2106,8 @@ Schema => SemanticDB v4
21062106
Uri => NamedApplyBlock.scala
21072107
Text => empty
21082108
Language => Scala
2109-
Symbols => 44 entries
2110-
Occurrences => 40 entries
2109+
Symbols => 45 entries
2110+
Occurrences => 46 entries
21112111

21122112
Symbols:
21132113
example/NamedApplyBlockCaseClassConstruction. => final object NamedApplyBlockCaseClassConstruction
@@ -2153,7 +2153,8 @@ example/NamedApplyBlockMethods.recursive(). => method recursive
21532153
local0 => val local b$1
21542154
local1 => val local c$1
21552155
local2 => val local b$3
2156-
local3 => val local head$1
2156+
local3 => val local b$2
2157+
local4 => val local head$1
21572158

21582159
Occurrences:
21592160
[0:8..0:15): example <- example/
@@ -2176,11 +2177,16 @@ Occurrences:
21762177
[5:17..5:20): foo -> example/NamedApplyBlockMethods.foo().
21772178
[5:17..5:17): -> local0
21782179
[5:21..5:26): local -> example/NamedApplyBlockMethods.local.
2180+
[5:28..5:29): c -> example/NamedApplyBlockMethods.foo().(c)
21792181
[6:6..6:15): recursive <- example/NamedApplyBlockMethods.recursive().
21802182
[6:18..6:21): foo -> example/NamedApplyBlockMethods.foo().
21812183
[6:18..6:18): -> local2
21822184
[6:22..6:27): local -> example/NamedApplyBlockMethods.local.
2183-
[6:33..6:33): -> local1
2185+
[6:29..6:30): c -> example/NamedApplyBlockMethods.foo().(c)
2186+
[6:33..6:36): foo -> example/NamedApplyBlockMethods.foo().
2187+
[6:33..6:33): -> local3
2188+
[6:37..6:42): local -> example/NamedApplyBlockMethods.local.
2189+
[6:44..6:45): c -> example/NamedApplyBlockMethods.foo().(c)
21842190
[9:7..9:43): NamedApplyBlockCaseClassConstruction <- example/NamedApplyBlockCaseClassConstruction.
21852191
[10:13..10:16): Msg <- example/NamedApplyBlockCaseClassConstruction.Msg#
21862192
[10:16..10:70): <- example/NamedApplyBlockCaseClassConstruction.Msg#`<init>`().
@@ -2193,9 +2199,10 @@ Occurrences:
21932199
[11:6..11:14): bodyText <- example/NamedApplyBlockCaseClassConstruction.bodyText.
21942200
[12:6..12:9): msg <- example/NamedApplyBlockCaseClassConstruction.msg.
21952201
[12:12..12:15): Msg -> example/NamedApplyBlockCaseClassConstruction.Msg.
2196-
[12:12..12:12): -> local3
2202+
[12:12..12:12): -> local4
21972203
[12:15..12:15): -> example/NamedApplyBlockCaseClassConstruction.Msg.apply().
21982204
[12:16..12:24): bodyText -> example/NamedApplyBlockCaseClassConstruction.bodyText.
2205+
[12:26..12:30): tail -> example/NamedApplyBlockCaseClassConstruction.Msg.apply().(tail)
21992206

22002207
expect/NamedArguments.scala
22012208
---------------------------
@@ -2206,7 +2213,7 @@ Uri => NamedArguments.scala
22062213
Text => empty
22072214
Language => Scala
22082215
Symbols => 15 entries
2209-
Occurrences => 11 entries
2216+
Occurrences => 13 entries
22102217

22112218
Symbols:
22122219
example/NamedArguments# => class NamedArguments
@@ -2235,8 +2242,10 @@ Occurrences:
22352242
[3:24..3:30): String -> scala/Predef.String#
22362243
[4:2..4:6): User -> example/NamedArguments#User.
22372244
[4:6..4:6): -> example/NamedArguments#User.apply().
2245+
[4:7..4:11): name -> example/NamedArguments#User.apply().(name)
22382246
[5:2..5:6): User -> example/NamedArguments#User.
22392247
[5:7..5:12): apply -> example/NamedArguments#User.apply().
2248+
[5:13..5:17): name -> example/NamedArguments#User.apply().(name)
22402249

22412250
expect/NewModifiers.scala
22422251
-------------------------

tests/semanticdb/todo.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Differences between scalameta implementation and dotc.
1111

1212
## Completed
1313

14+
- [x] Recognise named arguments and traverse their bodies.
1415
- [x] Recognise pattern val definitions.
1516
- [x] Recognise anonymous functions.
1617
- [x] Recognise specialised constant enum values.

0 commit comments

Comments
 (0)