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
Rendering…
Interface surface
| Method | Capability |
|---|---|
textDocument/completion | trigger_characters=["."], returns CompletionList |
completionItem/resolve | resolve_provider=True |
Handler: features/completion.py → handle_completion / handle_completion_resolve.
Trigger logic
- Compute
text_before_cursoron the current line. - Suppress completion inside comments and string literals (
in_comment_or_string). get_trigger_char— if the previous character is.(or(,,, space), treat as trigger.- If the last token contains
.(e.g.ta.,Side.,p.,Point.):- user-enum prefix → enum members
- UDT type prefix (
Point.) →newconstructor - receiver with an inferred UDT type (
p.) → fields + methods - catalog namespace (
ta.,strategy.risk.) →build_module_completion
- Else merge user symbols visible in the current scope,
build_keyword_items, enum names, builtin variables (close,bar_index, …), andbuild_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:
| Field | Source |
|---|---|
label | metadata label (e.g. ta.sma) |
kind | CompletionItemKind.Function |
detail | signature / detail string |
documentation | Markdown from metadata |
insert_text | Snippet if ${...} present, else plain label |
insert_text_format | Snippet or PlainText |
filter_text | dotted parts + brief |
sort_text | modules 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
| Path | Role |
|---|---|
features/completion.py | Request context + dispatch |
providers/completion_items.py | List / item / module builders |
providers/builtin_metadata.py | Load cache, fuzzy_filter, get_builtin |
protocol/utils.py | Word + trigger helpers |
Fuzzy filter scores
fuzzy_filter(query, items, limit=50):
| Match | Score |
|---|---|
| Exact label | 1000 |
| Prefix | 500 |
| Substring in label | 100 |
| Category | 50 |
| Brief | 25 |
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
- User symbols are scope-aware. A local
xshadows a script-levelx; only the nearest declaration is offered. Unknown receiver types produce no member list rather than unrelated builtins. - Empty metadata dict yields builtin completion without catalog items; user symbols and keywords still work.
- Module completion uses
startswith(module + ".")— nested namespaces beyond one dot still work if labels are fully qualified. - Snippets are generated at metadata build time from real handler signatures where available (
scripts/generate_builtin_metadata.py); setpynescript.completion.snippetstofalseto insert plain names. - 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
| Symptom | Cause |
|---|---|
| Zero items always | Metadata not loaded — check builtin metadata |
| Dot trigger ignored | Client did not set completion trigger characters from server capabilities |
| Snippets inserted raw | Client disabled snippet support; extension setting pynescript.completion.snippets |
See also
- Hover — shares metadata
- Builtin metadata
- Inlay hints — uses return types from
detail