@@ -19,34 +19,46 @@ set_option doc.verso true
1919
2020public abbrev NameMapExtension := PersistentEnvExtension (Name × Array Name) (Name × Array Name) (NameMap NameSet)
2121
22- builtin_initialize identifierSuggestionsImpl : NameMapExtension × NameMapExtension ←
23- -- This is mostly equivalent to a standard `ParametricAttribute` implementation
24- let existingToIncorrect : NameMapExtension ← registerPersistentEnvExtension {
25- name := `Lean .identifierSuggestForAttr.existingToIncorrect
26- mkInitial := pure {},
27- addImportedFn := fun _ => pure {},
28- addEntryFn := fun table (trueName, altNames) =>
29- table.alter trueName fun old =>
30- altNames.foldl (β := NameSet) (init := old.getD {}) fun accum altName =>
31- accum.insert altName
32- exportEntriesFn table :=
33- table.toArray.map (fun (trueName, altNames) =>(trueName, altNames.toArray))
34- |>.qsort (lt := fun a b => Name.quickLt a.1 b.1 )
35- }
22+ /--
23+ Create the extension mapping from existing identifiers to the incorrect alternatives for which we
24+ want to provide suggestions. This is mostly equivalent to a {name}`MapDeclarationExtension` or the
25+ extensions underlying {name}`ParametricAttribute` attributes, but it differs in allowing
26+ {name}`suggest_for` attributes to be assigned in files other than the ones where they were defined.
27+ -/
28+ def mkExistingToIncorrect : IO NameMapExtension := registerPersistentEnvExtension {
29+ name := `Lean .identifierSuggestForAttr.existingToIncorrect
30+ mkInitial := pure {},
31+ addImportedFn := fun _ => pure {},
32+ addEntryFn := fun table (trueName, altNames) =>
33+ table.alter trueName fun old =>
34+ altNames.foldl (β := NameSet) (init := old.getD {}) fun accum altName =>
35+ accum.insert altName
36+ exportEntriesFn table :=
37+ table.toArray.map (fun (trueName, altNames) =>(trueName, altNames.toArray))
38+ |>.qsort (lt := fun a b => Name.quickLt a.1 b.1 )
39+ }
3640
37- -- This indexes information the opposite of the way a `ParametricAttribute` does
38- let incorrectToExisting : NameMapExtension ← registerPersistentEnvExtension {
39- name := `Lean .identifierSuggestForAttr.incorrectToExisting
40- mkInitial := pure {},
41- addImportedFn := fun _ => pure {},
42- addEntryFn := fun table (trueName, altNames) =>
43- altNames.foldl (init := table) fun accum altName =>
44- accum.alter altName fun old =>
45- old.getD {} |>.insert trueName
46- exportEntriesFn table :=
47- table.toArray.map (fun (altName, trueNames) => (altName, trueNames.toArray))
48- |>.qsort (lt := fun a b => Name.quickLt a.1 b.1 )
49- }
41+ /--
42+ Create the extension mapping incorrect identifiers to the existing identifiers we want to suggest as
43+ replacements. This association is the opposite of the usual mapping for {name}`ParametricAttribute`
44+ attributes.
45+ -/
46+ def mkIncorrectToExisting : IO NameMapExtension := registerPersistentEnvExtension {
47+ name := `Lean .identifierSuggestForAttr.incorrectToExisting
48+ mkInitial := pure {},
49+ addImportedFn := fun _ => pure {},
50+ addEntryFn := fun table (trueName, altNames) =>
51+ altNames.foldl (init := table) fun accum altName =>
52+ accum.alter altName fun old =>
53+ old.getD {} |>.insert trueName
54+ exportEntriesFn table :=
55+ table.toArray.map (fun (altName, trueNames) => (altName, trueNames.toArray))
56+ |>.qsort (lt := fun a b => Name.quickLt a.1 b.1 )
57+ }
58+
59+ builtin_initialize identifierSuggestionsImpl : NameMapExtension × NameMapExtension ←
60+ let existingToIncorrect ← mkExistingToIncorrect
61+ let incorrectToExisting ← mkIncorrectToExisting
5062
5163 registerBuiltinAttribute {
5264 name := `suggest_for ,
@@ -70,7 +82,7 @@ builtin_initialize identifierSuggestionsImpl : NameMapExtension × NameMapExtens
7082
7183/--
7284Given a name, find all the stored correct, existing identifiers that mention that name in a
73- {lit }`suggest_for` annotation.
85+ {name }`suggest_for` annotation.
7486-/
7587public def getSuggestions [Monad m] [MonadEnv m] (incorrectName : Name) : m NameSet := do
7688 let env ← getEnv
@@ -98,7 +110,9 @@ public def getStoredSuggestions [Monad m] [MonadEnv m] (trueName : Name) : m Nam
98110Throw an unknown constant error message, potentially suggesting alternatives using
99111{name}`suggest_for` attributes. (Like {name}`throwUnknownConstantAt` but with suggestions.)
100112
101- The "Unknown constant `<id>`" message will fully qualify the name, whereas the
113+ The replacement will mimic the path structure of the original as much as possible if they share a
114+ path prefix: if there is a suggestion for replacing `Foo.Bar.jazz` with `Foo.Bar.baz`, then
115+ `Bar.jazz` will be replaced by `Bar.baz` unless the resulting constant is ambiguous.
102116-/
103117public def throwUnknownConstantWithSuggestions (constName : Name) (ref? : Option Syntax := .none) : CoreM α := do
104118 let suggestions := (← getSuggestions constName).toArray
0 commit comments