Skip to content
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

Add com-lihaoyi/acyclic to linting scala #3605

Merged
merged 3 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion docs/modules/ROOT/pages/Linting_Scala_Projects.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,8 @@ It can also perform automated refactoring.
Mill supports Scalafix through the Mill-Scalafix third party module. See the module documentation
for more details:

* https://github.com/joan38/mill-scalafix
* https://github.com/joan38/mill-scalafix

== Acyclic Files Enforcement

include::example/scalalib/linting/3-acyclic.adoc[]
61 changes: 61 additions & 0 deletions example/scalalib/linting/3-acyclic/build.mill
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// https://github.com/com-lihaoyi/acyclic[Acyclic] is a Scala compiler plugin that
// detects circular dependencies between files within a module. This can be very
// useful for ensuring code quality at a high-level:
//
// * While most linters can be concern themselves at a micro-level with formatting
// and whitespace, acyclic is concerned at a macro-level with how your codebase
// is structured into different files
//
// * While most linters satisfied by tweaking whitespace, circular dependencies may
// need significant refactorings like dependency-injection or
// interface-implementation-separation to resolve.
//
// As a Scala compiler plugin, Acyclic can be enabled on any `ScalaModule` by
// adding its `compileIvyDeps,` `scalacPluginIvyDeps`, and `scalacOptions` as
// shown below:

package build
import mill._, scalalib._

object `package` extends RootModule with ScalaModule {
def scalaVersion = "2.13.11"
def compileIvyDeps = Agg(ivy"com.lihaoyi:::acyclic:0.3.15")
def scalacPluginIvyDeps = Agg(ivy"com.lihaoyi:::acyclic:0.3.15")
def scalacOptions = Seq("-P:acyclic:force")
}

/** See Also: src/Foo.scala */

/** See Also: src/Bar.scala */

// Here we have a single `ScalaModule` with two files: `Foo.scala` and `Bar.scala`.
// `Bar` and `Foo` both depend on each other, which usually indicates an issue:

/** Usage

> ./mill compile
error: Unwanted cyclic dependency
...src/Bar.scala...
val value = Foo + " world"
^
symbol: object Foo
...src/Foo.scala...
println("hello " + Bar)
^
symbol: object Bar

*/

// Usually the code should be refactored such that references between files
// is only one way. For this example, we remove the reference to `Foo` in `Bar.scala`,
// which allows the code to compile:


/** Usage

> sed -i.bak 's/Foo/Bar/g' src/Bar.scala

> ./mill compile
done compiling

*/
4 changes: 4 additions & 0 deletions example/scalalib/linting/3-acyclic/src/Bar.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package foo
object Bar{
val value = Foo + " world"
}
7 changes: 7 additions & 0 deletions example/scalalib/linting/3-acyclic/src/Foo.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package foo
object Foo{
val value = 123
def main(args: Array[String]): Unit= {
println("hello " + Bar)
}
}
Loading