Skip to content

Commit

Permalink
add more tests, reduce Tree
Browse files Browse the repository at this point in the history
  • Loading branch information
rochala committed Mar 15, 2022
1 parent 59d86d4 commit 61822d2
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 13 deletions.
21 changes: 11 additions & 10 deletions compiler/src/dotty/tools/dotc/interactive/Completion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -295,15 +295,22 @@ object Completion {
resultMappings
}

/** Replaces underlying type with reduced one, when it's MatchType */
def reduceUnderlyingMatchType(qual: Tree)(using Context): Tree=
qual.tpe.widen match
case ctx.typer.MatchTypeInDisguise(mt) => qual.withType(mt)
case _ => qual

/** Completions for selections from a term.
* Direct members take priority over members from extensions
* and so do members from extensions over members from implicit conversions
*/
def selectionCompletions(qual: Tree)(using Context): CompletionMap =
implicitConversionMemberCompletions(qual) ++
extensionCompletions(qual) ++
matchTypeCompletions(qual) ++
directMemberCompletions(qual)
val reducedQual = reduceUnderlyingMatchType(qual)

implicitConversionMemberCompletions(reducedQual) ++
extensionCompletions(reducedQual) ++
directMemberCompletions(reducedQual)

/** Completions for members of `qual`'s type.
* These include inherited definitions but not members added by extensions or implicit conversions
Expand Down Expand Up @@ -363,12 +370,6 @@ object Completion {
implicitConversionTargets(qual)(using ctx.fresh.setExploreTyperState()).flatMap(accessibleMembers)
membersFromConversion.toSeq.groupByName

/** Completions for derived members of `MatchType`'s type. */
def matchTypeCompletions(qual: Tree)(using Context): CompletionMap =
qual.tpe.widenDealias match
case ctx.typer.MatchTypeInDisguise(mt) => accessibleMembers(mt.reduced).groupByName
case _ => Map.empty

/** Completions from extension methods */
private def extensionCompletions(qual: Tree)(using Context): CompletionMap =
def asDefLikeType(tpe: Type): Type = tpe match
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class CompletionTest {
@Test def completionFromScalaPredef: Unit = {
code"class Foo { def foo: Unit = prin${m1} }".withSource
.completion(m1, Set(
("print", Method, "(x: Any): Unit"),
("print", Method, "(x: Any): Unit"),
("printf", Method, "(text: String, xs: Any*): Unit"),
("println", Method, "(x: Any): Unit"),
("println", Method, "(): Unit")
Expand Down Expand Up @@ -1122,19 +1122,98 @@ class CompletionTest {
.withSource.completion(m1, expected)
}

@Test def matchTypeCompletion: Unit = {
@Test def matchTypeCompletions: Unit = {
val expected = Set(
("fooTest", Method, "(y: Int): Int"),
)
code"""case class Foo(x: Int) {
| def fooTest(y: Int): Int = ???
|}
|type Elem[X] = X match {
| case Int => Foo
| case Any => X
|}
|def elem[X](x: X): Elem[X] = x match {
| case x: Int => Foo(x)
| case x: Any => x
|}
|object Test:
| elem(1).foo${m1}"""
.withSource.completion(m1, expected)
}

@Test def higherKindedMatchTypeDeclaredCompletion: Unit = {
val expected = Set(
("map", Method, "[B](f: Int => B): Foo[B]"),
)
code"""trait Foo[A] {
| def map[B](f: A => B): Foo[B]
| def map[B](f: A => B): Foo[B] = ???
|}
|case class Bar[F[_]](bar: F[Int])
|type M[T] = T match {
| case Int => Foo[Int]
|}
|object Test:
| val x = Bar[M](new Foo[Int]{})
| x.bar.m${m1}"""
.withSource.completion(m1, expected)
}

@Test def higherKindedMatchTypeLazyCompletion: Unit = {
val expected = Set(
("map", Method, "[B](f: Int => B): Foo[B]"),
)
code"""trait Foo[A] {
| def map[B](f: A => B): Foo[B] = ???
|}
|case class Bar[F[_]](bar: F[Int])
|type M[T] = T match {
| case Int => Foo[Int]
|}
|def foo(x: Bar[M]) = x.bar.m${m1}"""
.withSource.completion(m1, expected)
}

// This test is not passing due to https://github.com/lampepfl/dotty/issues/14687
// @Test def higherKindedMatchTypeImplicitConversionCompletion: Unit = {
// val expected = Set(
// ("mapBoo", Method, "[B](op: Int => B): Boo[B]"),
// ("mapFoo", Method, "[B](op: Int => B): Foo[B]"),
// )
// code"""import scala.language.implicitConversions
// |case class Foo[A](x: A) {
// | def mapFoo[B](op: A => B): Foo[B] = ???
// |}
// |case class Boo[A](x: A) {
// | def mapBoo[B](op: A => B): Boo[B] = ???
// |}
// |type M[A] = A match {
// | case Int => Foo[Int]
// |}
// |implicit def fooToBoo[A](x: Foo[A]): Boo[A] = Boo(x.x)
// |case class Bar[F[_]](bar: F[Int])
// |def foo(x: Bar[M]) = x.bar.m${m1}"""
// .withSource.completion(m1, expected)
// }

@Test def higherKindedMatchTypeExtensionMethodCompletion: Unit = {
val expected = Set(
("mapFoo", Method, "[B](f: Int => B): Foo[B]"),
("mapExtensionMethod", Method, "[B](f: Int => B): Foo[B]"),
)
code"""trait Foo[A] {
| def mapFoo[B](f: A => B): Foo[B] = ???
|}
|extension[A] (x: Foo[A]) {
| def mapExtensionMethod[B](f: A => B): Foo[B] = ???
|}
|case class Baz[F[_]](baz: F[Int])
|type M[T] = T match {
| case Int => Foo[Int]
|}
|case class Bar[F[_]](bar: F[Int])
|def foo(x: Bar[M]) = x.bar.ma${m1}"""
.withSource.completion(m1, expected)
}

}

0 comments on commit 61822d2

Please sign in to comment.