@@ -36,12 +36,7 @@ class CheckUnused extends Phase:
36
36
override def description : String = CheckUnused .description
37
37
38
38
override def isRunnable (using Context ): Boolean =
39
- ctx.settings.WunusedHas .imports ||
40
- ctx.settings.WunusedHas .locals ||
41
- ctx.settings.WunusedHas .explicits ||
42
- ctx.settings.WunusedHas .implicits ||
43
- ctx.settings.WunusedHas .privates ||
44
- ctx.settings.WunusedHas .patvars
39
+ ctx.settings.Wunused .value.nonEmpty
45
40
46
41
override def run (using Context ): Unit =
47
42
val tree = ctx.compilationUnit.tpdTree
@@ -61,40 +56,17 @@ class CheckUnused extends Phase:
61
56
import UnusedData .ScopeType
62
57
63
58
override def traverse (tree : tpd.Tree )(using Context ): Unit = tree match
64
- case imp@ Import (_, sels) => sels.foreach { _ =>
65
- ctx.property(_key).foreach(_.registerImport(imp))
66
- }
59
+ case imp: tpd.Import =>
60
+ ctx.property(_key).foreach(_.registerImport(imp))
67
61
case ident : Ident =>
68
- val id = ident.symbol.id
69
- ctx.property(_key).foreach(_.registerUsed(id))
62
+ ctx.property(_key).foreach(_.registerUsed(ident.symbol))
70
63
traverseChildren(tree)
71
64
case sel : Select =>
72
- val id = sel.symbol.id
73
- ctx.property(_key).foreach(_.registerUsed(id))
74
- traverseChildren(tree)
75
- case tpd.Block (_,_) =>
76
- var prev : ScopeType = ScopeType .Other
77
- ctx.property(_key).foreach { ud =>
78
- ud.pushScope()
79
- prev = ud.currScope
80
- ud.currScope = ScopeType .Local
81
- }
65
+ ctx.property(_key).foreach(_.registerUsed(sel.symbol))
82
66
traverseChildren(tree)
67
+ case _ : (tpd.Block | tpd.Template ) =>
83
68
ctx.property(_key).foreach { ud =>
84
- ud.popScope()
85
- ud.currScope = prev
86
- }
87
- case tpd.Template (_,_,_,_) =>
88
- var prev : ScopeType = ScopeType .Other
89
- ctx.property(_key).foreach { ud =>
90
- ud.pushScope()
91
- prev = ud.currScope
92
- ud.currScope = ScopeType .Template
93
- }
94
- traverseChildren(tree)
95
- ctx.property(_key).foreach { ud =>
96
- ud.popScope()
97
- ud.currScope = prev
69
+ ud.inNewScope(ScopeType .fromTree(tree))(traverseChildren(tree))
98
70
}
99
71
case t: tpd.ValDef =>
100
72
ctx.property(_key).foreach(_.registerDef(t))
@@ -111,7 +83,7 @@ class CheckUnused extends Phase:
111
83
112
84
private def reportUnused (res : UnusedData .UnusedResult )(using Context ): Unit =
113
85
import CheckUnused .WarnTypes
114
- res.foreach { s =>
86
+ res.warnings. foreach { s =>
115
87
s match
116
88
case (t, WarnTypes .Imports ) =>
117
89
report.warning(s " unused import " , t)
@@ -149,14 +121,15 @@ object CheckUnused:
149
121
*/
150
122
private class UnusedData :
151
123
import collection .mutable .{Set => MutSet , Map => MutMap , Stack => MutStack , ListBuffer }
124
+ import dotty .tools .dotc .core .Symbols .Symbol
152
125
import UnusedData .ScopeType
153
126
154
- var currScope : ScopeType = ScopeType .Other
127
+ var currScopeType : ScopeType = ScopeType .Other
155
128
156
129
/* IMPORTS */
157
- private val impInScope = MutStack (MutMap [Int , ListBuffer [ImportSelector ]]())
130
+ private val impInScope = MutStack (MutMap [Symbol , ListBuffer [ImportSelector ]]())
158
131
private val unusedImport = MutSet [ImportSelector ]()
159
- private val usedImports = MutStack (MutSet [Int ]())
132
+ private val usedImports = MutStack (MutSet [Symbol ]())
160
133
161
134
/* LOCAL DEF OR VAL / Private Def or Val / Pattern variables */
162
135
private val localDefInScope = MutStack (MutSet [tpd.ValOrDefDef ]())
@@ -171,14 +144,26 @@ object CheckUnused:
171
144
private val unusedImplicitParams = ListBuffer [tpd.ValOrDefDef ]()
172
145
private val unusedPatVars = ListBuffer [tpd.Bind ]()
173
146
174
- private val usedDef = MutSet [Int ]()
147
+ private val usedDef = MutSet [Symbol ]()
148
+
149
+ /**
150
+ * Push a new Scope of the given type, executes the given Unit and
151
+ * pop it back to the original type.
152
+ */
153
+ def inNewScope (newScope : ScopeType )(execInNewScope : => Unit )(using Context ): Unit =
154
+ val prev = currScopeType
155
+ currScopeType = newScope
156
+ pushScope()
157
+ execInNewScope
158
+ popScope()
159
+ currScopeType = prev
175
160
176
161
private def isImportExclusion (sel : ImportSelector ): Boolean = sel.renamed match
177
162
case untpd.Ident (name) => name == StdNames .nme.WILDCARD
178
163
case _ => false
179
164
180
165
/** Register the id of a found (used) symbol */
181
- def registerUsed (id : Int ): Unit =
166
+ def registerUsed (id : Symbol ): Unit =
182
167
usedImports.top += id
183
168
usedDef += id
184
169
@@ -192,12 +177,11 @@ object CheckUnused:
192
177
else if s.isWildcard then
193
178
tree.tpe.allMembers
194
179
.filter(m => m.symbol.is(Given ) == s.isGiven) // given imports
195
- .map(_.symbol.id -> s)
196
-
180
+ .map(_.symbol -> s)
197
181
else
198
- val id = tree.tpe.member(s.name.toTermName).symbol.id
199
- val typeId = tree.tpe.member(s.name.toTypeName).symbol.id
200
- List (id -> s, typeId -> s)
182
+ val termSymbol = tree.tpe.member(s.name.toTermName).symbol
183
+ val typeSymbol = tree.tpe.member(s.name.toTypeName).symbol
184
+ List (termSymbol -> s, typeSymbol -> s)
201
185
}
202
186
entries.foreach{(id, sel) =>
203
187
map.get(id) match
@@ -211,9 +195,9 @@ object CheckUnused:
211
195
implicitParamInScope.top += valOrDef
212
196
else
213
197
explicitParamInScope.top += valOrDef
214
- else if currScope == ScopeType .Local then
198
+ else if currScopeType == ScopeType .Local then
215
199
localDefInScope.top += valOrDef
216
- else if currScope == ScopeType .Template && valOrDef.symbol.is(Private ) then
200
+ else if currScopeType == ScopeType .Template && valOrDef.symbol.is(Private ) then
217
201
privateDefInScope.top += valOrDef
218
202
219
203
def registerPatVar (patvar : tpd.Bind )(using Context ): Unit =
@@ -261,23 +245,23 @@ object CheckUnused:
261
245
}
262
246
263
247
def popScopeLocalDef ()(using Context ): Unit =
264
- val unused = localDefInScope.pop().filterInPlace(d => ! usedDef(d.symbol.id ))
248
+ val unused = localDefInScope.pop().filterInPlace(d => ! usedDef(d.symbol))
265
249
unusedLocalDef ++= unused
266
250
267
251
def popScopeExplicitParam ()(using Context ): Unit =
268
- val unused = explicitParamInScope.pop().filterInPlace(d => ! usedDef(d.symbol.id ))
252
+ val unused = explicitParamInScope.pop().filterInPlace(d => ! usedDef(d.symbol))
269
253
unusedExplicitParams ++= unused
270
254
271
255
def popScopeImplicitParam ()(using Context ): Unit =
272
- val unused = implicitParamInScope.pop().filterInPlace(d => ! usedDef(d.symbol.id ))
256
+ val unused = implicitParamInScope.pop().filterInPlace(d => ! usedDef(d.symbol))
273
257
unusedImplicitParams ++= unused
274
258
275
259
def popScopePrivateDef ()(using Context ): Unit =
276
- val unused = privateDefInScope.pop().filterInPlace(d => ! usedDef(d.symbol.id ))
260
+ val unused = privateDefInScope.pop().filterInPlace(d => ! usedDef(d.symbol))
277
261
unusedPrivateDef ++= unused
278
262
279
263
def popScopePatVars ()(using Context ): Unit =
280
- val unused = patVarsInScope.pop().filterInPlace(d => ! usedDef(d.symbol.id ))
264
+ val unused = patVarsInScope.pop().filterInPlace(d => ! usedDef(d.symbol))
281
265
unusedPatVars ++= unused
282
266
283
267
/**
@@ -317,20 +301,26 @@ object CheckUnused:
317
301
unusedPatVars.map(d => d.namePos -> WarnTypes .PatVars ).toList
318
302
else
319
303
Nil
320
- List (sortedImp, sortedLocalDefs, sortedExplicitParams, sortedImplicitParams, sortedPrivateDefs, sortedPatVars).flatten.sortBy { s =>
304
+ val warnings = List (sortedImp, sortedLocalDefs, sortedExplicitParams, sortedImplicitParams, sortedPrivateDefs, sortedPatVars).flatten.sortBy { s =>
321
305
val pos = s._1.sourcePos
322
306
(pos.line, pos.column)
323
307
}
308
+ UnusedResult (warnings, Nil )
324
309
325
310
end UnusedData
326
311
327
312
object UnusedData :
328
313
enum ScopeType :
329
314
case Local
330
315
case Template
331
- case Param
332
316
case Other
333
317
334
- type UnusedResult = List [(dotty.tools.dotc.util.SrcPos , WarnTypes )]
318
+ object ScopeType :
319
+ def fromTree (tree : tpd.Tree ): ScopeType = tree match
320
+ case _:tpd.Template => Template
321
+ case _:tpd.Block => Local
322
+ case _ => Other
323
+
324
+ case class UnusedResult (warnings : List [(dotty.tools.dotc.util.SrcPos , WarnTypes )], usedImports : List [(tpd.Import , untpd.ImportSelector )])
335
325
end CheckUnused
336
326
0 commit comments