Skip to content

Commit 12050ae

Browse files
committed
bugfix: Completions for named args in wrong order
1 parent 55c5864 commit 12050ae

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
@@ -442,6 +442,7 @@ class Completions(
442442
val args = NamedArgCompletions.contribute(
443443
pos,
444444
path,
445+
adjustedPath,
445446
indexedContext,
446447
config.isCompletionSnippetsEnabled
447448
)

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

@@ -329,15 +366,15 @@ object NamedArgCompletions:
329366
param.nameBackticked + " = " + memberName + " "
330367
CompletionValue.namedArg(
331368
label = editText,
332-
param
369+
param,
333370
)
334371
}
335372
}
336373

337374
params.map(p =>
338375
CompletionValue.namedArg(
339376
s"${p.nameBackticked} = ",
340-
p
377+
p,
341378
)
342379
) ::: findPossibleDefaults() ::: fillAllFields()
343380
end contribute
@@ -410,4 +447,4 @@ case class JustSymbol(symbol: Symbol)(using Context) extends ParamSymbol:
410447
def info: Type = symbol.info
411448

412449
case class RefinedSymbol(symbol: Symbol, name: Name, info: Type)
413-
extends ParamSymbol
450+
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)