Completion

textDocument/completion and completionItem/resolve from builtin metadata, module-dot triggers, and fuzzy filter.

This page

Abstract

Completion combines three static sources: builtin metadata (plaintext JSON in development, Fernet-encrypted in compiled binaries), Pine keywords, and the scope-aware symbol index built from the workspace AST. The index supplies local variables, parameters, functions, methods, UDT fields, enum types/members, and imports. Member completion (p.) is type-directed: the receiver type is inferred conservatively and only real fields/methods are offered. Resolve re-hydrates documentation for a single builtin item. Builtin, keyword, and user-item docs use the same AXIS Markdown card as hover (kind kicker, fenced signature, Pine v6 footer).

Conceptual model

Diagram

Rendering…

Interface surface

MethodCapability
textDocument/completiontrigger_characters=["."], returns CompletionList
completionItem/resolveresolve_provider=True

Handler: features/completion.py → handle_completion / handle_completion_resolve.

Trigger logic

  1. Compute text_before_cursor on the current line.
  2. Suppress completion inside comments and string literals (in_comment_or_string).
  3. get_trigger_char — if the previous character is . (or (, ,, space), treat as trigger.
  4. If the last token contains . (e.g. ta., Side., p., Point.):
    • user-enum prefix → enum members
    • UDT type prefix (Point.) → new constructor
    • receiver with an inferred UDT type (p.) → fields + methods
    • catalog namespace (ta., strategy.risk.) → build_module_completion
  5. Else merge user symbols visible in the current scope, build_keyword_items, enum names, builtin variables (close, bar_index, …), and build_completion_list(prefix=prefix).

Word boundaries for Pine identifiers: [a-zA-Z_][a-zA-Z0-9_.]* (protocol/utils.py).

Item fields

Built by providers/completion_items.py:

FieldSource
labelmetadata label (e.g. ta.sma)
kindCompletionItemKind.Function
detailsignature / detail string
documentationMarkdown from metadata
insert_textSnippet if ${...} present, else plain label
insert_text_formatSnippet or PlainText
filter_textdotted parts + brief
sort_textmodules first (\x01…), root second (\x02…)

Category headers may appear as Folder-kind items with empty insert text and labels like --- Technical Analysis (ta.*) (N) ---.

Internals

PathRole
features/completion.pyRequest context + dispatch
providers/completion_items.pyList / item / module builders
providers/builtin_metadata.pyLoad cache, fuzzy_filter, get_builtin
protocol/utils.pyWord + trigger helpers

Fuzzy filter scores

fuzzy_filter(query, items, limit=50):

MatchScore
Exact label1000
Prefix500
Substring in label100
Category50
Brief25

Results sorted by score descending, capped at limit.

Resolve

handle_completion_resolve looks up params.label in metadata; if found, rebuilds a full CompletionItem. Unknown labels return unchanged.

Invariants and edge cases

  1. User symbols are scope-aware. A local x shadows a script-level x; only the nearest declaration is offered. Unknown receiver types produce no member list rather than unrelated builtins.
  2. Empty metadata dict yields builtin completion without catalog items; user symbols and keywords still work.
  3. Module completion uses startswith(module + ".") — nested namespaces beyond one dot still work if labels are fully qualified.
  4. Snippets are generated at metadata build time from real handler signatures where available (scripts/generate_builtin_metadata.py); set pynescript.completion.snippets to false to insert plain names.
  5. Mid-edit buffers that do not parse (trailing ., unclosed call) use a minimally repaired parse for receiver/scope resolution; positions before the cursor are unchanged.

Worked example

User types ta. → module completion for all ta.* labels.

User types sma without a module → fuzzy filter may return ta.sma among others (substring score).

Resolve on ta.sma reloads full documentation markup for the detail pane.

Failure modes

SymptomCause
Zero items alwaysMetadata not loaded — check builtin metadata
Dot trigger ignoredClient did not set completion trigger characters from server capabilities
Snippets inserted rawClient disabled snippet support; extension setting pynescript.completion.snippets

See also