Skip to content

Commit 8308a3c

Browse files
committed
feat: linter for stale deprecated attrs
1 parent ea01174 commit 8308a3c

2 files changed

Lines changed: 70 additions & 0 deletions

File tree

Mathlib/Init.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Lean.Linter.Sets -- for the definition of linter sets
22
import Mathlib.Tactic.Linter.CommandStart
3+
import Mathlib.Tactic.Linter.DeprecatedAttr
34
import Mathlib.Tactic.Linter.DeprecatedSyntaxLinter
45
import Mathlib.Tactic.Linter.DirectoryDependency
56
import Mathlib.Tactic.Linter.DocPrime
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/-
2+
Copyright (c) 2025 ChatGPT. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: ChatGPT
5+
-/
6+
7+
import Lean.Elab.Command
8+
import Std.Time
9+
import Mathlib.Tactic.DeclarationNames
10+
-- Import this linter explicitly to ensure that
11+
-- this file has a valid copyright header and module docstring.
12+
import Mathlib.Tactic.Linter.Header
13+
14+
/-!
15+
# Linter for stale `deprecated` attributes
16+
17+
This linter reports declarations tagged with `@[deprecated]` whose
18+
`since` date lies more than three months in the past. Such declarations
19+
should usually have the `deprecated` attribute removed.
20+
-/
21+
22+
open Lean Elab Command Linter
23+
24+
namespace Mathlib.Linter
25+
26+
/--
27+
The `linter.deprecated.attr` linter flags declarations with a
28+
`@[deprecated]` attribute whose `since` date is more than three months
29+
in the past.
30+
-/
31+
register_option linter.deprecated.attr : Bool := {
32+
defValue := true
33+
descr := "enable the stale deprecated attribute linter"
34+
}
35+
36+
namespace DeprecatedAttr
37+
38+
/-- Return `true` if the given ISO date string is more than three months in the past. -/
39+
def outdated (since : String) : IO Bool := do
40+
match Std.Time.PlainDate.fromLeanDateString since with
41+
| .error _ =>
42+
return false
43+
| .ok date =>
44+
let today ← Std.Time.PlainDate.now
45+
let threshold := date.addMonthsClip (3 : Std.Time.Month.Offset)
46+
return compare threshold today == .lt
47+
48+
@[inherit_doc linter.deprecated.attr]
49+
def deprecatedAttr : Linter where
50+
run := withSetOptionIn fun stx => do
51+
unless getLinterValue linter.deprecated.attr (← getLinterOptions) do
52+
return
53+
if (← get).messages.hasErrors then
54+
return
55+
for id in ← getNamesFrom (stx.getPos?.getD default) do
56+
let declName := id.getId
57+
let some info := Lean.Linter.deprecatedAttr.getParam? (← getEnv) declName | continue
58+
let some since := info.since? | continue
59+
if (← outdated since) then
60+
let disable := m!"note: this linter can be disabled with `set_option {linter.deprecated.attr.name} false`"
61+
logInfoAt id (.tagged linter.deprecated.attr.name
62+
m!"`{declName}` was deprecated on {since}, more than three months ago\n{disable}")
63+
64+
initialize addLinter deprecatedAttr
65+
66+
end DeprecatedAttr
67+
68+
end Mathlib.Linter
69+

0 commit comments

Comments
 (0)