Skip to content

Commit ffe90c5

Browse files
authored
Add abstract trait inspections to scala3 (#889)
* add abstract trait to scala3 * remove unused imports * reorder imports for scalafix
1 parent 16b1c9d commit ffe90c5

File tree

5 files changed

+82
-4
lines changed

5 files changed

+82
-4
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,12 @@ To suppress warnings globally for the project, use `disabledInspections` or `ove
157157

158158
### Inspections
159159

160-
There are currently 122 inspections for Scala 2, and 1 for Scala 3.
160+
There are currently 122 inspections for Scala 2, and 2 for Scala 3.
161161
An overview list is given, followed by a more detailed description of each inspection after the list (todo: finish rest of detailed descriptions)
162162

163163
| Name | Brief Description | Default Level | Scala 2 | Scala 3 |
164164
|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|---------|---------|
165-
| AbstractTrait | Check if trait is abstract | Info | Yes | No |
165+
| AbstractTrait | Check if trait is abstract | Info | Yes | Yes |
166166
| ArrayEquals | Checks for comparison of arrays using `==` which will always return false | Info | Yes | No |
167167
| ArraysInFormat | Checks for arrays passed to String.format | Error | Yes | No |
168168
| ArraysToString | Checks for explicit toString calls on arrays | Warning | Yes | No |
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.sksamuel.scapegoat
22

33
import com.sksamuel.scapegoat.inspections.option._
4+
import com.sksamuel.scapegoat.inspections.traits._
45

56
object Inspections {
67

78
final val inspections: List[Inspection] = List(
8-
new OptionGet
9+
new OptionGet,
10+
new AbstractTrait
911
)
1012

1113
}

src/main/scala-3/com/sksamuel/scapegoat/Plugin.scala

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ class ScapegoatPhase(var configuration: Configuration, override val inspections:
3232
extends PluginPhase
3333
with ScapegoatBasePlugin {
3434

35-
3635
private[scapegoat] var feedback: Option[FeedbackDotty] = None
3736

3837
override def phaseName: String = "scapegoat"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.sksamuel.scapegoat.inspections.traits
2+
3+
import com.sksamuel.scapegoat.*
4+
import dotty.tools.dotc.ast.tpd
5+
import dotty.tools.dotc.core.Contexts.Context
6+
import dotty.tools.dotc.core.Flags
7+
import dotty.tools.dotc.core.Symbols.ClassSymbol
8+
import dotty.tools.dotc.core.Types.TypeRef
9+
import dotty.tools.dotc.util.SourcePosition
10+
11+
class AbstractTrait
12+
extends Inspection(
13+
text = "Use of abstract trait",
14+
defaultLevel = Levels.Info,
15+
description = "Traits are automatically abstract.",
16+
explanation =
17+
"The abstract modifier is used in class definitions. It is redundant for traits, and mandatory for all other classes which have incomplete members."
18+
) {
19+
20+
import tpd.*
21+
22+
def inspect(feedback: Feedback[SourcePosition], tree: tpd.Tree)(using ctx: Context): Unit = {
23+
val traverser = new InspectionTraverser {
24+
def traverse(tree: Tree)(using Context): Unit = {
25+
tree match {
26+
case tDef: TypeDef =>
27+
tDef.tpe match {
28+
case TypeRef(_, kls: ClassSymbol)
29+
if kls.flags.is(Flags.Trait) && kls.flags.is(Flags.Abstract) =>
30+
feedback.warn(tree.sourcePos, self, tree.asSnippet)
31+
case _ =>
32+
}
33+
34+
case _ =>
35+
traverseChildren(tree)
36+
}
37+
}
38+
}
39+
traverser.traverse(tree)
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.sksamuel.scapegoat.inspections.traits
2+
3+
import com.sksamuel.scapegoat.InspectionTest
4+
5+
class AbstractTraitTest extends InspectionTest(classOf[AbstractTrait]) {
6+
7+
"abstract trait use" - {
8+
"should report warning" in {
9+
val code = "abstract trait Test { }"
10+
11+
val feedback = runner.compileCodeSnippet(code)
12+
feedback.warnings.assertable.size shouldBe 1
13+
}
14+
15+
"should not report warning on sealed" in {
16+
val code = "sealed trait Test { val x: Int = 1 }"
17+
18+
val feedback = runner.compileCodeSnippet(code)
19+
feedback.warnings.assertable.size shouldBe 0
20+
}
21+
22+
"should not report warning on trait without modifiers" in {
23+
val code = "trait Test1 { val x: Int = 1 }"
24+
25+
val feedback = runner.compileCodeSnippet(code)
26+
feedback.warnings.assertable.size shouldBe 0
27+
}
28+
29+
"should not report on private trait" in {
30+
val code = "private trait Test1 { val x: Int = 1 }"
31+
32+
val feedback = runner.compileCodeSnippet(code)
33+
feedback.warnings.assertable.size shouldBe 0
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)