/** * Completion provider for DomainLang - context-aware, grammar-aligned. * * **Design:** * - Context-aware: Only suggests what's valid at cursor position * - Grammar-aligned: Completions match grammar structure exactly * - Simple: Uses parent node to determine context * - Maintainable: Clear mapping from grammar to completions * - Import-aware: Provides completions for local paths, aliases, and dependencies */ import type { LangiumDocument } from 'langium'; import { GrammarAST } from 'langium'; import { CompletionAcceptor, CompletionContext, DefaultCompletionProvider, NextFeature } from 'langium/lsp'; import { CompletionList } from 'vscode-languageserver'; import type { CancellationToken, CompletionParams } from 'vscode-languageserver-protocol'; import type { DomainLangServices } from '../domain-lang-module.js'; export declare class DomainLangCompletionProvider extends DefaultCompletionProvider { private readonly manifestManager; readonly completionOptions: { triggerCharacters: string[]; }; constructor(services: DomainLangServices); /** * Override getCompletion to handle import string completions for incomplete strings. * * **Why this override is necessary:** * When the cursor sits inside an incomplete string token (e.g. `import "partial`) * Langium's lexer cannot produce a valid STRING token, so `completionFor()` never * fires for the `uri` property. This override detects the incomplete-string case * via regex and returns completions directly. For all other positions the parent * implementation (which routes through `completionFor`) is used. */ getCompletion(document: LangiumDocument, params: CompletionParams, cancelToken?: CancellationToken): Promise; /** * Post-process completion results to replace full-FQN items with segmented items * when the cursor is at a dotted path. * * **Why this is necessary:** * Langium's `buildContexts` creates a "data type rule" context that triggers our * `completionForCrossReference` override, which correctly produces segmented items. * However, when the CST is broken (e.g., partial `Core.B` doesn't fully parse as * a QualifiedName), `findDataTypeRuleStart` returns `undefined` and only token-based * contexts fire. These contexts have features that are ID terminals (not cross-references), * so `completionForCrossReference` is never called. Langium's default pipeline then * produces full-FQN items like `Core.Baunwalls.Jannie`. * * This post-processing step catches those FQN items and segments them, * ensuring consistent behavior regardless of parse state. */ private segmentDottedCompletions; /** Transform a single FQN item into a segmented item, or keep non-matching items. */ private segmentSingleItem; /** * Scan backwards from cursor to find a dotted identifier path. * Returns the full typed text and start position, or undefined if no dots found. * * This is intentionally cursor-based (not tokenOffset-based) to be robust * across all Langium completion contexts. */ private extractDottedPathAtCursor; /** Walk backwards through `.ID` pairs from the given position. */ private walkBackThroughDotIdPairs; /** * Collect import completion items for a given partial input string. * * Shared by both the `getCompletion` override (incomplete string case) * and the `completionFor` path (normal Langium feature-based routing). */ private collectImportItems; protected completionFor(context: CompletionContext, next: NextFeature, acceptor: CompletionAcceptor): Promise; /** * Override cross-reference completion to provide dot-segmented completions. * * When the user types a dotted prefix (e.g., `Core.`), only the next * namespace segment is shown instead of the full qualified name — * matching how modern IDEs handle hierarchical completions. * * Example: Scope contains `Core.CoreDomain`, `Core.BaunWalls.Jannie`, `Core.BaunWalls.Anna` * - No dots typed → default FQN labels: `Core.CoreDomain`, `Core.BaunWalls.Jannie`, ... * - `Core.` typed → segmented: `CoreDomain`, `BaunWalls` * - `Core.BaunWalls.` typed → segmented: `Jannie`, `Anna` */ protected completionForCrossReference(context: CompletionContext, next: NextFeature, acceptor: CompletionAcceptor): void | Promise; /** * Iterate scope candidates and emit segmented completion items. * Splits FQN candidates by the typed prefix, extracting only the next segment. */ private acceptSegmentedCandidates; private safeCompletionFor; /** * Detect if we're completing inside an import statement's uri property. * * This checks: * 1. The NextFeature's type and property (when completing STRING for uri) * 2. The current AST node (when inside an ImportStatement) * 3. Text-based pattern matching (fallback for edge cases) */ private isImportUriCompletion; /** * Add import completions asynchronously. * This method ensures the manifest is loaded before providing completions. */ private addImportCompletions; /** * Add local path starters. * @remarks * Not implemented: listing local directory entries requires async fs access * which is not available in the synchronous completion context. * TODO: Implement using vscode.workspace.fs or a dedicated async completion path. */ private addLocalPathStarters; /** * Add all starter options when input is empty. */ private addAllStarterOptions; /** * Add alias completions that match the current input. */ private addAliasCompletions; /** * Add dependency completions that match the current input. */ private addDependencyCompletions; /** * Add filtered options for partial input that doesn't start with special characters. * Shows aliases and dependencies that match the user's partial input. */ private addFilteredOptions; private handleNodeCompletions; private handleContainerCompletions; private addTopLevelSnippets; /** * Add property/collection completions for BoundedContext. */ private addBoundedContextCompletions; /** * Add property completions for Domain. */ private addDomainCompletions; /** * Add completions for ContextMap. * Suggests relationship patterns and context references. */ private addContextMapCompletions; /** * Add completions for DomainMap. * Suggests domain references. */ private addDomainMapCompletions; /** * Add completions for relationships. * Provides integration patterns and relationship types. */ private addRelationshipCompletions; }