Skip to content

Commit 98fb4dc

Browse files
committed
fix type alias completion, improve previous match type fix
1 parent af34319 commit 98fb4dc

File tree

4 files changed

+68
-37
lines changed

4 files changed

+68
-37
lines changed

compiler/src/dotty/tools/dotc/interactive/Completion.scala

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import dotty.tools.dotc.core.Symbols.{Symbol, defn}
1616
import dotty.tools.dotc.core.StdNames.nme
1717
import dotty.tools.dotc.core.SymDenotations.SymDenotation
1818
import dotty.tools.dotc.core.TypeError
19-
import dotty.tools.dotc.core.Types.{ExprType, MethodOrPoly, NameFilter, NoType, TermRef, Type}
19+
import dotty.tools.dotc.core.Types.{AppliedType, ExprType, MethodOrPoly, NameFilter, NoType, TermRef, Type}
2020
import dotty.tools.dotc.parsing.Tokens
2121
import dotty.tools.dotc.util.Chars
2222
import dotty.tools.dotc.util.SourcePosition
@@ -310,22 +310,21 @@ object Completion {
310310
resultMappings
311311
}
312312

313-
/** Replaces underlying type with reduced one, when it's MatchType */
314-
def reduceUnderlyingMatchType(qual: Tree)(using Context): Tree=
315-
qual.tpe.widen match
316-
case ctx.typer.MatchTypeInDisguise(mt) => qual.withType(mt)
313+
def widenDealiasAppliedTypes(qual: Tree)(using Context): Tree =
314+
qual.tpe.widenDealias match
315+
case appliedType: AppliedType => qual.withType(appliedType)
317316
case _ => qual
318317

319318
/** Completions for selections from a term.
320319
* Direct members take priority over members from extensions
321320
* and so do members from extensions over members from implicit conversions
322321
*/
323322
def selectionCompletions(qual: Tree)(using Context): CompletionMap =
324-
val reducedQual = reduceUnderlyingMatchType(qual)
323+
val adjustedQual = widenDealiasAppliedTypes(qual)
325324

326-
implicitConversionMemberCompletions(reducedQual) ++
327-
extensionCompletions(reducedQual) ++
328-
directMemberCompletions(reducedQual)
325+
implicitConversionMemberCompletions(adjustedQual) ++
326+
extensionCompletions(adjustedQual) ++
327+
directMemberCompletions(adjustedQual)
329328

