lean4-htt/tests/pkg/linter_set/LinterSet.lean
Anne Baanen e982bf9472
feat: implement "linter sets" that can be turned on as a group (#8106)
This PR adds a `register_linter_set` command for declaring linter sets.
The `getLinterValue` function now checks if the present linter is
contained in a set that has been enabled (using the `set_option` command
or on the command line).

The implementation stores linter set membership in an environment
extension. As a consequence, we need to pass more data to
`getLinterValue`: the argument of ype `Options` has been replaced with a
`LinterOptions`, which you can access by writing `getLinterOptions`
instead of `getOptions`. (The alternative I considered is to modify the
`Options` structure. The current approach seems a bit higher-level and
lower-impact.)

The logic for checking whether a linter should be enabled now goes in
four steps:
1. If the linter has been explicitly en/disabled, return that.
2. If `linter.all` has been explicitly set, return that.
3. If the linter is in any set that has been enabled, return true.
4. Return the default setting for the linter.

Reasoning:
* The linter's explicit setting should take precedence.
* We want to be able to disable all but the explicitly enabled linters
with `linter.all`, so it should take precedence over linter sets.
* We want to progressively enable more linters as they become available,
so the check over sets should be *any*.
* Falling back to the default value last, ensures compatibility with the
current way we define linters.

The public-facing API currently does not allow modifying sets: all
linters have to be added when the set is declared. This way, there is
one place where all the contents of the set are listed.

Linter sets can be declared to contain linters that have not been
declared (yet): this allows declaring linter sets low down in the import
hierarchy when not all the requested linters are defined yet.

---------

Co-authored-by: grunweg <rothgami@math.hu-berlin.de>
2025-05-14 23:30:42 +00:00

93 lines
2.5 KiB
Text

import LinterSet.Def
open Lean Linter
def fooInitially : MetaM Unit := do
-- linter.foo1 and linter.foo2 are declared to be false by default
assert! !(getLinterValue linter.foo1 (← getLinterOptions))
assert! !(getLinterValue linter.foo2 (← getLinterOptions))
-- linter.foo_true is declared to be true by default
assert! (getLinterValue linter.foo_true (← getLinterOptions))
pure ()
#eval fooInitially
set_option linter.set.foo true
def fooSetTrue : MetaM Unit := do
-- All linters in the `foo` set should now be true
assert! (getLinterValue linter.foo1 (← getLinterOptions))
assert! (getLinterValue linter.foo2 (← getLinterOptions))
assert! (getLinterValue linter.foo_true (← getLinterOptions))
pure ()
#eval fooSetTrue
section OverrideFalse
set_option linter.foo2 false
def overrideFalse : MetaM Unit := do
-- The overridden linter should now be false.
assert! (getLinterValue linter.foo1 (← getLinterOptions))
assert! !(getLinterValue linter.foo2 (← getLinterOptions))
assert! (getLinterValue linter.foo_true (← getLinterOptions))
pure ()
#eval overrideFalse
end OverrideFalse
section AllFalse
set_option linter.all false
def allSetFalse : MetaM Unit := do
-- All linters, including those in the `foo` set, should now be false
assert! !(getLinterValue linter.foo1 (← getLinterOptions))
assert! !(getLinterValue linter.foo2 (← getLinterOptions))
assert! !(getLinterValue linter.foo_true (← getLinterOptions))
pure ()
#eval allSetFalse
end AllFalse
set_option linter.set.foo false
def fooSetFalse : MetaM Unit := do
-- All linters in the `foo` set should now be back to default.
assert! !(getLinterValue linter.foo1 (← getLinterOptions))
assert! !(getLinterValue linter.foo2 (← getLinterOptions))
assert! (getLinterValue linter.foo_true (← getLinterOptions))
pure ()
#eval fooSetFalse
section AllTrue
set_option linter.all true
/-- Running this code will check that all linters in the `foo` set are true.
This docstring is required due to `linter.all` being true(!). -/
def allSetTrue : MetaM Unit := do
-- All linters, including those in the `foo` set, should now be true
assert! (getLinterValue linter.foo1 (← getLinterOptions))
assert! (getLinterValue linter.foo2 (← getLinterOptions))
assert! (getLinterValue linter.foo_true (← getLinterOptions))
pure ()
#eval allSetTrue
end AllTrue
/-! Test setting user options from lakefile. -/
open Lean
def barFromLakefile : MetaM Unit := do
assert! (getLinterValue linter.bar (← getLinterOptions))
#eval barFromLakefile