Skip to content
Closed
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
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ examples export-ignore

# Substitution for the _VERSION_PRIVATE placeholder
tools/version.bzl export-subst

#################################
# Generated files - collapse in GitHub diffs and hide from git diff
#################################
**/maven_install.json linguist-generated=true -diff
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ bazel_dep(name = "rules_multitool", version = "0.11.0")
bazel_dep(name = "rules_diff", version = "1.0.0")
bazel_dep(name = "rules_shell", version = "0.5.0")
bazel_dep(name = "rules_java", version = "7.0.6")
bazel_dep(name = "rules_scala", version = "7.1.6")

# Needed in the root because we use the run_clippy action in our aspect impl
bazel_dep(name = "rules_rust", version = "0.67.0")
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Linters which are not language-specific:
| Ruby | | [RuboCop], [Standard] |
| Rust | [rustfmt] | [clippy] |
| SQL | [prettier-plugin-sql] | |
| Scala | [scalafmt] | |
| Scala | [scalafmt] | [scalafix] |
| Shell | [shfmt] | [shellcheck] |
| Starlark | [Buildifier] | |
| Swift | [SwiftFormat] (1) | |
Expand Down Expand Up @@ -86,6 +86,7 @@ Linters which are not language-specific:
[gofumpt]: https://github.com/mvdan/gofumpt
[jsonnetfmt]: https://github.com/google/go-jsonnet
[scalafmt]: https://scalameta.org/scalafmt
[scalafix]: https://scalacenter.github.io/scalafix/
[rubocop]: https://docs.rubocop.org/
[standard]: https://github.com/standardrb/standard
[ruff]: https://docs.astral.sh/ruff/
Expand Down
7 changes: 7 additions & 0 deletions examples/scala/.bazelrc
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
import %workspace%/../java/tools/java21.bazelrc

# Use syntactic mode for targets without SemanticDB
build:lint --aspects=//tools/lint:linters.bzl%scalafix

# Use semantic mode for targets with SemanticDB enabled
# Note: semantic mode can also run syntactic rules if configured in .scalafix.semantic.conf
build:lint-semantic --aspects=//tools/lint:linters.bzl%scalafix_semantic
27 changes: 27 additions & 0 deletions examples/scala/.scalafix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Scalafix configuration
# See https://scalacenter.github.io/scalafix/docs/users/configuration.html

rules = [
DisableSyntax
LeakingImplicitClassVal
NoValInForComprehension
ProcedureSyntax
]

# DisableSyntax configuration
DisableSyntax.noVars = true
DisableSyntax.noNulls = true
DisableSyntax.noReturns = true
DisableSyntax.noWhileLoops = true
DisableSyntax.noAsInstanceOf = true
DisableSyntax.noIsInstanceOf = true

# OrganizeImports configuration (requires semantic mode)
# To enable semantic rules, you need to:
# 1. Configure your scala_toolchain with enable_semanticdb = True
# 2. Use lint_scalafix_aspect with semantic = True
# 3. Uncomment the OrganizeImports rule above
#
# OrganizeImports.removeUnused = true
# OrganizeImports.groupedImports = Merge
# OrganizeImports.importsOrder = Ascii
28 changes: 28 additions & 0 deletions examples/scala/.scalafix.semantic.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
rules = [
# Syntactic rules (also work without SemanticDB)
DisableSyntax
LeakingImplicitClassVal
NoValInForComprehension
ProcedureSyntax

# Semantic rules (require SemanticDB)
OrganizeImports
]

# DisableSyntax configuration
DisableSyntax.noVars = true
DisableSyntax.noNulls = true
DisableSyntax.noReturns = true
DisableSyntax.noWhileLoops = true
DisableSyntax.noAsInstanceOf = true
DisableSyntax.noIsInstanceOf = true

# OrganizeImports configuration
# Note: removeUnused requires -Wunused:imports compiler flag
OrganizeImports.removeUnused = false
OrganizeImports.groupedImports = Merge
OrganizeImports.groups = [
"re:javax?\\.",
"scala.",
"*"
]
2 changes: 2 additions & 0 deletions examples/scala/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ package(default_visibility = ["//visibility:public"])

