Skip to content

Commit 854d9e2

Browse files
author
Roman Janusz
authored
Merge pull request #433 from AVSystem/base-package-analyzer-rule
Analyzer rule to check for a required base package
2 parents 6b61445 + 6dcae27 commit 854d9e2

File tree

4 files changed

+107
-2
lines changed

4 files changed

+107
-2
lines changed

commons-analyzer/src/main/scala/com/avsystem/commons/analyzer/AnalyzerPlugin.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ final class AnalyzerPlugin(val global: Global) extends Plugin { plugin =>
5858
new DiscardedMonixTask(global),
5959
new BadSingletonComponent(global),
6060
new ConstantDeclarations(global),
61+
new BasePackage(global),
6162
)
6263

6364
private lazy val rulesByName = rules.map(r => (r.name, r)).toMap
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.avsystem.commons
2+
package analyzer
3+
4+
import scala.annotation.tailrec
5+
import scala.tools.nsc.Global
6+
7+
class BasePackage(g: Global) extends AnalyzerRule(g, "basePackage") {
8+
9+
import global._
10+
11+
def analyze(unit: CompilationUnit): Unit = if (argument != null) {
12+
val requiredBasePackage = argument
13+
14+
@tailrec def validate(tree: Tree): Unit = tree match {
15+
case PackageDef(pid, _) if pid.symbol.hasPackageFlag && pid.symbol.fullName == requiredBasePackage =>
16+
case PackageDef(_, List(stat)) => validate(stat)
17+
case t => report(t.pos, s"`$requiredBasePackage` must be one of the base packages in this file")
18+
}
19+
20+
validate(unit.body)
21+
}
22+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.avsystem.commons
2+
package analyzer
3+
4+
import org.scalatest.funsuite.AnyFunSuite
5+
6+
class BasePackageTest extends AnyFunSuite with AnalyzerTest {
7+
settings.pluginOptions.value ++= List("AVSystemAnalyzer:+basePackage:com.avsystem.commons")
8+
9+
test("base package only") {
10+
assertNoErrors(
11+
"""
12+
|package com.avsystem.commons
13+
|
14+
|object bar
15+
|""".stripMargin)
16+
}
17+
18+
test("chained base package") {
19+
assertNoErrors(
20+
"""
21+
|package com.avsystem
22+
|package commons
23+
|
24+
|object bar
25+
|""".stripMargin)
26+
}
27+
28+
test("base package with chained subpackage") {
29+
assertNoErrors(
30+
"""
31+
|package com.avsystem.commons
32+
|package core
33+
|
34+
|object bar
35+
|""".stripMargin)
36+
}
37+
38+
test("base package object") {
39+
assertNoErrors(
40+
"""
41+
|package com.avsystem
42+
|
43+
|package object commons
44+
|""".stripMargin)
45+
}
46+
47+
test("no base package") {
48+
assertErrors(1,
49+
"""
50+
|object bar
51+
|""".stripMargin)
52+
}
53+
54+
test("wrong base package") {
55+
assertErrors(1,
56+
"""
57+
|package com.avsystem.kommons
58+
|
59+
|object bar
60+
|""".stripMargin)
61+
}
62+
63+
test("unchained subpackage") {
64+
assertErrors(1,
65+
"""
66+
|package com.avsystem.commons.core
67+
|
68+
|object bar
69+
|""".stripMargin)
70+
}
71+
}

docs/Analyzer.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,29 @@ Here's a list of currently supported rules:
3030
| `discardedMonixTask` | warning | Makes sure that expressions evaluating to Monix `Task`s are not accidentally discarded by conversion to `Unit` |
3131
| `throwableObjects` | warning | Makes sure that objects are never used as `Throwable`s (unless they have stack traces disabled) |
3232
| `constantDeclarations` | off | Checks if constants are always declared as `final val`s with `UpperCamelCase` and no explicit type annotation for literal values |
33+
| `basePackage | warning | Checks if all sources are within the specified base package |
3334

3435
Rules may be enabled and disabled in `build.sbt` with Scala compiler options:
3536

3637
```scala
37-
scalacOptions += "-P:AVSystemAnalyzer:<level><ruleName>,<level><ruleName>,..."
38+
scalacOptions += "-P:AVSystemAnalyzer:<level><ruleName>[:<arg>],<level><ruleName>[:<arg>],..."
3839
```
3940

40-
`<name>` must be one of the rule names listed above or `_` to apply to all rules.
41+
`<ruleName>` must be one of the rule names listed above or `_` to apply to all rules.
4142

4243
`<level>` may be one of:
4344

4445
* `-` to disable rule
4546
* `*` for "info" level
4647
* _empty_ for "warning" level
4748
* `+` for "error" level
49+
50+
`<arg>` is an argument specific for given rule
51+
52+
For example, this options sets all rules on "error" level except for `constantDeclarations` which is disabled
53+
and `discardedMonixTask` which is lowered to "warning" level. The `basePackage` rule is also lowered to "warning" level
54+
and `com.avsystem.commons` is specified as the base package.
55+
56+
```scala
57+
scalacOptions += "-P:AVSystemAnalyzer:+_,-constantDeclarations,discardedMonixTask,basePackage:com.avsystem.commons
58+
```

0 commit comments

Comments
 (0)