Skip to content

Commit 3370e96

Browse files
committed
bugfix: Fix enumeration issues when Value is imported (scala#23124)
This is still not a perfect fix, since we add the full prefix, but that's the current status quo. Making prefixes shorter is something we need to work on separately.
1 parent e7aee4f commit 3370e96

File tree

4 files changed

+96
-11
lines changed

4 files changed

+96
-11
lines changed

presentation-compiler/src/main/dotty/tools/pc/IndexedContext.scala

+27-7
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ sealed trait IndexedContext:
2323
given ctx: Context
2424
def scopeSymbols: List[Symbol]
2525
def rename(sym: Symbol): Option[String]
26-
def findSymbol(name: Name): Option[List[Symbol]]
26+
def findSymbol(name: Name, fromPrefix: Option[Type] = None): Option[List[Symbol]]
2727
def findSymbolInLocalScope(name: String): Option[List[Symbol]]
2828

29-
final def lookupSym(sym: Symbol): Result =
29+
final def lookupSym(sym: Symbol, fromPrefix: Option[Type] = None): Result =
3030
def all(symbol: Symbol): Set[Symbol] = Set(symbol, symbol.companionModule, symbol.companionClass, symbol.companion).filter(_ != NoSymbol)
3131
val isRelated = all(sym) ++ all(sym.dealiasType)
32-
findSymbol(sym.name) match
32+
findSymbol(sym.name, fromPrefix) match
3333
case Some(symbols) if symbols.exists(isRelated) => Result.InScope
3434
case Some(symbols) if symbols.exists(isTermAliasOf(_, sym)) => Result.InScope
3535
case Some(symbols) if symbols.map(_.dealiasType).exists(isRelated) => Result.InScope
@@ -81,7 +81,7 @@ object IndexedContext:
8181

8282
case object Empty extends IndexedContext:
8383
given ctx: Context = NoContext
84-
def findSymbol(name: Name): Option[List[Symbol]] = None
84+
def findSymbol(name: Name, fromPrefix: Option[Type]): Option[List[Symbol]] = None
8585
def findSymbolInLocalScope(name: String): Option[List[Symbol]] = None
8686
def scopeSymbols: List[Symbol] = List.empty
8787
def rename(sym: Symbol): Option[String] = None
@@ -111,11 +111,31 @@ object IndexedContext:
111111

112112
override def findSymbolInLocalScope(name: String): Option[List[Symbol]] =
113113
names.get(name).map(_.map(_.symbol).toList).filter(_.nonEmpty)
114-
def findSymbol(name: Name): Option[List[Symbol]] =
114+
def findSymbol(name: Name, fromPrefix: Option[Type]): Option[List[Symbol]] =
115115
names
116116
.get(name.show)
117-
.map(_.map(_.symbol).toList)
118-
.orElse(defaultScopes(name))
117+
.map { denots =>
118+
def skipThisType(tp: Type): Type = tp match
119+
case ThisType(prefix) => skipThisType(prefix)
120+
case _ => tp
121+
122+
val filteredDenots = fromPrefix match
123+
case Some(prefix) =>
124+
val target = skipThisType(prefix)
125+
denots.filter { denot =>
126+
denot.prefix == NoPrefix ||
127+
(denot.prefix match
128+
case tref: TermRef =>
129+
tref.termSymbol.info <:< target
130+
case otherPrefix =>
131+
otherPrefix <:< target
132+
)
133+
}
134+
case None => denots
135+
136+
filteredDenots.map(_.symbol).toList
137+
}
138+
.orElse(defaultScopes(name)).filter(_.nonEmpty)
119139

120140
def scopeSymbols: List[Symbol] =
121141
names.values.flatten.map(_.symbol).toList

presentation-compiler/src/main/dotty/tools/pc/InferredTypeProvider.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ final class InferredTypeProvider(
9494
tpe match
9595
case tref: TypeRef =>
9696
indexedCtx.lookupSym(
97-
tref.currentSymbol
97+
tref.currentSymbol,
98+
Some(tref.prefix)
9899
) == IndexedContext.Result.InScope
99100
case AppliedType(tycon, args) =>
100101
isInScope(tycon) && args.forall(isInScope)
@@ -137,7 +138,6 @@ final class InferredTypeProvider(
137138
findNamePos(sourceText, vl, keywordOffset).endPos.toLsp
138139
adjustOpt.foreach(adjust => endPos.setEnd(adjust.adjustedEndPos))
139140
val spaceBefore = name.isOperatorName
140-
141141
new TextEdit(
142142
endPos,
143143
printTypeAscription(optDealias(tpt.typeOpt), spaceBefore) + {

presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala

+1-2
Original file line numberDiff line numberDiff line change
@@ -174,14 +174,13 @@ class ShortenedTypePrinter(
174174
res.toPrefixText
175175
}
176176

177-
178177
override def toTextPrefixOf(tp: NamedType): Text = controlled {
179178
val maybeRenamedPrefix: Option[Text] = findRename(tp)
180179
def trimmedPrefix: Text =
181180
if !tp.designator.isInstanceOf[Symbol] && tp.typeSymbol == NoSymbol then
182181
super.toTextPrefixOf(tp)
183182
else
184-
indexedCtx.lookupSym(tp.symbol) match
183+
indexedCtx.lookupSym(tp.symbol, Some(tp.prefix)) match
185184
case _ if indexedCtx.rename(tp.symbol).isDefined => Text()
186185
// symbol is missing and is accessible statically, we can import it and add proper prefix
187186
case Result.Missing if isAccessibleStatically(tp.symbol) =>

presentation-compiler/test/dotty/tools/pc/tests/edit/InsertInferredTypeSuite.scala

+66
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,72 @@ class InsertInferredTypeSuite extends BaseCodeActionSuite:
970970
|""".stripMargin
971971
)
972972

973+
@Test def `enums` =
974+
checkEdit(
975+
"""|object EnumerationValue:
976+
| object Day extends Enumeration {
977+
| type Day = Value
978+
| val Weekday, Weekend = Value
979+
| }
980+
| object Bool extends Enumeration {
981+
| type Bool = Value
982+
| val True, False = Value
983+
| }
984+
| import Bool._
985+
| def day(d: Day.Value): Unit = ???
986+
| val <<d>> =
987+
| if (true) Day.Weekday
988+
| else Day.Weekend
989+
|""".stripMargin,
990+
"""|object EnumerationValue:
991+
| object Day extends Enumeration {
992+
| type Day = Value
993+
| val Weekday, Weekend = Value
994+
| }
995+
| object Bool extends Enumeration {
996+
| type Bool = Value
997+
| val True, False = Value
998+
| }
999+
| import Bool._
1000+
| def day(d: Day.Value): Unit = ???
1001+
| val d: EnumerationValue.Day.Value =
1002+
| if (true) Day.Weekday
1003+
| else Day.Weekend
1004+
|""".stripMargin
1005+
)
1006+
1007+
@Test def `enums2` =
1008+
checkEdit(
1009+
"""|object EnumerationValue:
1010+
| object Day extends Enumeration {
1011+
| type Day = Value
1012+
| val Weekday, Weekend = Value
1013+
| }
1014+
| object Bool extends Enumeration {
1015+
| type Bool = Value
1016+
| val True, False = Value
1017+
| }
1018+
| import Bool._
1019+
| val <<b>> =
1020+
| if (true) True
1021+
| else False
1022+
|""".stripMargin,
1023+
"""|object EnumerationValue:
1024+
| object Day extends Enumeration {
1025+
| type Day = Value
1026+
| val Weekday, Weekend = Value
1027+
| }
1028+
| object Bool extends Enumeration {
1029+
| type Bool = Value
1030+
| val True, False = Value
1031+
| }
1032+
| import Bool._
1033+
| val b: Value =
1034+
| if (true) True
1035+
| else False
1036+
|""".stripMargin
1037+
)
1038+
9731039
def checkEdit(
9741040
original: String,
9751041
expected: String

0 commit comments

Comments
 (0)