exports_files([
".scalafmt.conf",
".scalafix.conf",
".scalafix.semantic.conf",
"maven_install.json",
])
8 changes: 8 additions & 0 deletions examples/scala/MODULE.aspect
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Aspect Extension setup for CLI "lint" and "format" commands
# This example is in rules_lint, so we use a local dependency.
# See https://github.com/bazel-starters/scala for a real-world example.
axl_local_dep(
name = "rules_lint",
path = "../..",
auto_use_tasks = True,
)
25 changes: 23 additions & 2 deletions examples/scala/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
"Bazel dependencies for Scala formatting example"
"Bazel dependencies for Scala formatting and linting example"

bazel_dep(name = "aspect_rules_lint")
bazel_dep(name = "rules_jvm_external", version = "6.5")
bazel_dep(name = "rules_java", version = "8.5.0")
bazel_dep(name = "rules_scala", version = "7.1.6")
bazel_dep(name = "bazel_skylib", version = "1.4.2")

local_path_override(
module_name = "aspect_rules_lint",
path = "../..",
)

# Configure Scala version - must match rules_scala's expected version
scala_config = use_extension(
"@rules_scala//scala/extensions:config.bzl",
"scala_config",
)
scala_config.settings(scala_version = "2.13.17")

# Load Scala dependency toolchains
scala_deps = use_extension(
"@rules_scala//scala/extensions:deps.bzl",
"scala_deps",
)
scala_deps.scala()

maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
artifacts = [
"org.scalameta:scalafmt-cli_2.13:3.7.14",
"org.scalameta:scalafmt-cli_2.13:3.9.10",
# scalafix-cli is published for specific Scala versions
# Use 2.13.18 which has version 0.14.5 available on Maven Central
"ch.epfl.scala:scalafix-cli_2.13.18:0.14.5",
],
lock_file = "@//:maven_install.json",
repositories = [
Expand All @@ -22,3 +40,6 @@ maven.install(
],
)
use_repo(maven, "maven")

# Register custom toolchain with SemanticDB enabled for semantic linting rules
register_toolchains("//tools/scala:semanticdb_toolchain")
24 changes: 19 additions & 5 deletions examples/scala/README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
# Scala Formatting Example
# Scala Formatting and Linting Example

This example demonstrates how to set up formatting for Scala code using `rules_lint`.
This example demonstrates how to set up formatting and linting for Scala code using `rules_lint`.

## Supported Tools

### Formatters

- **Scalafmt** - Code formatter for Scala

Note: No Scala linter is currently available in rules_lint.
### Linters

- **Scalafix** - Scala linter and refactoring tool (syntactic + semantic rules)

## Setup

1. Configure MODULE.bazel with required dependencies
2. Create the MODULE.aspect file to register CLI tasks
3. Configure Maven Dependencies (add scalafmt to maven.install artifacts)
4. Configure Formatters
3. Configure Maven Dependencies (add scalafmt + scalafix to maven.install artifacts)
4. Configure Formatters and Linters

- See `tools/format/BUILD.bazel` for how to set up the formatter
- See `.scalafmt.conf` for scalafmt configuration
- See `.scalafix.conf` for scalafix syntactic rules
- See `.scalafix.semantic.conf` for scalafix semantic rules

5. Perform formatting using `aspect format`
6. Perform linting using `aspect lint --config=lint`
7. Perform semantic linting using `aspect lint --config=lint-semantic`

## Example Code

Expand All @@ -31,8 +37,16 @@ The `src/` directory contains example Scala files:
## Configuration Files

- `.scalafmt.conf` - Scalafmt configuration file
- `.scalafix.conf` - Scalafix syntactic configuration file
- `.scalafix.semantic.conf` - Scalafix semantic configuration file
- `maven_install.json` - Maven dependency lock file (auto-generated by rules_jvm_external)

### Semantic rules note

Semantic rules require SemanticDB. This example registers a Scala toolchain with
`enable_semanticdb = True` and `semanticdb_bundle_in_jar = True`, which is required
for scalafix to run in Bazel's sandbox.

### Generating maven_install.json

After setting up your MODULE.bazel, generate the lock file:
Expand Down
Loading