Navigation

Go-to-definition, find-references, document highlight, rename across open documents, document outline, and workspace symbol search over the ASDL AST.

This page

Abstract

Navigation features operate on user AST symbols, not the builtin catalog. A shared static index (langserver/analysis.py) builds Pine scopes, declarations, member references, exact identifier ranges, and conservative types. Definition/references/highlight/rename resolve the symbol under the cursor through that index, so shadowed locals and unrelated same-named fields are not conflated. Definition and reference locations are character-precise. Rename applies to every currently open workspace document (script-level names also match other open scripts); document symbols build a hierarchical outline; workspace symbols include open documents plus a bounded index of closed Pine files under the workspace roots.

Conceptual model

Diagram

Rendering…

Interface surface

MethodHandlerReturns
textDocument/definitiondefinitions.handle_definitionlist[Location] | None
textDocument/referencesreferences.handle_referenceslist[Location] (possibly empty)
textDocument/documentHighlighthighlight.handle_document_highlightlist[DocumentHighlight]
textDocument/prepareRenamerename.handle_prepare_renameRange | None
textDocument/renamerename.handle_renameWorkspaceEdit | None (all open documents)
textDocument/documentSymbolsymbols.handle_document_symbolslist[DocumentSymbol]
workspace/symbolserver._collect_workspace_symbolslist[SymbolInformation]

Capabilities: definition_provider, references_provider, document_highlight_provider, rename_provider (prepare_provider=True), document + workspace symbol options with work-done progress flags.

Definition (DefinitionFinder)

Matches target word against:

  • FunctionDef.name
  • TypeDef.name
  • Assign targets (Name or nested names)

Ignores mere call sites (visit_Call returns early when the callee name matches).

References (ReferencesFinder)

  • Name with Load / Store contexts
  • Function and type definitions when include_declaration is true
  • Call sites of bare Name callees

params.context.include_declaration controls whether declarations appear.

Document symbols

Hierarchical:

ASTSymbolKindChildren
FunctionDefFunctionVariables assigned inside body
TypeDefClassFields (Assign targets)
EnumDefEnumMembers
Top-level AssignVariable—

Function detail is a coarse function name() string; assignments may show callee module attribute as detail when RHS is a call.

Workspace symbols

Flat SymbolInformation for functions/methods, types, enums + members, imports, and assigned names. Open buffers are authoritative; closed files under workspace roots are searched through WorkspaceIndex (bounded). Filter is a lowercase query substring.

Internals

PathRole
features/definitions.pyGo-to-definition visitor
features/references.pyFind-all-references visitor
features/highlight.pyDocument highlight + ident occurrence collector
features/rename.pyprepareRename (cursor document) + rename across open documents
features/symbols.pyDocument outline
server.pyWorkspace symbol aggregation

Handlers accept the version-matched AST (tree=doc.valid_ast from server.py). They re-parse from source only when tree is omitted (tests / isolated calls). Pass tree=None after a failed parse so the handler does not retry.

Invariants and edge cases

  1. Parse failure → empty / null (definition None, others []).
  2. Builtin names have no definition in-file; clients should not expect ta.sma to resolve to a library file URI.
  3. Ranges are character-precise for definition, references, highlight, rename, and document symbols. The analysis layer stores each identifier's exact (line, column, end_line, end_column).
  4. Scopes are modeled — script, function/method, if/for/while/switch/once, type, and enum. := resolves outward; = declares locally. UDT fields/methods and enum members are separate from script variables.
  5. Closed documents are included in workspace symbol search through the bounded WorkspaceIndex, but not in textDocument/rename or references; those still operate on open buffers. Rename updates every currently open buffer that contains the symbol (script-level names also match other open scripts). prepareRename stays the cursor document's ident range.

Worked example

pinescript
//@version=6
indicator("nav")
length = 14
mySma(src, len) =>
    ta.sma(src, len)
v = mySma(close, length)
  • Definition on mySma at the call site → function line.
  • References on length → assign + call argument (and declaration if included).
  • Outline → length variable, mySma function (with locals), v variable.

Failure modes

SymptomCause
Jump lands column 0Expected with current Location encoding
Missing references inside function when targeting another functionvisit_FunctionDef only walks body when the def name differs from target — intentional for declaration handling; calls inside same-named functions are a known edge
Empty outlineParse error or empty source

See also