flowchart TD
REQ["LSP completion request"] --> SVC["CompletionService.complete"]
SVC --> ROUTE{"URI router"}
ROUTE -- "empty" --> SCAF["scaffolds_for_uri"]
ROUTE -- ".sql" --> SQL["complete_sql: Jinja or SQL keywords"]
ROUTE -- ".yaml" --> YAML["complete_yaml"]
ROUTE -- "other" --> EMPTY1["return ()"]
YAML --> REPAIR["repair.parse_or_repair (single pass)"]
REPAIR -- "fail" --> EMPTY2["return ()"]
REPAIR -- "ok" --> CAN{"schema_resolver.can_resolve"}
CAN -- "false" --> EMPTY3["return ()"]
CAN -- "true" --> ROLE["detect_role (line text, col)"]
ROLE --> PATH["resolve_dotted_path (tree port plus source map)"]
PATH --> TGT["target_at (priority 1 to 7)"]
TGT --> CTX["build CompletionContext"]
CTX --> DISPATCH["dispatch.complete (role, target, ctx)"]
DISPATCH --> ARM{"match arm"}
ARM -- "Key or Empty, ObjectShape" --> OK["completers.object_keys.complete"]
ARM -- "DashItem or Empty, ArrayOfObjects" --> AOO["completers.array_items.complete_object_item"]
ARM -- "DashItem or Empty, ArrayOfScalars" --> AOS["completers.array_items.complete_scalar_item"]
ARM -- "Value, Scalar" --> SV["completers.scalar_value.complete"]
ARM -- "Value, ColumnRef" --> RC["completers.refs.complete_column"]
ARM -- "Value, DbTable" --> DT["completers.db.complete_table"]
ARM -- "Value, DbColumn" --> DC["completers.db.complete_column"]
ARM -- "Value, DomainRef" --> RD["completers.refs.complete_domain"]
ARM -- "Value, ContractRef" --> RR["completers.refs.complete_contract"]
ARM -- "Value, DatasetRef" --> RDS["completers.refs.complete_dataset"]
ARM -- "Value, SqlCheckRef" --> RS["completers.refs.complete_sql_check"]
ARM -- "catch all NotInSchema or impossible" --> EMPTY4["return ()"]
OK --> ITEMS["tuple of CompletionItemInfo"]
AOO --> ITEMS
AOS --> ITEMS
SV --> ITEMS
RC --> ITEMS
DT --> ITEMS
DC --> ITEMS
RD --> ITEMS
RR --> ITEMS
RDS --> ITEMS
RS --> ITEMSsequenceDiagram
participant H as LSP handler
participant S as CompletionService
participant R as repair.parse_or_repair
participant DR as detect_role
participant TA as target_at
participant D as dispatch.complete
participant C as completer arm
participant SR as SchemaResolver port
participant IC as IntrospectionCache port
H->>S: complete(query)
S->>S: route by URI (empty, .sql, .yaml)
S->>R: parse_or_repair(parser, query)
R-->>S: RawSource or None
S->>SR: can_resolve(data)
SR-->>S: True
S->>DR: detect_role(line_text, col)
DR-->>S: CursorRole value
S->>S: resolve_dotted_path via tree port and source map
S->>TA: target_at(data, path, resolver, index, intro, registry, checks_dir)
TA->>SR: turbine_ref_at(data, path)
SR-->>TA: extension dict or None
TA->>SR: resolve_children(data, path)
SR-->>TA: ResolvedNode
TA-->>S: CompletionTarget variant
S->>S: build CompletionContext
S->>D: complete(role, target, ctx)
D->>C: arm(target, ctx)
C->>SR: resolve_children when needed
C->>IC: known_table_names or get_table when needed
C-->>D: tuple of CompletionItemInfo
D-->>S: items
S-->>H: itemsclassDiagram
class CompletionService {
+parser: Callable
+schema_resolver: SchemaResolver
+tree_port: DocumentTreePort
+index_provider: Callable
+introspection_provider: Callable
+checks_dir: Path
+layout: ProjectLayout
+domain_registry: DomainRegistry
+complete(query) tuple~CompletionItemInfo~
}
class CompletionContext {
<<dataclass>>
+data: dict
+path: str
+source_map: SourceMap
+schema_resolver: SchemaResolver
+index: ProjectIndex
+introspection: IntrospectionCache
+domain_registry: DomainRegistry
+checks_dir: Path
}
class CursorRole {
<<StrEnum>>
KEY
VALUE
DASH_ITEM
EMPTY
}
class CompletionTarget {
<<union>>
}
class ObjectShape
class ArrayOfObjects
class ArrayOfScalars
class Scalar
class ColumnRef
class DbTable
class DbColumn
class DomainRef
class ContractRef
class DatasetRef
class SqlCheckRef
class NotInSchema
class Dispatch {
+complete(role, target, ctx) tuple~CompletionItemInfo~
}
class ObjectKeysCompleter {
+complete(target, ctx) tuple~CompletionItemInfo~
}
class ArrayItemsCompleter {
+complete_object_item(target, ctx) tuple~CompletionItemInfo~
+complete_scalar_item(target, ctx) tuple~CompletionItemInfo~
}
class ScalarValueCompleter {
+complete(target, ctx) tuple~CompletionItemInfo~
}
class RefsCompleter {
+complete_column(target, ctx) tuple~CompletionItemInfo~
+complete_contract(ctx) tuple~CompletionItemInfo~
+complete_dataset(ctx) tuple~CompletionItemInfo~
+complete_sql_check(ctx) tuple~CompletionItemInfo~
+complete_domain(ctx) tuple~CompletionItemInfo~
}
class DbCompleter {
+complete_table(ctx) tuple~CompletionItemInfo~
+complete_column(ctx) tuple~CompletionItemInfo~
}
CompletionService --> Dispatch : calls
CompletionService --> CompletionContext : builds
Dispatch --> CursorRole : matches on
Dispatch --> CompletionTarget : matches on
Dispatch --> ObjectKeysCompleter : routes
Dispatch --> ArrayItemsCompleter : routes
Dispatch --> ScalarValueCompleter : routes
Dispatch --> RefsCompleter : routes
Dispatch --> DbCompleter : routes
CompletionTarget <|-- ObjectShape
CompletionTarget <|-- ArrayOfObjects
CompletionTarget <|-- ArrayOfScalars
CompletionTarget <|-- Scalar
CompletionTarget <|-- ColumnRef
CompletionTarget <|-- DbTable
CompletionTarget <|-- DbColumn
CompletionTarget <|-- DomainRef
CompletionTarget <|-- ContractRef
CompletionTarget <|-- DatasetRef
CompletionTarget <|-- SqlCheckRef
CompletionTarget <|-- NotInSchema