Skip to content

Commit

Permalink
improvement: Better inlay Hints for anonymous implicits
Browse files Browse the repository at this point in the history
  • Loading branch information
jkciesluk committed Feb 29, 2024
1 parent 4903c4f commit 340ecd4
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import dotty.tools.dotc.util.SourcePosition
import dotty.tools.dotc.util.Spans.Span
import org.eclipse.lsp4j.InlayHint
import org.eclipse.lsp4j.InlayHintKind
import org.eclipse.{lsp4j as l}

class PcInlayHintsProvider(
driver: InteractiveDriver,
Expand Down Expand Up @@ -77,13 +76,24 @@ 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,
label,
InlayHintKind.Parameter,
)
case AnonymousGivenDef(symbol, pos) if params.implicitParameters() =>
val adjustedPos = adjustPos(pos)
if inlayHints.containsDef(adjustedPos.start) then inlayHints
else
inlayHints
.add(
adjustedPos.toLsp,
labelPart(symbol, symbol.decodedName) :: LabelPart(": ") :: Nil,
InlayHintKind.Parameter,
)
.addDefinition(adjustedPos.start)
case ValueOf(label, pos) if params.implicitParameters() =>
inlayHints.add(
adjustPos(pos).toLsp,
Expand Down Expand Up @@ -226,6 +236,18 @@ object ImplicitParameters:
case _ => false
end ImplicitParameters

object AnonymousGivenDef:
def unapply(tree: Tree)(using Context) =
tree match
case vd: ValDef
if vd.symbol.is(Flags.Given) &&
vd.symbol.isTerm &&
vd.namePos.span.isZeroExtent &&
!vd.span.isZeroExtent =>
Some(vd.symbol, vd.namePos)
case _ => None
end AnonymousGivenDef

object ValueOf:
def unapply(tree: Tree)(using Context) =
tree match
Expand Down
125 changes: 114 additions & 11 deletions tests/cross/src/test/scala/tests/pc/InlayHintsSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
)

check(
"local",
"local".tag(IgnoreForScala3CompilerPC),
"""|object Main {
| def foo() = {
| implicit val imp: Int = 2
Expand All @@ -25,7 +25,18 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
| val x/*: Int<<scala/Int#>>*/ = addOne(1)/*(imp<<(3:17)>>)*/
| }
|}
|""".stripMargin
|""".stripMargin,
compat = Map(
"3" ->
"""|object Main {
| def foo()/*: Unit<<scala/Unit#>>*/ = {
| implicit val imp: Int = 2
| def addOne(x: Int)(implicit one: Int)/*: Int<<scala/Int#>>*/ = x + one
| val x/*: Int<<scala/Int#>>*/ = addOne(1)/*(using imp<<(3:17)>>)*/
| }
|}
|""".stripMargin
)
)

check(
Expand Down Expand Up @@ -65,7 +76,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
)

check(
"implicit-param",
"implicit-param".tag(IgnoreForScala3CompilerPC),
"""|case class User(name: String)
|object Main {
| implicit val imp: Int = 2
Expand All @@ -79,7 +90,17 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
| def addOne(x: Int)(implicit one: Int)/*: Int<<scala/Int#>>*/ = x + one
| val x/*: Int<<scala/Int#>>*/ = addOne(1)/*(imp<<(3:15)>>)*/
|}
|""".stripMargin
|""".stripMargin,
compat = Map(
"3" ->
"""|case class User(name: String)
|object Main {
| implicit val imp: Int = 2
| def addOne(x: Int)(implicit one: Int)/*: Int<<scala/Int#>>*/ = x + one
| val x/*: Int<<scala/Int#>>*/ = addOne(1)/*(using imp<<(3:15)>>)*/
|}
|""".stripMargin
)
)

check(
Expand All @@ -99,7 +120,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
)

check(
"using-param".tag(IgnoreScala2),
"using-param".tag(IgnoreScala2.and(IgnoreForScala3CompilerPC)),
"""|case class User(name: String)
|object Main {
| implicit val imp: Int = 2
Expand All @@ -111,7 +132,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
|object Main {
| implicit val imp: Int = 2
| def addOne(x: Int)(using one: Int)/*: Int<<scala/Int#>>*/ = x + one
| val x/*: Int<<scala/Int#>>*/ = addOne(1)/*(imp<<(3:15)>>)*/
| val x/*: Int<<scala/Int#>>*/ = addOne(1)/*(using imp<<(3:15)>>)*/
|}
|""".stripMargin
)
Expand Down Expand Up @@ -145,7 +166,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
| def doX: Int
|trait Yg:
| def doY: String
|given (using Xg): Yg with
|given (using /*x$1<<(5:13)>>: */Xg): Yg with
| def doY/*: String<<scala/Predef.String#>>*/ = "7"
|""".stripMargin
)
Expand Down Expand Up @@ -545,15 +566,22 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
)

check(
"ord",
"ord".tag(IgnoreForScala3CompilerPC),
"""|object Main {
| val ordered = "acb".sorted
|}
|""".stripMargin,
"""|object Main {
| val ordered/*: String<<scala/Predef.String#>>*/ = /*augmentString<<scala/Predef.augmentString().>>(*/"acb"/*)*/.sorted/*[Char<<scala/Char#>>]*//*(Char<<scala/math/Ordering.Char.>>)*/
|}
|""".stripMargin
|""".stripMargin,
compat = Map(
"3" ->
"""|object Main {
| val ordered/*: String<<scala/Predef.String#>>*/ = /*augmentString<<scala/Predef.augmentString().>>(*/"acb"/*)*/.sorted/*[Char<<scala/Char#>>]*//*(using Char<<scala/math/Ordering.Char.>>)*/
|}
|""".stripMargin
)
)

