@@ -92,7 +92,7 @@ structure Insertion where
9292 edit : TextEdit
9393
9494structure Query extends LeanModuleQuery where
95- env : Environment
95+ ctx : Elab.ContextInfo
9696 determineInsertion : Name → Insertion
9797
9898partial def collectOpenNamespaces (currentNamespace : Name) (openDecls : List OpenDecl)
@@ -121,7 +121,7 @@ def computeIdQuery?
121121 return {
122122 identifier := id.toString
123123 openNamespaces := collectOpenNamespaces ctx.currNamespace ctx.openDecls
124- env := ctx.env
124+ ctx
125125 determineInsertion decl :=
126126 let minimizedId := minimizeGlobalIdentifierInContext ctx.currNamespace ctx.openDecls decl
127127 {
@@ -155,7 +155,7 @@ def computeDotQuery?
155155 return some {
156156 identifier := String.Pos.Raw.extract text.source pos tailPos
157157 openNamespaces := typeNames.map (.allExcept · #[])
158- env := ctx.env
158+ ctx
159159 determineInsertion decl :=
160160 {
161161 fullName := decl
@@ -186,7 +186,7 @@ def computeDotIdQuery?
186186 return some {
187187 identifier := id.toString
188188 openNamespaces := typeNames.map (.allExcept · #[])
189- env := ctx.env
189+ ctx
190190 determineInsertion decl :=
191191 {
192192 fullName := decl
@@ -237,6 +237,22 @@ def importAllUnknownIdentifiersCodeAction (params : CodeActionParams) (kind : St
237237 }
238238}
239239
240+ private def mkImportText (ctx : Elab.ContextInfo) (mod : Name) :
241+ String := Id.run do
242+ let mut text := s! "import { mod} \n "
243+ if let some parentDecl := ctx.parentDecl? then
244+ if isMarkedMeta ctx.env parentDecl then
245+ text := s! "meta { text} "
246+ if !isPrivateName parentDecl then
247+ -- As `meta` declarations go through a second, stricter visibility check in the compiler,
248+ -- we should add `public` anywhere in a public definition (technically even private defs
249+ -- could require public imports but that is not something we can check for here).
250+ text := s! "public { text} "
251+ else if ctx.env.isExporting then
252+ -- Outside `meta`, add `public` only from public scope
253+ text := s! "public { text} "
254+ text
255+
240256def handleUnknownIdentifierCodeAction
241257 (id : JsonRpc.RequestID)
242258 (params : CodeActionParams)
@@ -276,8 +292,8 @@ def handleUnknownIdentifierCodeAction
276292 | return #[]
277293 for query in queries, result in response.queryResults do
278294 for ⟨mod, decl, isExactMatch⟩ in result do
279- let isDeclInEnv := query.env.contains decl
280- if ! isDeclInEnv && mod == query.env.mainModule then
295+ let isDeclInEnv := query.ctx. env.contains decl
296+ if ! isDeclInEnv && mod == query.ctx. env.mainModule then
281297 -- Don't offer any code actions for identifiers defined further down in the same file
282298 continue
283299 let insertion := query.determineInsertion decl
@@ -290,7 +306,7 @@ def handleUnknownIdentifierCodeAction
290306 edits := #[
291307 {
292308 range := importInsertionRange
293- newText := s! "import { mod} \n "
309+ newText := mkImportText query.ctx mod
294310 },
295311 insertion.edit
296312 ]
@@ -344,15 +360,15 @@ def handleResolveImportAllUnknownIdentifiersCodeAction?
344360 let mut imports : Std.HashSet Name := ∅
345361 for q in queries, result in response.queryResults do
346362 let some ⟨mod, decl, _⟩ := result.find? fun id =>
347- id.isExactMatch && ! q.env.contains id.decl
363+ id.isExactMatch && ! q.ctx. env.contains id.decl
348364 | continue
349- if mod == q.env.mainModule then
365+ if mod == q.ctx. env.mainModule then
350366 continue
351367 let insertion := q.determineInsertion decl
352368 if ! imports.contains mod then
353369 edits := edits.push {
354370 range := importInsertionRange
355- newText := s! "import { mod} \n "
371+ newText := mkImportText q.ctx mod
356372 }
357373 edits := edits.push insertion.edit
358374 imports := imports.insert mod
0 commit comments