// ─── Token types ────────────────────────────────────────────────── export enum TokenKind { LParen, // ( RParen, // ) LCurly, // { RCurly, // } Colon, // : Lt, // < Lte, // <= Gt, // > Gte, // >= String, // "..." Ident, // unquoted literal (may contain wildcards, spaces and escapes) And, // 'and' surrounded by whitespace Or, // 'or' surrounded by whitespace Not, // 'not' followed by whitespace Whitespace, EOF, } export interface Token { kind: TokenKind; value: string; start: number; end: number; } // ─── AST types ──────────────────────────────────────────────────── export type RangeOperator = 'lt' | 'lte' | 'gt' | 'gte'; export interface LiteralNode { type: 'literal'; value: string; isQuoted: boolean; isWildcard: boolean; start: number; end: number; } export interface ValueListNode { type: 'valueList'; values: KQLNode[]; start: number; end: number; } export interface IsNode { type: 'is'; /** null when matching the default field (bare value expression) */ field: LiteralNode | null; /** null when the input is incomplete (e.g. "field:") */ value: LiteralNode | ValueListNode | null; start: number; end: number; } export interface RangeNode { type: 'range'; field: LiteralNode; operator: RangeOperator; value: LiteralNode | null; start: number; end: number; } export interface NotNode { type: 'not'; child: KQLNode | null; start: number; end: number; } export interface AndNode { type: 'and'; children: KQLNode[]; start: number; end: number; } export interface OrNode { type: 'or'; children: KQLNode[]; start: number; end: number; } export interface NestedNode { type: 'nested'; field: LiteralNode; query: KQLNode | null; start: number; end: number; } export type KQLNode = OrNode | AndNode | NotNode | NestedNode | IsNode | RangeNode | ValueListNode | LiteralNode; export interface KQLQuery { root: KQLNode | null; errors: ParseError[]; } export interface ParseError { message: string; start: number; end: number; } // ─── Completion situation ───────────────────────────────────────── export type SituationKind = 'NONE' | 'IN_FIELD' | 'AFTER_FIELD' | 'IN_VALUE' | 'IN_VALUE_LIST' | 'AFTER_EXPRESSION' | 'IN_NESTED'; export interface Situation { kind: SituationKind; prefix: string; replaceRange: { start: number; end: number }; /** Field name for value completion (IN_VALUE / IN_VALUE_LIST), dotted inside nested queries */ fieldName?: string; /** Dotted nested path when inside path:{ } (IN_NESTED), e.g. "user.tags" */ nestedPath?: string; /** True when the cursor is inside an existing quoted string */ insideString?: boolean; }