Skip to content

Commit 5179962

Browse files
committed
bugfix: Completions for named args in wrong order
1 parent e196dec commit 5179962

File tree

3 files changed

+117
-11
lines changed

3 files changed

+117
-11
lines changed

presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ class Completions(
5656

5757
val coursierComplete = new CoursierComplete(BuildInfo.scalaVersion)
5858

59+
private lazy val adjustedPath = Completion.resolveTypedOrUntypedPath(path, pos)
5960
private lazy val completionMode =
60-
val adjustedPath = Completion.resolveTypedOrUntypedPath(path, pos)
6161
val mode = Completion.completionMode(adjustedPath, pos)
6262
path match
6363
case Literal(Constant(_: String)) :: _ => Mode.Term // literal completions
@@ -451,6 +451,7 @@ class Completions(
451451
val args = NamedArgCompletions.contribute(
452452
pos,
453453
path,
454+
adjustedPath,
454455
indexedContext,
455456
config.isCompletionSnippetsEnabled()
456457
)

presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dotty.tools.pc.completions
22

33
import scala.util.Try
44

5+
import dotty.tools.dotc.ast.NavigateAST
56
import dotty.tools.dotc.ast.Trees.ValDef
67
import dotty.tools.dotc.ast.tpd.*
78
import dotty.tools.dotc.core.Constants.Constant
@@ -12,7 +13,10 @@ import dotty.tools.dotc.core.Flags
1213
import dotty.tools.dotc.core.Flags.Method
1314
import dotty.tools.dotc.core.NameKinds.DefaultGetterName
1415
import dotty.tools.dotc.core.Names.Name
16+
import dotty.tools.dotc.core.StdNames.*
17+
import dotty.tools.dotc.core.SymDenotations.NoDenotation
1518
import dotty.tools.dotc.core.Symbols
19+
import dotty.tools.dotc.core.Symbols.NoSymbol
1620
import dotty.tools.dotc.core.Symbols.Symbol
1721
import dotty.tools.dotc.core.Types.AndType
1822
import dotty.tools.dotc.core.Types.AppliedType
@@ -33,8 +37,9 @@ object NamedArgCompletions:
3337
def contribute(
3438
pos: SourcePosition,
3539
path: List[Tree],
40+
untypedPath: => List[Tree],
3641
indexedContext: IndexedContext,
37-
clientSupportsSnippets: Boolean
42+
clientSupportsSnippets: Boolean,
3843
)(using ctx: Context): List[CompletionValue] =
3944
path match
4045
case (ident: Ident) :: ValDef(_, _, _) :: Block(_, app: Apply) :: _
@@ -43,7 +48,7 @@ object NamedArgCompletions:
4348
Some(ident),
4449
app,
4550
indexedContext,
46-
clientSupportsSnippets
51+
clientSupportsSnippets,
4752
)
4853
case (ident: Ident) :: rest =>
4954
def getApplyForContextFunctionParam(path: List[Tree]): Option[Apply] =
@@ -63,9 +68,29 @@ object NamedArgCompletions:
6368
Some(ident),
6469
app,
6570
indexedContext,
66-
clientSupportsSnippets
71+
clientSupportsSnippets,
6772
)
6873
contribution.getOrElse(Nil)
74+
case (app: Apply) :: _ =>
75+
/**
76+
* def foo(aaa: Int, bbb: Int, ccc: Int) = ???
77+
* val x = foo(
78+
* bbb = 123,
79+
* ccc = 123,
80+
* @@
81+
* )
82+
* In this case, typed path doesn't contain already provided arguments
83+
*/
84+
untypedPath match
85+
case (ident: Ident) :: (app: Apply) :: _ =>
86+
contribute(
87+
Some(ident),
88+
app,
89+
indexedContext,
90+
clientSupportsSnippets,
91+
)
92+
case _ =>
93+
Nil
6994
case _ =>
7095
Nil
7196
end match
@@ -87,7 +112,7 @@ object NamedArgCompletions:
87112
ident: Option[Ident],
88113
apply: Apply,
89114
indexedContext: IndexedContext,
90-
clientSupportsSnippets: Boolean
115+
clientSupportsSnippets: Boolean,
91116
)(using context: Context): List[CompletionValue] =
92117
def isUselessLiteral(arg: Tree): Boolean =
93118
arg match
@@ -117,6 +142,11 @@ object NamedArgCompletions:
117142

118143
val argss = collectArgss(apply)
119144