330329
/** Completions for members of `qual`'s type.
331330
* These include inherited definitions but not members added by extensions or implicit conversions

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,22 +1522,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
15221522
assignType(cpy.Closure(tree)(env1, meth1, target), meth1, target)
15231523
}
15241524

1525-
/** Extractor for match types hidden behind an AppliedType/MatchAlias */
1526-
object MatchTypeInDisguise {
1527-
def unapply(tp: AppliedType)(using Context): Option[MatchType] = tp match {
1528-
case AppliedType(tycon: TypeRef, args) =>
1529-
tycon.info match {
1530-
case MatchAlias(alias) =>
1531-
alias.applyIfParameterized(args) match {
1532-
case mt: MatchType => Some(mt)
1533-
case _ => None
1534-
}
1535-
case _ => None
1536-
}
1537-
case _ => None
1538-
}
1539-
}
1540-
15411525
def typedMatch(tree: untpd.Match, pt: Type)(using Context): Tree =
15421526
tree.selector match {
15431527
case EmptyTree =>
@@ -1565,6 +1549,21 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
15651549
val selType = rawSelectorTpe match
15661550
case c: ConstantType if tree.isInline => c
15671551
case otherTpe => otherTpe.widen
1552+
/** Extractor for match types hidden behind an AppliedType/MatchAlias */
1553+
object MatchTypeInDisguise {
1554+
def unapply(tp: AppliedType)(using Context): Option[MatchType] = tp match {
1555+
case AppliedType(tycon: TypeRef, args) =>
1556+
tycon.info match {
1557+
case MatchAlias(alias) =>
1558+
alias.applyIfParameterized(args) match {
1559+
case mt: MatchType => Some(mt)
1560+
case _ => None
1561+
}
1562+
case _ => None
1563+
}
1564+
case _ => None
1565+
}
1566+
}
15681567

15691568
/** Does `tree` has the same shape as the given match type?
15701569
* We only support typed patterns with empty guards, but

language-server/test/dotty/tools/languageserver/CompletionTest.scala

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,7 @@ class CompletionTest {
10011001
)
10021002
code"""import scala.concurrent.Future
10031003
|class Foo(x: Fut${m1})""".withSource
1004-
.completion(m1, expected)
1004+
.completion(m1, expected)
10051005
}
10061006

10071007
@Test def completeTemplateParents: Unit = {
@@ -1011,7 +1011,7 @@ class CompletionTest {
10111011
)
10121012
code"""import scala.concurrent.Future
10131013
|class Foo extends Futu${m1}""".withSource
1014-
.completion(m1, expected)
1014+
.completion(m1, expected)
10151015
}
10161016

10171017
@Test def completeTemplateSelfType: Unit = {
@@ -1021,7 +1021,7 @@ class CompletionTest {
10211021
)
10221022
code"""import scala.concurrent.Future
10231023
|class Foo[A]{ self: Futu${m1} => }""".withSource
1024-
.completion(m1, expected)
1024+
.completion(m1, expected)
10251025
}
10261026

10271027
@Test def backticks: Unit = {
@@ -1061,7 +1061,7 @@ class CompletionTest {
10611061
| enum Bar:
10621062
| case `back-tick`
10631063
| case `match`
1064-
|
1064+
|
10651065
| val x = Bar.${m1}"""
10661066
.withSource.completion(m1, expected)
10671067
}
@@ -1074,7 +1074,7 @@ class CompletionTest {
10741074
| enum Bar:
10751075
| case `back-tick`
10761076
| case `match`
1077-
|
1077+
|
10781078
| val x = Bar.`back${m1}"""
10791079
.withSource.completion(m1, expected)
10801080
}
@@ -1086,7 +1086,7 @@ class CompletionTest {
10861086
code"""object Foo:
10871087
| enum Bar:
10881088
| case `has space`
1089-
|
1089+
|
10901090
| val x = Bar.`has s${m1}"""
10911091
.withSource.completion(m1, expected)
10921092
}
@@ -1102,7 +1102,7 @@ class CompletionTest {
11021102
| val foo = 1
11031103
| val `foo-bar` = 2
11041104
| val `bar` = 3
1105-
|
1105+
|
11061106
| val x = Bar.fo${m1}"""
11071107
.withSource.completion(m1, expected)
11081108
}
@@ -1117,7 +1117,7 @@ class CompletionTest {
11171117
| object Bar:
11181118
| val foo = 1
11191119
| val `foo-bar` = 2
1120-
|
1120+
|
11211121
| val x = Bar.`fo${m1}"""
11221122
.withSource.completion(m1, expected)
11231123
}
@@ -1146,7 +1146,7 @@ class CompletionTest {
11461146
| case x: Int => Foo(x)
11471147
| case x: Any => x
11481148
|}
1149-
|object Test:
1149+
|object Test:
11501150
| elem(1).foo${m1}"""
11511151
.withSource.completion(m1, expected)
11521152
}
@@ -1245,4 +1245,40 @@ class CompletionTest {
12451245
.withSource.completion(m1, expected)
12461246
}
12471247

1248+
@Test def typeAliasCompletions: Unit = {
1249+
val expected = Set(
1250+
("fooTest", Method, "(x: Int): Unit"),
1251+
)
1252+
1253+
code"""class Test() {
1254+
| def fooTest(x: Int): Unit = ???
1255+
|}
1256+
|type TestAlias = Test
1257+
|object M:
1258+
| val test: TestAlias = new Test()
1259+
| test.foo${m1}"""
1260+
.withSource.completion(m1, expected)
1261+
1262+
}
1263+
1264+
@Test def higherKindedTypeAliasesCompletions: Unit = {
1265+
val expected = Set(
1266+
("fooTest", Method, "(x: Int): Option[Unit]"),
1267+
)
1268+
code"""trait Test[F[_]] {
1269+
| def fooTest(x: Int): F[Unit] = ???
1270+
|}
1271+
|
1272+
|type TestAlias[M[_[_]]] = M[Option]
1273+
|object M:
1274+
| val test: TestAlias[Test] = new Test[Option] {}
1275+
| val test2: Test[Option] = new Test[Option] {}
1276+
| test.foo${m1}
1277+
| test2.foo${m2}""".withSource
1278+
.completion(m1, expected)
1279+
.completion(m2, expected)
1280+
1281+
}
1282+
1283+
12481284
}

language-server/test/dotty/tools/languageserver/util/CodeTester.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ import dotty.tools.languageserver.util.Code._
44
import dotty.tools.languageserver.util.actions._
55
import dotty.tools.languageserver.util.embedded.CodeMarker
66
import dotty.tools.languageserver.util.server.{TestFile, TestServer}
7-
87
import dotty.tools.dotc.reporting.ErrorMessageID
98
import dotty.tools.dotc.util.Signatures.Signature
109

1110
import org.eclipse.lsp4j.{ CompletionItem, CompletionItemKind, DocumentHighlightKind, Diagnostic, DiagnosticSeverity }
12-
1311
import org.junit.Assert.assertEquals
1412

15-
import org.junit.Assert.assertEquals
1613

1714
/**
1815
* Simulates an LSP client for test in a project defined by `sources`.

0 commit comments

Comments
 (0)