-
Notifications
You must be signed in to change notification settings - Fork 383
/
Copy pathStyle.lean
78 lines (62 loc) · 3 KB
/
Style.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/-
Copyright (c) 2024 Michael Rothgang. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Michael Rothgang
-/
import Lean.Elab.Command
import Lean.Linter.Util
/-!
## Style linters
This file contains (currently one, eventually more) linters about stylistic aspects:
these are only about coding style, but do not affect correctness nor global coherence of mathlib.
Historically, these were ported from the `lint-style.py` Python script.
-/
open Lean Elab Command
namespace Mathlib.Linter
/-- The `setOption` linter emits a warning on a `set_option` command, term or tactic
which sets a `pp`, `profiler` or `trace` option. -/
register_option linter.setOption : Bool := {
defValue := true
descr := "enable the `setOption` linter"
}
namespace Style.SetOption
/-- Whether a syntax element is a `set_option` command, tactic or term:
Return the name of the option being set, if any. -/
def parse_set_option : Syntax → Option Name
-- This handles all four possibilities of `_val`: a string, number, `true` and `false`.
| `(command|set_option $name:ident $_val) => some name.getId
| `(set_option $name:ident $_val in $_x) => some name.getId
| `(tactic|set_option $name:ident $_val in $_x) => some name.getId
| _ => none
/-- Whether a given piece of syntax is a `set_option` command, tactic or term. -/
def is_set_option : Syntax → Bool :=
fun stx ↦ parse_set_option stx matches some _name
/-- Gets the value of the `linter.setOption` option. -/
def getLinterHash (o : Options) : Bool := Linter.getLinterValue linter.setOption o
/-- The `setOption` linter: this lints any `set_option` command, term or tactic
which sets a `pp`, `profiler` or `trace` option.
**Why is this bad?** These options are good for debugging, but should not be
used in production code.
**How to fix this?** Remove these options: usually, they are not necessary for production code.
(Some tests will intentionally use one of these options; in this case, simply allow the linter.)
-/
def setOptionLinter : Linter where run := withSetOptionIn fun stx => do
unless getLinterHash (← getOptions) do
return
if (← MonadState.get).messages.hasErrors then
return
-- TODO: once mathlib's Lean version includes leanprover/lean4#4741, make this configurable
unless #[`Mathlib, `test, `Archive, `Counterexamples].contains (← getMainModule).getRoot do
return
if let some head := stx.find? is_set_option then
if let some name := parse_set_option head then
let forbidden := [`debug, `pp, `profiler, `trace]
if forbidden.contains name.getRoot then
Linter.logLint linter.setOption head
m!"Setting options starting with '{"', '".intercalate (forbidden.map (·.toString))}' \
is only intended for development and not for final code. \
If you intend to submit this contribution to the Mathlib project, \
please remove 'set_option {name}'."
initialize addLinter setOptionLinter
end Style.SetOption
end Mathlib.Linter