Skip to content

bugfix: Fix enumeration issues when Value is imported #23124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions presentation-compiler/src/main/dotty/tools/pc/IndexedContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ sealed trait IndexedContext:
given ctx: Context
def scopeSymbols: List[Symbol]
def rename(sym: Symbol): Option[String]
def findSymbol(name: Name): Option[List[Symbol]]
def findSymbol(name: Name, fromPrefix: Option[Type] = None): Option[List[Symbol]]
def findSymbolInLocalScope(name: String): Option[List[Symbol]]

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

case object Empty extends IndexedContext:
given ctx: Context = NoContext
def findSymbol(name: Name): Option[List[Symbol]] = None
def findSymbol(name: Name, fromPrefix: Option[Type]): Option[List[Symbol]] = None
def findSymbolInLocalScope(name: String): Option[List[Symbol]] = None
def scopeSymbols: List[Symbol] = List.empty
def rename(sym: Symbol): Option[String] = None
Expand Down Expand Up @@ -111,11 +111,31 @@ object IndexedContext:

override def findSymbolInLocalScope(name: String): Option[List[Symbol]] =
names.get(name).map(_.map(_.symbol).toList).filter(_.nonEmpty)
def findSymbol(name: Name): Option[List[Symbol]] =
def findSymbol(name: Name, fromPrefix: Option[Type]): Option[List[Symbol]] =
names
.get(name.show)
.map(_.map(_.symbol).toList)
.orElse(defaultScopes(name))
.map { denots =>
def skipThisType(tp: Type): Type = tp match
case ThisType(prefix) => skipThisType(prefix)
case _ => tp

val filteredDenots = fromPrefix match
case Some(prefix) =>
val target = skipThisType(prefix)
denots.filter { denot =>
denot.prefix == NoPrefix ||
(denot.prefix match
case tref: TermRef =>
tref.termSymbol.info <:< target
case otherPrefix =>
otherPrefix <:< target
)
}
case None => denots

filteredDenots.map(_.symbol).toList
}
.orElse(defaultScopes(name)).filter(_.nonEmpty)

def scopeSymbols: List[Symbol] =
names.values.flatten.map(_.symbol).toList
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ final class InferredTypeProvider(
tpe match
case tref: TypeRef =>
indexedCtx.lookupSym(
tref.currentSymbol
tref.currentSymbol,
Some(tref.prefix)
) == IndexedContext.Result.InScope
case AppliedType(tycon, args) =>
isInScope(tycon) && args.forall(isInScope)
Expand Down Expand Up @@ -136,7 +137,6 @@ final class InferredTypeProvider(
findNamePos(sourceText, vl, keywordOffset).endPos.toLsp
adjustOpt.foreach(adjust => endPos.setEnd(adjust.adjustedEndPos))
val spaceBefore = name.isOperatorName

new TextEdit(
endPos,
printTypeAscription(optDealias(tpt.typeOpt), spaceBefore) + {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,13 @@ class ShortenedTypePrinter(
res.toPrefixText
}


override def toTextPrefixOf(tp: NamedType): Text = controlled {
val maybeRenamedPrefix: Option[Text] = findRename(tp)
def trimmedPrefix: Text =
if !tp.designator.isInstanceOf[Symbol] && tp.typeSymbol == NoSymbol then
super.toTextPrefixOf(tp)
else
indexedCtx.lookupSym(tp.symbol) match
indexedCtx.lookupSym(tp.symbol, Some(tp.prefix)) match
case _ if indexedCtx.rename(tp.symbol).isDefined => Text()
// symbol is missing and is accessible statically, we can import it and add proper prefix
case Result.Missing if isAccessibleStatically(tp.symbol) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,72 @@ class InsertInferredTypeSuite extends BaseCodeActionSuite:
|""".stripMargin
)

@Test def `enums` =
checkEdit(
"""|object EnumerationValue:
| object Day extends Enumeration {
| type Day = Value
| val Weekday, Weekend = Value
| }
| object Bool extends Enumeration {
| type Bool = Value
| val True, False = Value
| }
| import Bool._
| def day(d: Day.Value): Unit = ???
| val <<d>> =
| if (true) Day.Weekday
| else Day.Weekend
|""".stripMargin,
"""|object EnumerationValue:
| object Day extends Enumeration {
| type Day = Value
| val Weekday, Weekend = Value
| }
| object Bool extends Enumeration {
| type Bool = Value
| val True, False = Value
| }
| import Bool._
| def day(d: Day.Value): Unit = ???
| val d: EnumerationValue.Day.Value =
| if (true) Day.Weekday
| else Day.Weekend
|""".stripMargin
)

@Test def `enums2` =
checkEdit(
"""|object EnumerationValue:
| object Day extends Enumeration {
| type Day = Value
| val Weekday, Weekend = Value
| }
| object Bool extends Enumeration {
| type Bool = Value
| val True, False = Value
| }
| import Bool._
| val <<b>> =
| if (true) True
| else False
|""".stripMargin,
"""|object EnumerationValue:
| object Day extends Enumeration {
| type Day = Value
| val Weekday, Weekend = Value
| }
| object Bool extends Enumeration {
| type Bool = Value
| val True, False = Value
| }
| import Bool._
| val b: Value =
| if (true) True
| else False
|""".stripMargin
)

def checkEdit(
original: String,
expected: String
Expand Down
Loading