Skip to content

Commit 32545a2

Browse files
committed
merge enum clause with other addendums
1 parent 58e084e commit 32545a2

File tree

5 files changed

+69
-43
lines changed

5 files changed

+69
-43
lines changed

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import printing.Formatting.hl
2323
import ast.Trees._
2424
import ast.untpd
2525
import ast.tpd
26+
import transform.SymUtils._
2627

2728
/** Messages
2829
* ========
@@ -323,16 +324,29 @@ import ast.tpd
323324
.filter((d, n) => d <= maxDist && d < missing.length && d < n.length)
324325
.sorted // sort by distance first, alphabetically second
325326

327+
val enumClause =
328+
if ((name eq nme.values) || (name eq nme.valueOf)) && site.classSymbol.companionClass.isEnumClass then
329+
val kind = if name eq nme.values then i"${nme.values} array" else i"${nme.valueOf} lookup method"
330+
// an assumption is made here that the values and valueOf methods were not generated
331+
// because the enum defines non-singleton cases
332+
i"""
333+
|Although ${site.classSymbol.companionClass} is an enum, it has non-singleton cases,
334+
|meaning a $kind is not defined"""
335+
else
336+
""
337+
338+
def prefixEnumClause(addendum: String) =
339+
if enumClause.nonEmpty then s".$enumClause$addendum" else addendum
340+
326341
val finalAddendum =
327-
if addendum.nonEmpty then addendum
328-
else closest match {
342+
if addendum.nonEmpty then prefixEnumClause(addendum)
343+
else closest match
329344
case (d, n) :: _ =>
330345
val siteName = site match
331346
case site: NamedType => site.name.show
332347
case site => i"$site"
333-
s" - did you mean $siteName.$n?"
334-
case Nil => ""
335-
}
348+
s" - did you mean $siteName.$n?$enumClause"
349+
case Nil => prefixEnumClause("")
336350

337351
ex"$selected $name is not a member of ${site.widen}$finalAddendum"
338352
}

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

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ package typer
44

55
import ast._
66
import core._
7-
import Types._, ProtoTypes._, Contexts._, Decorators._, Denotations._, Symbols._, Names._
7+
import Types._, ProtoTypes._, Contexts._, Decorators._, Denotations._, Symbols._
88
import Implicits._, Flags._, Constants.Constant
99
import util.Spans._
1010
import util.SrcPos
1111
import config.Feature
1212
import java.util.regex.Matcher.quoteReplacement
1313
import reporting._
14-
import transform.SymUtils._
15-
import StdNames._
1614

1715
object ErrorReporting {
1816

@@ -147,7 +145,7 @@ object ErrorReporting {
147145
else ""
148146

149147
def selectErrorAddendum
150-
(tree: untpd.RefTree, qual1: Tree, qualType: Type, name: Name, suggestImports: Type => String)
148+
(tree: untpd.RefTree, qual1: Tree, qualType: Type, suggestImports: Type => String)
151149
(using Context): String =
152150
val attempts: List[Tree] = qual1.getAttachment(Typer.HiddenSearchFailure) match
153151
case Some(failures) =>
@@ -173,13 +171,6 @@ object ErrorReporting {
173171
|or drop any spaces behind the operator."""
174172
else if qualType.isBottomType then
175173
""
176-
else if ((name eq nme.values) || (name eq nme.valueOf)) && qualType.classSymbol.companionClass.isEnumClass then
177-
val kind = if name eq nme.values then i"${nme.values} array" else i"${nme.valueOf} lookup method"
178-
// an assumption is made here that the values and valueOf methods were not generated
179-
// because the enum defines non-singleton cases
180-
i""".
181-
|Although ${qualType.classSymbol.companionClass} is an enum, it has non-singleton cases,
182-
|which prevents it from having a $kind."""
183174
else
184175
val add = suggestImports(
185176
ViewProto(qualType.widen,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ trait TypeAssigner {
163163
errorType(ex"$qualType does not have a constructor", tree.srcPos)
164164
else {
165165
val kind = if (name.isTypeName) "type" else "value"
166-
def addendum = err.selectErrorAddendum(tree, qual1, qualType, name, importSuggestionAddendum)
166+
def addendum = err.selectErrorAddendum(tree, qual1, qualType, importSuggestionAddendum)
167167
errorType(NotAMember(qualType, name, kind, addendum), tree.srcPos)
168168
}
169169
}

tests/neg/enum-values.check

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,61 @@
1-
-- [E008] Not Found Error: tests/neg/enum-values.scala:28:45 -----------------------------------------------------------
2-
28 | val tags: Array[Tag[?]] = Tag.values // error
1+
-- [E008] Not Found Error: tests/neg/enum-values.scala:32:45 -----------------------------------------------------------
2+
32 | val tags: Array[Tag[?]] = Tag.values // error
33
| ^^^^^^^^^^
44
| value values is not a member of object example.Tag.
55
| Although class Tag is an enum, it has non-singleton cases,
6-
| which prevents it from having a values array.
7-
-- [E008] Not Found Error: tests/neg/enum-values.scala:29:50 -----------------------------------------------------------
8-
29 | val listlikes: Array[ListLike[?]] = ListLike.values // error
6+
| meaning a values array is not defined.
7+
| An extension method was tried, but could not be fully constructed:
8+
|
9+
| example.Extensions.extension_values(Tag)
10+
-- [E008] Not Found Error: tests/neg/enum-values.scala:33:50 -----------------------------------------------------------
11+
33 | val listlikes: Array[ListLike[?]] = ListLike.values // error
912
| ^^^^^^^^^^^^^^^
1013
| value values is not a member of object example.ListLike.
1114
| Although class ListLike is an enum, it has non-singleton cases,
12-
| which prevents it from having a values array.
13-
-- [E008] Not Found Error: tests/neg/enum-values.scala:30:52 -----------------------------------------------------------
14-
30 | val typeCtorsK: Array[TypeCtorsK[?]] = TypeCtorsK.values // error
15+
| meaning a values array is not defined.
16+
| An extension method was tried, but could not be fully constructed:
17+
|
18+
| example.Extensions.extension_values(ListLike)
19+
-- [E008] Not Found Error: tests/neg/enum-values.scala:34:52 -----------------------------------------------------------
20+
34 | val typeCtorsK: Array[TypeCtorsK[?]] = TypeCtorsK.values // error
1521
| ^^^^^^^^^^^^^^^^^
1622
| value values is not a member of object example.TypeCtorsK.
1723
| Although class TypeCtorsK is an enum, it has non-singleton cases,
18-
| which prevents it from having a values array.
19-
-- [E008] Not Found Error: tests/neg/enum-values.scala:32:6 ------------------------------------------------------------
20-
32 | Tag.valueOf("Int") // error
24+
| meaning a values array is not defined.
25+
| An extension method was tried, but could not be fully constructed:
26+
|
27+
| example.Extensions.extension_values(TypeCtorsK)
28+
-- [E008] Not Found Error: tests/neg/enum-values.scala:36:6 ------------------------------------------------------------
29+
36 | Tag.valueOf("Int") // error
2130
| ^^^^^^^^^^^
2231
| value valueOf is not a member of object example.Tag.
2332
| Although class Tag is an enum, it has non-singleton cases,
24-
| which prevents it from having a valueOf lookup method.
25-
-- [E008] Not Found Error: tests/neg/enum-values.scala:33:11 -----------------------------------------------------------
26-
33 | ListLike.valueOf("EmptyListLike") // error
33+
| meaning a valueOf lookup method is not defined
34+
-- [E008] Not Found Error: tests/neg/enum-values.scala:37:11 -----------------------------------------------------------
35+
37 | ListLike.valueOf("EmptyListLike") // error
2736
| ^^^^^^^^^^^^^^^^
28-
| value valueOf is not a member of object example.ListLike.
37+
| value valueOf is not a member of object example.ListLike - did you mean ListLike.valuef?
2938
| Although class ListLike is an enum, it has non-singleton cases,
30-
| which prevents it from having a valueOf lookup method.
31-
-- [E008] Not Found Error: tests/neg/enum-values.scala:34:13 -----------------------------------------------------------
32-
34 | TypeCtorsK.valueOf("Option") // error
39+
| meaning a valueOf lookup method is not defined
40+
-- [E008] Not Found Error: tests/neg/enum-values.scala:38:13 -----------------------------------------------------------
41+
38 | TypeCtorsK.valueOf("Option") // error
3342
| ^^^^^^^^^^^^^^^^^^
3443
| value valueOf is not a member of object example.TypeCtorsK.
3544
| Although class TypeCtorsK is an enum, it has non-singleton cases,
36-
| which prevents it from having a valueOf lookup method.
37-
-- [E008] Not Found Error: tests/neg/enum-values.scala:36:12 -----------------------------------------------------------
38-
36 | NotAnEnum.values // error
45+
| meaning a valueOf lookup method is not defined, but could be made available as an extension method.
46+
|
47+
| The following import might fix the problem:
48+
|
49+
| import example.UnimportedExtensions.valueOf
50+
|
51+
-- [E008] Not Found Error: tests/neg/enum-values.scala:40:12 -----------------------------------------------------------
52+
40 | NotAnEnum.values // error
3953
| ^^^^^^^^^^^^^^^^
40-
| value values is not a member of object example.NotAnEnum
41-
-- [E008] Not Found Error: tests/neg/enum-values.scala:37:12 -----------------------------------------------------------
42-
37 | NotAnEnum.valueOf("Foo") // error
54+
| value values is not a member of object example.NotAnEnum.
55+
| An extension method was tried, but could not be fully constructed:
56+
|
57+
| example.Extensions.extension_values(NotAnEnum)
58+
-- [E008] Not Found Error: tests/neg/enum-values.scala:41:12 -----------------------------------------------------------
59+
41 | NotAnEnum.valueOf("Foo") // error
4360
| ^^^^^^^^^^^^^^^^^
4461
| value valueOf is not a member of object example.NotAnEnum

tests/neg/enum-values.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,22 @@ object ListLike:
1212
def valuef(s: String): ListLike[?] = ??? // this will usually trigger a "- did you mean ListLike.valuef" addendum
1313

1414
object Extensions:
15-
extension (TagModule: Tag.type) // this will usually trigger an import suggestions addendum
15+
extension (foo: Nothing) // this will usually trigger an attempted extension method addendum
1616
def values: Array[Tag[?]] = ???
1717

1818
enum TypeCtorsK[F[_]]:
1919
case List extends TypeCtorsK[List]
2020
case Option extends TypeCtorsK[Option]
2121
case Const[T]() extends TypeCtorsK[[U] =>> T]
2222

23+
object UnimportedExtensions:
24+
extension (TypeCtorsKModule: TypeCtorsK.type) // this will usually trigger an import suggestions addendum
25+
def valueOf(name: String): TypeCtorsK[?] = ???
26+
2327
object NotAnEnum // object without a companion class
2428

2529
def Test: Unit =
26-
import Tag._, ListLike._, TypeCtorsK._
30+
import Tag._, ListLike._, TypeCtorsK._, Extensions._
2731

2832
val tags: Array[Tag[?]] = Tag.values // error
2933
val listlikes: Array[ListLike[?]] = ListLike.values // error

0 commit comments

Comments
 (0)