diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala index 30346690bd18..d5ecf60dc341 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala @@ -237,15 +237,24 @@ object NamedArgCompletions: .getOrElse(baseArgs) .filterNot(isUselessLiteral) + @tailrec + def isDefaultArg(t: Tree): Boolean = t match + // default args + case Ident(name) => name.is(DefaultGetterName) + // default args for methods defined in object + case Select(_, name) => + name.is(DefaultGetterName) + // default args in not-first parameter list + // eg. def m(fst: Int)(snd: Int)(arg1: Int, arg2: Int = 123) = ??? + case Apply(fun, _) => isDefaultArg(fun) + case _ => false + val isNamed: Set[Name] = args.iterator .zip(baseParams.iterator) // filter out synthesized args and default arg getters .filterNot { case (arg, _) if arg.symbol.denot.is(Flags.Synthetic) => true - case (Ident(name), _) => name.is(DefaultGetterName) // default args - case (Select(Ident(_), name), _) => - name.is(DefaultGetterName) // default args for apply method - case _ => false + case (arg, _) => isDefaultArg(arg) } .map { case (NamedArg(name, _), _) => name diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala index 6e91209d5788..bce430afe881 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala @@ -238,6 +238,111 @@ class CompletionArgSuite extends BaseCompletionSuite: "" ) + @Test def `default-args` = + check( + s"""|object Main { + | def foo() = { + | def deployment( + | fst: Option[String], + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment(@@) + | } + |} + |""".stripMargin, + """|fst = : Option[String] + |snd = : Int + |""".stripMargin, + topLines = Some(2), + ) + @Test def `default-args2` = + check( + s"""|object Main { + | def deployment( + | fst: Option[String], + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment(@@) + |} + |""".stripMargin, + """|fst = : Option[String] + |snd = : Int + |""".stripMargin, + topLines = Some(2), + ) + + @Test def `default-args3` = + check( + s"""|object Main { + | def deployment(str: String)( + | fst: Option[String], + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment("str")( + | @@ + | ) + |} + |""".stripMargin, + """|fst = : Option[String] + |snd = : Int + |""".stripMargin, + topLines = Some(2), + ) + + @Test def `default-args4` = + check( + s"""|object Main { + | def deployment(str: String)(opt: Option[Int])( + | fst: Option[String], + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment("str")(None)( + | @@ + | ) + |} + |""".stripMargin, + """|fst = : Option[String] + |snd = : Int + |""".stripMargin, + topLines = Some(2), + ) + + @Test def `default-args5` = + check( + s"""|object Main { + | def deployment(str: String)(opt: Option[Int] = None)( + | fst: Option[String], + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment("str")( + | @@ + | ) + |} + |""".stripMargin, + """|opt = : Option[Int] + |""".stripMargin, + topLines = Some(1), + ) + + @Test def `default-args6` = + check( + s"""|object Main { + | def deployment(using str: String)( + | fst: Option[String], + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment(using "str")( + | @@ + | ) + |} + |""".stripMargin, + """|fst = : Option[String] + |snd = : Int + |""".stripMargin, + topLines = Some(2), + ) + + // @Test def `explicit-dollar` = // checkSnippet( // see: https://github.com/scalameta/metals/issues/2400 // """