check(
Expand Down Expand Up @@ -599,7 +627,9 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
)

check(
"complex".tag(IgnoreScalaVersion.forLessThan("2.12.16")),
"complex".tag(
IgnoreScalaVersion.forLessThan("2.12.16").and(IgnoreForScala3CompilerPC)
),
"""|object ScalatestMock {
| class SRF
| implicit val subjectRegistrationFunction: SRF = new SRF()
Expand Down Expand Up @@ -673,7 +703,47 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
| def checkThing1[A](implicit ev: Eq[A])/*: Nothing<<scala/Nothing#>>*/ = ???
| def checkThing2[A](implicit ev: Eq[A], sem: Semigroup[A])/*: Nothing<<scala/Nothing#>>*/ = ???
|}
|""".stripMargin
|""".stripMargin,
compat = Map(
"3" ->
"""|object ScalatestMock {
| class SRF
| implicit val subjectRegistrationFunction: SRF = new SRF()
| class Position
| implicit val here: Position = new Position()
| implicit class StringTestOps(name: String) {
| def should(right: => Unit)(implicit config: SRF): Unit = ()
| def in(f: => Unit)(implicit pos: Position): Unit = ()
| }
| implicit def instancesString: Eq[String] with Semigroup[String] = ???
|}
|
|trait Eq[A]
|trait Semigroup[A]
|
|class DemoSpec {
| import ScalatestMock._
|
| /*StringTestOps<<(6:17)>>(*/"foo"/*)*/ should {
| /*StringTestOps<<(6:17)>>(*/"checkThing1"/*)*/ in {
| checkThing1[String]/*(using instancesString<<(10:15)>>)*/
| }/*(using here<<(5:15)>>)*/
| /*StringTestOps<<(6:17)>>(*/"checkThing2"/*)*/ in {
| 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]/*(using instancesString<<(10:15)>>)*/
| }/*(using here<<(5:15)>>)*/
| }/*(using subjectRegistrationFunction<<(3:15)>>)*/
|
| def checkThing1[A](implicit ev: Eq[A])/*: Nothing<<scala/Nothing#>>*/ = ???
| def checkThing2[A](implicit ev: Eq[A], sem: Semigroup[A])/*: Nothing<<scala/Nothing#>>*/ = ???
|}
|""".stripMargin
)
)

check(
Expand Down Expand Up @@ -744,4 +814,37 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
|case class ErrorMessage(error)
|""".stripMargin
)

// NOTE: We don't show inlayHints for anonymous given instances
check(
"anonymous-given".tag(IgnoreScala2.and(IgnoreForScala3CompilerPC)),
"""|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<<scala/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<<scala/Int#>>*/ =
| /*augmentString<<scala/Predef.augmentString().>>(*/x/*)*/.compare(y)
|
|""".stripMargin
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,4 @@ example/nested/LocalClass.scala -> example/nested/LocalClass#
example/nested/package.scala -> example/PackageObjectSibling#
example/nested/package.scala -> example/nested/package.
example/package.scala -> example/package.
example/type/Backtick.scala -> example/type/Backtick#
example/type/Backtick.scala -> example/type/Backtick#
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ given given_Char: Char = '?'
given `given_Float`: Float = 3.0
given `* *` : Long = 5

def method(using Int)/*: String<<java/lang/String#>>*/ = ""
def method(using /*x$1<<(10:17)>>: */Int)/*: String<<java/lang/String#>>*/ = ""

object X:
given Double = 4.0
Expand All @@ -28,7 +28,7 @@ trait Zg[T]:
given Xg with
def doX/*: Int<<scala/Int#>>*/ = 7

given (using Xg): Yg with
given (using /*x$1<<(30:13)>>: */Xg): Yg with
def doY/*: String<<scala/Predef.String#>>*/ = "7"

given [T]: Zg[T] with
Expand All @@ -43,5 +43,5 @@ val f/*: Float<<scala/Float#>>*/ = given_Float
val g/*: Long<<scala/Long#>>*/ = `* *`
val i/*: Option<<scala/Option#>>[Int<<scala/Int#>>]*/ = X.of[Int]
val x/*: given_Xg<<(27:6)>>.type*/ = given_Xg
val y/*: given_Yg<<(30:6)>>*/ = given_Yg/*(given_Xg<<(27:0)>>)*/
val y/*: given_Yg<<(30:6)>>*/ = given_Yg/*(using given_Xg<<(27:0)>>)*/
val z/*: given_Zg_T<<(33:6)>>[String<<scala/Predef.String#>>]*/ = given_Zg_T[String]
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package example

type Toplevel = Int
type Toplevel = Int
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<<package>>/*keyword*/ <<example>>/*namespace*/

<<type>>/*keyword*/ <<Toplevel>>/*type,definition*/ = <<Int>>/*class,abstract*/
<<type>>/*keyword*/ <<Toplevel>>/*type,definition*/ = <<Int>>/*class,abstract*/

0 comments on commit 340ecd4

Please sign in to comment.