From 8044214df60648b8e0875921d4e155d22030d795 Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Mon, 11 Mar 2024 15:00:05 +0100 Subject: [PATCH 1/3] improvement: Better inlay Hints for anonymous implicits --- .../dotty/tools/pc/PcInlayHintsProvider.scala | 7 +- ...tionsSuite.scala => InlayHintsSuite.scala} | 127 ++++++++++++++++-- 2 files changed, 119 insertions(+), 15 deletions(-) rename presentation-compiler/test/dotty/tools/pc/tests/inlayHints/{SyntheticDecorationsSuite.scala => InlayHintsSuite.scala} (82%) diff --git a/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala index 3a17d30bc024..9b40f1e6777a 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala @@ -83,7 +83,7 @@ class PcInlayHintsProvider( if params.implicitParameters() => val labelParts = symbols.map(s => List(labelPart(s, s.decodedName))) val label = - if allImplicit then labelParts.separated("(", ", ", ")") + if allImplicit then labelParts.separated("(using ", ", ", ")") else labelParts.separated(", ") inlayHints.add( adjustPos(pos).toLsp, @@ -218,7 +218,10 @@ object ImplicitParameters: case Apply(fun, args) if args.exists(isSyntheticArg) && !tree.sourcePos.span.isZeroExtent => val (implicitArgs, providedArgs) = args.partition(isSyntheticArg) - val allImplicit = providedArgs.isEmpty + val allImplicit = providedArgs.isEmpty || providedArgs.forall { + case Ident(name) => name == nme.MISSING + case _ => false + } val pos = implicitArgs.head.sourcePos Some(implicitArgs.map(_.symbol), pos, allImplicit) case _ => None diff --git a/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/SyntheticDecorationsSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala similarity index 82% rename from presentation-compiler/test/dotty/tools/pc/tests/inlayHints/SyntheticDecorationsSuite.scala rename to presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala index 0e32e5cf0682..d8286a79c2f2 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/SyntheticDecorationsSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala @@ -19,7 +19,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite { | def foo()/*: Unit<>*/ = { | implicit val imp: Int = 2 | def addOne(x: Int)(implicit one: Int)/*: Int<>*/ = x + one - | val x/*: Int<>*/ = addOne(1)/*(imp<<(3:17)>>)*/ + | val x/*: Int<>*/ = addOne(1)/*(using imp<<(3:17)>>)*/ | } |} |""".stripMargin @@ -66,7 +66,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite { |object Main { | implicit val imp: Int = 2 | def addOne(x: Int)(implicit one: Int)/*: Int<>*/ = x + one - | val x/*: Int<>*/ = addOne(1)/*(imp<<(3:15)>>)*/ + | val x/*: Int<>*/ = addOne(1)/*(using imp<<(3:15)>>)*/ |} |""".stripMargin ) @@ -100,7 +100,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite { |object Main { | implicit val imp: Int = 2 | def addOne(x: Int)(using one: Int)/*: Int<>*/ = x + one - | val x/*: Int<>*/ = addOne(1)/*(imp<<(3:15)>>)*/ + | val x/*: Int<>*/ = addOne(1)/*(using imp<<(3:15)>>)*/ |} |""".stripMargin ) @@ -502,7 +502,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite { |} |""".stripMargin, """|object Main { - | val ordered/*: String<>*/ = /*augmentString<>(*/"acb"/*)*/.sorted/*[Char<>]*//*(Char<>)*/ + | val ordered/*: String<>*/ = /*augmentString<>(*/"acb"/*)*/.sorted/*[Char<>]*//*(using Char<>)*/ |} |""".stripMargin ) @@ -608,18 +608,18 @@ class InlayHintsSuite extends BaseInlayHintsSuite { | | /*StringTestOps<<(6:17)>>(*/"foo"/*)*/ should { | /*StringTestOps<<(6:17)>>(*/"checkThing1"/*)*/ in { - | checkThing1[String]/*(instancesString<<(10:15)>>)*/ - | }/*(here<<(5:15)>>)*/ + | checkThing1[String]/*(using instancesString<<(10:15)>>)*/ + | }/*(using here<<(5:15)>>)*/ | /*StringTestOps<<(6:17)>>(*/"checkThing2"/*)*/ in { - | checkThing2[String]/*(instancesString<<(10:15)>>, instancesString<<(10:15)>>)*/ - | }/*(here<<(5:15)>>)*/ - | }/*(subjectRegistrationFunction<<(3:15)>>)*/ + | checkThing2[String]/*(using instancesString<<(10:15)>>, instancesString<<(10:15)>>)*/ + | }/*(using here<<(5:15)>>)*/ + | }/*(using subjectRegistrationFunction<<(3:15)>>)*/ | | /*StringTestOps<<(6:17)>>(*/"bar"/*)*/ should { | /*StringTestOps<<(6:17)>>(*/"checkThing1"/*)*/ in { - | checkThing1[String]/*(instancesString<<(10:15)>>)*/ - | }/*(here<<(5:15)>>)*/ - | }/*(subjectRegistrationFunction<<(3:15)>>)*/ + | checkThing1[String]/*(using instancesString<<(10:15)>>)*/ + | }/*(using here<<(5:15)>>)*/ + | }/*(using subjectRegistrationFunction<<(3:15)>>)*/ | | def checkThing1[A](implicit ev: Eq[A])/*: Nothing<>*/ = ??? | def checkThing2[A](implicit ev: Eq[A], sem: Semigroup[A])/*: Nothing<>*/ = ??? @@ -664,4 +664,105 @@ class InlayHintsSuite extends BaseInlayHintsSuite { |case class ErrorMessage(error) |""".stripMargin ) -} \ No newline at end of file + + @Test def `anonymous-given` = + check( + """|package example + | + |trait Ord[T]: + | def compare(x: T, y: T): Int + | + |given intOrd: Ord[Int] with + | def compare(x: Int, y: Int) = + | if x < y then -1 else if x > y then +1 else 0 + | + |given Ord[String] with + | def compare(x: String, y: String) = + | x.compare(y) + | + |""".stripMargin, + """|package example + | + |trait Ord[T]: + | def compare(x: T, y: T): Int + | + |given intOrd: Ord[Int] with + | def compare(x: Int, y: Int)/*: Int<>*/ = + | if x < y then -1 else if x > y then +1 else 0 + | + |given Ord[String] with + | def compare(x: String, y: String)/*: Int<>*/ = + | /*augmentString<>(*/x/*)*/.compare(y) + | + |""".stripMargin + ) + + // TODO: Add a separate option for hints for context bounds + @Test def `context-bounds1` = + check( + """|package example + |object O { + | given Int = 1 + | def test[T: Ordering](x: T)(using Int) = ??? + | test(1) + |} + |""".stripMargin, + """|package example + |object O { + | given Int = 1 + | def test[T: Ordering](x: T)(using Int)/*: Nothing<>*/ = ??? + | test/*[Int<>]*/(1)/*(using Int<>, given_Int<<(2:8)>>)*/ + |} + |""".stripMargin + ) + + @Test def `context-bounds2` = + check( + """|package example + |object O { + | def test[T: Ordering](x: T) = ??? + | test(1) + |} + |""".stripMargin, + """|package example + |object O { + | def test[T: Ordering](x: T)/*: Nothing<>*/ = ??? + | test/*[Int<>]*/(1)/*(using Int<>)*/ + |} + |""".stripMargin + ) + + @Test def `context-bounds3` = + check( + """|package example + |object O { + | def test[T: Ordering](x: T)(using Int) = ??? + | test(1) + |} + |""".stripMargin, + """|package example + |object O { + | def test[T: Ordering](x: T)(using Int)/*: Nothing<>*/ = ??? + | test/*[Int<>]*/(1)/*(using Int<>)*/ + |} + |""".stripMargin + ) + + @Test def `context-bounds4` = + check( + """|package example + |object O { + | implicit val i: Int = 123 + | def test[T: Ordering](x: T)(implicit v: Int) = ??? + | test(1) + |} + |""".stripMargin, + """|package example + |object O { + | implicit val i: Int = 123 + | def test[T: Ordering](x: T)(implicit v: Int)/*: Nothing<>*/ = ??? + | test/*[Int<>]*/(1)/*(using Int<>, i<<(2:15)>>)*/ + |} + |""".stripMargin + ) +} From c31f87bde7d3b8bfd8defbbf3577a75f180f65dc Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Mon, 11 Mar 2024 15:03:20 +0100 Subject: [PATCH 2/3] bugfix: Don't show unhelpful renames in hover --- .../tools/pc/printer/ShortenedTypePrinter.scala | 3 ++- .../tools/pc/tests/hover/HoverTermSuite.scala | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala index ed37e133372b..a7cf1a703a1f 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala @@ -66,7 +66,8 @@ class ShortenedTypePrinter( private val foundRenames = collection.mutable.LinkedHashMap.empty[Symbol, String] - def getUsedRenames: Map[Symbol, String] = foundRenames.toMap + def getUsedRenames: Map[Symbol, String] = + foundRenames.toMap.filter { case (k, v) => k.showName != v } def getUsedRenamesInfo(using Context): List[String] = foundRenames.map { (from, to) => diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala index 82fd0c657e67..d1e90241e639 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala @@ -637,3 +637,19 @@ class HoverTermSuite extends BaseHoverSuite: |def test(d: S[Int], f: S[Char]): AB[Int, String] |```""".stripMargin, ) + + @Test def `import-no-rename` = + check( + """ + |import scala.collection + | + |object O { + | < 2)>> + |} + |""".stripMargin, + """ + |```scala + |val abc: scala.collection.Map[Int, Int] + |``` + |""".stripMargin + ) From bc73d364a5f464aaa45465304a0d87a257e33d8c Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Mon, 11 Mar 2024 16:04:41 +0100 Subject: [PATCH 3/3] delete `TODO` comment --- .../test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala index d8286a79c2f2..da7601e3c746 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala @@ -697,7 +697,6 @@ class InlayHintsSuite extends BaseInlayHintsSuite { |""".stripMargin ) - // TODO: Add a separate option for hints for context bounds @Test def `context-bounds1` = check( """|package example