145+
def fallbackFindApply(sym: Symbol) =
146+
sym.info.member(nme.apply) match
147+
case NoDenotation => Nil
148+
case den => List(den.symbol)
149+
120150
// fallback for when multiple overloaded methods match the supplied args
121151
def fallbackFindMatchingMethods() =
122152
def maybeNameAndIndexedContext(
@@ -182,7 +212,9 @@ object NamedArgCompletions:
182212
if foundPotential.contains(method.symbol) then foundPotential
183213
else method.symbol :: foundPotential
184214
else List(method.symbol)
185-
else fallbackFindMatchingMethods()
215+
else if method.symbol.is(Method) || method.symbol == NoSymbol then
216+
fallbackFindMatchingMethods()
217+
else fallbackFindApply(method.symbol)
186218
end if
187219
end matchingMethods
188220

@@ -227,8 +259,13 @@ object NamedArgCompletions:
227259
def refineParams(method: Tree, level: Int): List[ParamSymbol] =
228260
method match
229261
case Select(Apply(f, _), _) => refineParams(f, level + 1)
230-
case Select(h, v) => getRefinedParams(h.symbol.info, level)
231-
case _ => defaultBaseParams
262+
case Select(h, name) =>
263+
// for Select(foo, name = apply) we want `foo.symbol`
264+
if name == nme.apply then getRefinedParams(h.symbol.info, level)
265+
else getRefinedParams(method.symbol.info, level)
266+
case Apply(f, _) =>
267+
refineParams(f, level + 1)
268+
case _ => getRefinedParams(method.symbol.info, level)
232269
refineParams(method, 0)
233270
end baseParams
234271

@@ -330,15 +367,15 @@ object NamedArgCompletions:
330367
param.nameBackticked + " = " + memberName + " "
331368
CompletionValue.namedArg(
332369
label = editText,
333-
param
370+
param,
334371
)
335372
}
336373
}
337374

338375
params.map(p =>
339376
CompletionValue.namedArg(
340377
s"${p.nameBackticked} = ",
341-
p
378+
p,
342379
)
343380
) ::: findPossibleDefaults() ::: fillAllFields()
344381
end contribute
@@ -411,4 +448,4 @@ case class JustSymbol(symbol: Symbol)(using Context) extends ParamSymbol:
411448
def info: Type = symbol.info
412449

413450
case class RefinedSymbol(symbol: Symbol, name: Name, info: Type)
414-
extends ParamSymbol
451+
extends ParamSymbol

presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,3 +1038,71 @@ class CompletionArgSuite extends BaseCompletionSuite:
10381038
|""".stripMargin,
10391039
topLines = Some(1),
10401040
)
1041+
1042+
@Test def `second-first` =
1043+
check(
1044+
"""|object Main {
1045+
| def foo(aaa: Int, bbb: Int, ccc: Int) = aaa + bbb + ccc
1046+
| val k = foo (
1047+
| bbb = 123,
1048+
| aa@@
1049+
| )
1050+
|}
1051+
|""".stripMargin,
1052+
"""|aaa = : Int
1053+
|""".stripMargin,
1054+
topLines = Some(1),
1055+
)
1056+
1057+
@Test def `second-first2` =
1058+
check(
1059+
"""|object Main {
1060+
| def foo(aaa: Int, bbb: Int, ccc: Int) = aaa + bbb + ccc
1061+
| val k = foo (
1062+
| bbb = 123,
1063+
| ccc = 123,
1064+
| aa@@
1065+
| )
1066+
|}
1067+
|""".stripMargin,
1068+
"""|aaa = : Int
1069+
|""".stripMargin,
1070+
topLines = Some(1),
1071+
)
1072+
1073+
@Test def `second-first3` =
1074+
check(
1075+
"""|object Main {
1076+
| def foo(ddd: Int)(aaa: Int, bbb: Int, ccc: Int) = aaa + bbb + ccc
1077+
| val k = foo(123)(
1078+
| bbb = 123,
1079+
| ccc = 123,
1080+
| aa@@
1081+
| )
1082+
|}
1083+
|""".stripMargin,
1084+
"""|aaa = : Int
1085+
|""".stripMargin,
1086+
topLines = Some(1),
1087+
)
1088+
1089+
@Test def `second-first4` =
1090+
check(
1091+
"""|object O:
1092+
| val hello: (x: Int, y: Int) => Unit = (x, _) => println(x)
1093+
|val k = O.hello(y = 1, @@)
1094+
|""".stripMargin,
1095+
"""|x = : Int
1096+
|""".stripMargin,
1097+
topLines = Some(1),
1098+
)
1099+
1100+
@Test def `second-first5` =
1101+
check(
1102+
"""|val hello: (x: Int) => Int => (str: String, ccc: String) => Unit = x => j => (str, _) => println(str)
1103+
|val k = hello(x = 1)(2)(ccc = "abc", @@)
1104+
|""".stripMargin,
1105+
"""|str = : String
1106+
| """.stripMargin,
1107+
topLines = Some(1),
1108+
)

0 commit comments

Comments
 (0)