Skip to content

Diagnose scope-isolated same-file locals alongside cross-file exclusions #145

@jbearak

Description

@jbearak

Context

When a local macro reference in a file using do/run has:

  1. A callee-side definition that's excluded by do/run inheritance, and
  2. A same-file definition that exists but isn't visible at the reference site (e.g. inside a different program body)

the provider currently preserves the analyzer's generic `Undefined local macro \`foo'` diagnostic. That's accurate but unhelpful — it doesn't tell the user why their same-file definition is invisible, or that a callee-side alternative exists.

We explored emitting OUT_OF_SCOPE_SYMBOL with the existing "local macros are not inherited via do/run (use include or @lsp-include)" message in those cases, but the message is misleading: it points at the callee file and recommends include, even though the user likely intended the same-file definition they wrote. Switching to include wouldn't expose that same-file local anyway.

Commits b852e1c1e38388 on include-edge-case explored a scope-aware rewrite and were reverted because each iteration compounded the mis-messaging.

Scenarios worth distinguishing

  • Reference at top-level, same-file local defined only inside a program define body.
  • Reference inside program body number 1, same-file local defined in program body number 2 (redeclared program).
  • Reference inside one program, same-file local defined in a sibling program.
  • Reference + `local' redef where the first definition is program-scoped but a later top-level definition exists via additional_definitions.

Proposed enhancement

Introduce a dedicated diagnostic (separate wording from "not inherited via do/run") for "same-file definition exists but isn't visible in this scope". Ideas:

  • 'foo' is defined in program \my_prog' but program locals aren't visible here`
  • 'foo' is defined later in the same program body; use this name after the definition
  • When both a same-file scope-isolated local and a callee-side local exist, emit a combined message or rank them by proximity.

Requirements sketch

  1. Detect enclosing program for the reference line and for each same-file definition (primary + additional_definitions), handling first-definition-wins ProgramSymbol.additional_definitions for redeclared programs. Use a body-specific key (e.g. name#startLine) so redeclarations aren't merged.
  2. Classify: (a) no same-file def, (b) same-file def in-scope, (c) same-file def out-of-scope, (d) both same-file out-of-scope and callee-side. Emit tailored wording per class.
  3. Keep the "any same-file match preserves generic UNDEFINED_MACRO" default as a safe fallback when the scope-analysis heuristics are uncertain.

Not in scope

  • Callee-only references (OUT_OF_SCOPE_SYMBOL with existing message is correct and unchanged).
  • Globals, scalars, matrices, variables — program-body scoping only affects locals.

Related

  • Reverted commits on include-edge-case: b852e1c, 3ac1904, 12dc34c, 1e38388.
  • Anchor in source: src/providers/diagnostics.ts::is_symbol_defined_in_current_document and the forward-call rewrite path near src/providers/diagnostics.ts:332-368.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions