Skip to content

[Semester Project] Add new front-end phase for unused entities and add support for unused imports #16157

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 54 commits into from
Jan 9, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
27bfda8
Report simple unused import
PaulCoral Sep 30, 2022
93ba6c9
Merge branch 'lampepfl:main' into feature/linter/unused
PaulCoral Sep 30, 2022
f2c1551
Add warnings for unused wildcard imports
PaulCoral Oct 4, 2022
d6fa4cb
Add tests and fixes for unused warning
PaulCoral Oct 8, 2022
9f75334
Add warning unused given imports
PaulCoral Oct 9, 2022
b131601
Merge branch 'lampepfl:main' into feature/linter/unused
PaulCoral Oct 9, 2022
e37c2f9
Add tests for inline method
PaulCoral Oct 10, 2022
2d6da62
Add an `isRunnable` for `CheckUnused`
PaulCoral Oct 11, 2022
617155d
Merge branch 'lampepfl:main' into feature/linter/unused
PaulCoral Oct 14, 2022
0801dd6
Ignore exclusion when unused import
PaulCoral Oct 14, 2022
a6e7d05
Merge branch 'lampepfl:main' into feature/linter/unused
PaulCoral Oct 23, 2022
e1188b6
Add "-Wunused:locals" warning support
PaulCoral Oct 23, 2022
5447cdb
Add "-Wunused:privates" warning option
PaulCoral Oct 24, 2022
950e7de
Fix CheckUnused phasename
PaulCoral Oct 25, 2022
9ad1daa
Merge branch 'lampepfl:main' into feature/linter/unused
PaulCoral Oct 28, 2022
5ecb0eb
fix overlapping warning
PaulCoral Oct 28, 2022
a1c2bae
Merge branch 'lampepfl:main' into feature/linter/unused
PaulCoral Oct 31, 2022
f993782
Fix warning location
PaulCoral Oct 31, 2022
b2fd8cb
Add -Wunused:params,explicits,implicits,patvars
PaulCoral Nov 6, 2022
368748a
Merge branch 'lampepfl:main' into feature/linter/unused
PaulCoral Nov 6, 2022
e69c4a3
Merge branch 'feature/linter/unused' of github.com:PaulCoral/dotty in…
PaulCoral Nov 6, 2022
8ac97b3
Fix requested changes, add new tests
PaulCoral Nov 16, 2022
892621b
Annotation usage, allow unsed Self, add tests
PaulCoral Nov 17, 2022
6d8d20d
Refactor CheckUnused, fix pkg false negative
PaulCoral Nov 17, 2022
412412c
No -Wunused:imports for language imports
PaulCoral Nov 17, 2022
f354b96
Clean CheckUnused phase code, add doc+comments
PaulCoral Nov 18, 2022
d41c6dd
Remove report unused implicit imports
PaulCoral Nov 23, 2022
95c8a40
Revert to unused implicit check, also synthetics
PaulCoral Nov 24, 2022
b2f0fa1
Add warn Annotated Types and "new" kw
PaulCoral Dec 5, 2022
82290c8
Fix unused imports in import stmt
PaulCoral Dec 5, 2022
5a755dd
Reports more import alternatives
PaulCoral Dec 5, 2022
2ed1f1f
Warn unused Imports methods overload
PaulCoral Dec 5, 2022
8a91af1
Add an helpful message for `-W` option
PaulCoral Dec 12, 2022
ca8dbaf
Merge branch 'feature/linter/unused' of github.com:PaulCoral/dotty in…
PaulCoral Dec 12, 2022
426d34a
Fix typo in help -W
PaulCoral Dec 12, 2022
5ab55f8
Fix isBlank not member of String on CI
PaulCoral Dec 12, 2022
0cb2af0
Add `-Wunused:strict-no-implicit-warn` warning option
PaulCoral Dec 13, 2022
d1f9441
Fix test i15503j
PaulCoral Dec 13, 2022
e158a9f
Add better support for unused renamed import
PaulCoral Dec 13, 2022
e2b6b61
Clean, refine scope, add comments
PaulCoral Dec 14, 2022
b0790d1
Refactor CheckUnused into a MiniPhase
PaulCoral Dec 16, 2022
7f04ce3
Add support for @annotation.unused
PaulCoral Dec 26, 2022
779ec7d
Add support for trivial body
PaulCoral Dec 26, 2022
d37d99e
Fix the import precedence in -Wunused:imports
PaulCoral Dec 27, 2022
ae24d64
Improve -Wunused:locals
PaulCoral Dec 27, 2022
527aa31
Fix -Wunused:privates trait accessor
PaulCoral Dec 27, 2022
bfa20a1
Fix -Wunused:locals,privates with recursive
PaulCoral Dec 27, 2022
c70fa68
Fixes for -Wunused:params
PaulCoral Dec 29, 2022
7de90b3
Add better support for trivial methods -Wunused
PaulCoral Jan 3, 2023
c89e27c
Merge branch 'lampepfl:main' into feature/linter/unused
PaulCoral Jan 3, 2023
422ecb8
Merge branch 'lampepfl:main' into feature/linter/unused
PaulCoral Jan 4, 2023
4a06bc6
Remove unused method in CheckUnused
PaulCoral Jan 5, 2023
1db9040
Merge branch 'feature/linter/unused' of github.com:PaulCoral/dotty in…
PaulCoral Jan 5, 2023
08f807c
Make -Wunused:patvars to unsafe
PaulCoral Jan 5, 2023
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
51 changes: 38 additions & 13 deletions compiler/src/dotty/tools/dotc/transform/CheckUnused.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ class CheckUnused extends Phase:

