Skip to content

Commit bde33f0

Browse files
committed
Add error code to unused diagnostics
1 parent 05354ba commit bde33f0

File tree

4 files changed

+53
-30
lines changed

4 files changed

+53
-30
lines changed

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

+1
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe
208208
case UnstableInlineAccessorID // errorNumber: 192
209209
case VolatileOnValID // errorNumber: 193
210210
case ExtensionNullifiedByMemberID // errorNumber: 194
211+
case UnusedSymbolID // errorNumber: 195
211212

212213
def errorNumber = ordinal - 1
213214

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

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ enum MessageKind:
2121
case MatchCaseUnreachable
2222
case Compatibility
2323
case PotentialIssue
24+
case UnusedSymbol
2425

2526
/** Human readable message that will end up being shown to the user.
2627
* NOTE: This is only used in the situation where you have multiple words
@@ -37,5 +38,6 @@ enum MessageKind:
3738
case PatternMatchExhaustivity => "Pattern Match Exhaustivity"
3839
case MatchCaseUnreachable => "Match case Unreachable"
3940
case PotentialIssue => "Potential Issue"
41+
case UnusedSymbol => "Unused symbol"
4042
case kind => kind.toString
4143
end MessageKind

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

+18
Original file line numberDiff line numberDiff line change
@@ -3194,3 +3194,21 @@ class VolatileOnVal()(using Context)
31943194
extends SyntaxMsg(VolatileOnValID):
31953195
protected def msg(using Context): String = "values cannot be volatile"
31963196
protected def explain(using Context): String = ""
3197+
3198+
class UnusedSymbol(pos: SourcePosition, _msg: String, _actions: List[CodeAction])(using Context)
3199+
extends Message(UnusedSymbolID) {
3200+
def kind = MessageKind.UnusedSymbol
3201+
3202+
override def actions(using Context) = _actions
3203+
override def msg(using Context) = _msg
3204+
override def explain(using Context) = ""
3205+
}
3206+
3207+
object UnusedSymbol {
3208+
def imports(treePos: SourcePosition)(using Context): UnusedSymbol = new UnusedSymbol(treePos, i"unused import", Nil)
3209+
def localDefs(treePos: SourcePosition)(using Context): UnusedSymbol = new UnusedSymbol(treePos, i"unused local definition", Nil)
3210+
def explicitParams(treePos: SourcePosition)(using Context): UnusedSymbol = new UnusedSymbol(treePos, i"unused explicit parameter", Nil)
3211+
def implicitParams(treePos: SourcePosition)(using Context): UnusedSymbol = new UnusedSymbol(treePos, i"unused implicit parameter", Nil)
3212+
def privateMembers(treePos: SourcePosition)(using Context): UnusedSymbol = new UnusedSymbol(treePos, i"unused private member", Nil)
3213+
def patVars(treePos: SourcePosition)(using Context): UnusedSymbol = new UnusedSymbol(treePos, i"unused pattern variable", Nil)
3214+
}

compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

+32-30
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import dotty.tools.dotc.core.Phases.Phase
1313
import dotty.tools.dotc.core.StdNames
1414
import dotty.tools.dotc.report
1515
import dotty.tools.dotc.reporting.Message
16+
import dotty.tools.dotc.reporting.UnusedSymbol as UnusedSymbolMessage
1617
import dotty.tools.dotc.typer.ImportInfo
1718
import dotty.tools.dotc.util.{Property, SrcPos}
1819
import dotty.tools.dotc.core.Mode
@@ -279,27 +280,27 @@ class CheckUnused private (phaseMode: CheckUnused.PhaseMode, suffix: String, _ke
279280
private def traverseAnnotations(sym: Symbol)(using Context): Unit =
280281
sym.denot.annotations.foreach(annot => traverser.traverse(annot.tree))
281282

282-
283283
/** Do the actual reporting given the result of the anaylsis */
284284
private def reportUnused(res: UnusedData.UnusedResult)(using Context): Unit =
285-
res.warnings.toList.sortBy(_.pos.line)(using Ordering[Int]).foreach { s =>
286-
s match
287-
case UnusedSymbol(t, _, WarnTypes.Imports) =>
288-
report.warning(s"unused import", t)
289-
case UnusedSymbol(t, _, WarnTypes.LocalDefs) =>
290-
report.warning(s"unused local definition", t)
291-
case UnusedSymbol(t, _, WarnTypes.ExplicitParams) =>
292-
report.warning(s"unused explicit parameter", t)
293-
case UnusedSymbol(t, _, WarnTypes.ImplicitParams) =>
294-
report.warning(s"unused implicit parameter", t)
295-
case UnusedSymbol(t, _, WarnTypes.PrivateMembers) =>
296-
report.warning(s"unused private member", t)
297-
case UnusedSymbol(t, _, WarnTypes.PatVars) =>
298-
report.warning(s"unused pattern variable", t)
299-
case UnusedSymbol(t, _, WarnTypes.UnsetLocals) =>
300-
report.warning(s"unset local variable, consider using an immutable val instead", t)
301-
case UnusedSymbol(t, _, WarnTypes.UnsetPrivates) =>
302-
report.warning(s"unset private variable, consider using an immutable val instead", t)
285+
res.warnings.toList.sortBy(_.namePos.sourcePos.line)(using Ordering[Int])
286+
.foreach { s =>
287+
s match
288+
case UnusedSymbol(_, namePos, WarnTypes.Imports) =>
289+
report.warning(UnusedSymbolMessage.imports(namePos.sourcePos), namePos)
290+
case UnusedSymbol(treePos, namePos, WarnTypes.LocalDefs) =>
291+
report.warning(UnusedSymbolMessage.localDefs(treePos.sourcePos), namePos)
292+
case UnusedSymbol(treePos, namePos, WarnTypes.ExplicitParams) =>
293+
report.warning(UnusedSymbolMessage.explicitParams(treePos.sourcePos), namePos)
294+
case UnusedSymbol(treePos, namePos, WarnTypes.ImplicitParams) =>
295+
report.warning(UnusedSymbolMessage.implicitParams(treePos.sourcePos), namePos)
296+
case UnusedSymbol(treePos, namePos, WarnTypes.PrivateMembers) =>
297+
report.warning(UnusedSymbolMessage.privateMembers(treePos.sourcePos), namePos)
298+
case UnusedSymbol(treePos, namePos, WarnTypes.PatVars) =>
299+
report.warning(UnusedSymbolMessage.patVars(treePos.sourcePos), namePos)
300+
case UnusedSymbol(_, namePos, WarnTypes.UnsetLocals) =>
301+
report.warning("unset local variable, consider using an immutable val instead", namePos)
302+
case UnusedSymbol(_, namePos, WarnTypes.UnsetPrivates) =>
303+
report.warning("unset private variable, consider using an immutable val instead", namePos)
303304
}
304305

305306
end CheckUnused
@@ -312,7 +313,7 @@ object CheckUnused:
312313
case Aggregate
313314
case Report
314315

315-
private enum WarnTypes:
316+
enum WarnTypes:
316317
case Imports
317318
case LocalDefs
318319
case ExplicitParams
@@ -513,7 +514,7 @@ object CheckUnused:
513514
popScope()
514515
val sortedImp =
515516
if ctx.settings.WunusedHas.imports || ctx.settings.WunusedHas.strictNoImplicitWarn then
516-
unusedImport.map(d => UnusedSymbol(d.srcPos, d.name, WarnTypes.Imports)).toList
517+
unusedImport.map(d => UnusedSymbol(d.srcPos, d.srcPos, WarnTypes.Imports)).toList
517518
else
518519
Nil
519520
// Partition to extract unset local variables from usedLocalDefs
@@ -526,24 +527,24 @@ object CheckUnused:
526527
unusedLocalDefs
527528
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
528529
.filterNot(d => containsSyntheticSuffix(d.symbol))
529-
.map(d => UnusedSymbol(d.namePos, d.name, WarnTypes.LocalDefs)).toList
530-
val unsetLocalDefs = usedLocalDefs.filter(isUnsetVarDef).map(d => UnusedSymbol(d.namePos, d.name, WarnTypes.UnsetLocals)).toList
530+
.map(d => UnusedSymbol(d.sourcePos, d.namePos, WarnTypes.LocalDefs)).toList
531+
val unsetLocalDefs = usedLocalDefs.filter(isUnsetVarDef).map(d => UnusedSymbol(d.sourcePos, d.namePos, WarnTypes.UnsetLocals)).toList
531532

532533
val sortedExplicitParams =
533534
if ctx.settings.WunusedHas.explicits then
534535
explicitParamInScope
535536
.filterNot(d => d.symbol.usedDefContains)
536537
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
537538
.filterNot(d => containsSyntheticSuffix(d.symbol))
538-
.map(d => UnusedSymbol(d.namePos, d.name, WarnTypes.ExplicitParams)).toList
539+
.map(d => UnusedSymbol(d.sourcePos, d.namePos, WarnTypes.ExplicitParams)).toList
539540
else
540541
Nil
541542
val sortedImplicitParams =
542543
if ctx.settings.WunusedHas.implicits then
543544
implicitParamInScope
544545
.filterNot(d => d.symbol.usedDefContains)
545546
.filterNot(d => containsSyntheticSuffix(d.symbol))
546-
.map(d => UnusedSymbol(d.namePos, d.name, WarnTypes.ImplicitParams)).toList
547+
.map(d => UnusedSymbol(d.sourcePos, d.namePos, WarnTypes.ImplicitParams)).toList
547548
else
548549
Nil
549550
// Partition to extract unset private variables from usedPrivates
@@ -552,15 +553,15 @@ object CheckUnused:
552553
privateDefInScope.partition(d => d.symbol.usedDefContains)
553554
else
554555
(Nil, Nil)
555-
val sortedPrivateDefs = unusedPrivates.filterNot(d => containsSyntheticSuffix(d.symbol)).map(d => UnusedSymbol(d.namePos, d.name, WarnTypes.PrivateMembers)).toList
556-
val unsetPrivateDefs = usedPrivates.filter(isUnsetVarDef).map(d => UnusedSymbol(d.namePos, d.name, WarnTypes.UnsetPrivates)).toList
556+
val sortedPrivateDefs = unusedPrivates.filterNot(d => containsSyntheticSuffix(d.symbol)).map(d => UnusedSymbol(d.sourcePos, d.namePos, WarnTypes.PrivateMembers)).toList
557+
val unsetPrivateDefs = usedPrivates.filter(isUnsetVarDef).map(d => UnusedSymbol(d.sourcePos, d.namePos, WarnTypes.UnsetPrivates)).toList
557558
val sortedPatVars =
558559
if ctx.settings.WunusedHas.patvars then
559560
patVarsInScope
560561
.filterNot(d => d.symbol.usedDefContains)
561562
.filterNot(d => containsSyntheticSuffix(d.symbol))
562563
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
563-
.map(d => UnusedSymbol(d.namePos, d.name, WarnTypes.PatVars)).toList
564+
.map(d => UnusedSymbol(d.sourcePos, d.namePos, WarnTypes.PatVars)).toList
564565
else
565566
Nil
566567
val warnings =
@@ -574,7 +575,7 @@ object CheckUnused:
574575
unsetLocalDefs :::
575576
unsetPrivateDefs
576577
unsorted.sortBy { s =>
577-
val pos = s.pos.sourcePos
578+
val pos = s.namePos.sourcePos
578579
(pos.line, pos.column)
579580
}
580581
UnusedResult(warnings.toSet)
@@ -807,7 +808,8 @@ object CheckUnused:
807808
case _:tpd.Block => Local
808809
case _ => Other
809810

810-
case class UnusedSymbol(pos: SrcPos, name: Name, warnType: WarnTypes)
811+
case class UnusedSymbol(defnTree: SrcPos, namePos: SrcPos, warnType: WarnTypes)
812+
811813
/** A container for the results of the used elements analysis */
812814
case class UnusedResult(warnings: Set[UnusedSymbol])
813815
object UnusedResult:

0 commit comments

Comments
 (0)