override def run(using Context): Unit =
val tree = ctx.compilationUnit.tpdTree
val data = UnusedData()
val fresh = ctx.fresh.setProperty(_key, data)
traverser.traverse(tree)(using fresh)
reportUnusedImport(data.getUnused)
val data = UnusedData(ctx)
if data.neededChecks.nonEmpty then
// Execute checks if there exists at lease one config
val fresh = ctx.fresh.setProperty(_key, data)
traverser.traverse(tree)(using fresh)
reportUnusedImport(data.getUnused)

/**
* This traverse is the **main** component of this phase
Expand Down Expand Up @@ -77,15 +79,30 @@ object CheckUnused:
val phaseName: String = "check unused"
val description: String = "check for unused elements"

/**
* Various supported configuration chosen by -Wunused:<config>
*/
private enum UnusedConfig:
case UnusedImports
// TODO : handle other cases like unused local def

/**
* A stateful class gathering the infos on :
* - imports
* - definitions
* - usage
*/
private class UnusedData:
private class UnusedData(initctx: Context):
import collection.mutable.{Set => MutSet, Map => MutMap, Stack, ListBuffer}

val neededChecks =
import UnusedConfig._
val hasConfig = initctx.settings.WunusedHas
val mut = MutSet[UnusedConfig]()
if hasConfig.imports(using initctx) then
mut += UnusedImports
mut.toSet

private val used = Stack(MutSet[Int]())
private val impInScope = Stack(MutMap[Int, ListBuffer[ImportSelector]]())
private val unused = ListBuffer[ImportSelector]()
Expand All @@ -108,8 +125,9 @@ object CheckUnused:
.filter(m => m.symbol.is(Given) == s.isGiven) // given imports
.map(_.symbol.id -> s)
else
val id = tree.tpe.member(s.name).symbol.id
List(id -> s)
val id = tree.tpe.member(s.name.toTermName).symbol.id
val typeId = tree.tpe.member(s.name.toTypeName).symbol.id
List(id -> s, typeId -> s)
}
entries.foreach{(id, sel) =>
map.get(id) match
Expand All @@ -125,27 +143,34 @@ object CheckUnused:
/** leave the current scope */
def popScope(): Unit =
val usedImp = MutSet[ImportSelector]()
val popedImp = impInScope.pop()
val poppedImp = impInScope.pop()
val notDefined = used.pop().filter{id =>
popedImp.remove(id) match
poppedImp.remove(id) match
case None => true
case Some(value) =>
usedImp.addAll(value)
false
}
if used.size > 0 then
used.top.addAll(notDefined)
popedImp.values.flatten.foreach{ sel =>
poppedImp.values.flatten.foreach{ sel =>
// If **any** of the entities used by the import is used,
// do not add to the `unused` Set
if !usedImp(sel) then
unused += sel
}

/** leave the scope and return unused `ImportSelector`s*/
def getUnused: List[ImportSelector] =
/**
* Leave the scope and return a `List` of unused `ImportSelector`s
*
* The given `List` is sorted by line and then column of the position
*/
def getUnused(using Context): List[ImportSelector] =
popScope()
unused.toList
unused.toList.sortBy{ sel =>
val pos = sel.srcPos.sourcePos
(pos.line, pos.column)
}

end UnusedData
end CheckUnused
Expand Down
38 changes: 38 additions & 0 deletions tests/neg-custom-args/fatal-warnings/i15503/i15503a.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,44 @@ object FooGiven:

val foo = summon[Int]

/**
* Import used as type name are considered
* as used.
*
* Import here are only used as types, not as
* Term
*/
object FooTypeName:
import collection.mutable.Set // OK
import collection.mutable.Map // OK
import collection.mutable.Seq // OK
import collection.mutable.ArrayBuilder // OK
import collection.mutable.ListBuffer // error

def checkImplicit[A](using Set[A]) = ()
def checkParamType[B](a: Map[B,B]): Seq[B] = ???
def checkTypeParam[A] = ()

checkTypeParam[ArrayBuilder[Int]]


object InlineChecks:
object InlineFoo:
import collection.mutable.Set // OK
import collection.mutable.Map // error
inline def getSet = Set(1)

object InlinedBar:
import collection.mutable.Set // error
import collection.mutable.Map // error
val a = InlineFoo.getSet

object MacroChecks:
object StringInterpol:
import collection.mutable.Set // OK
import collection.mutable.Map // OK
println(s"This is a mutableSet : ${Set[Map[Int,Int]]()}")

/**
* Some given values for the test
*/
Expand Down