@neo4j-cypher/language-support
Advanced tools
Comparing version 2.0.0-canary-a1ed8f3 to 2.0.0-canary-a6f05d1
# @neo4j-cypher/language-support | ||
## 2.0.0-next.7 | ||
### Patch Changes | ||
- 3661e9d: Fixes database completions for CREATE ALIAS commands | ||
- b76af58: Fixes bug in signature help of functions nested inside procedure calls | ||
- 21699b7: Updates the semantic analysis module to use the antlr parser instead of the javaCC one | ||
- 6afc0e3: Adds signature information on auto-completions | ||
- 39b924d: Fixes bug in labels completion | ||
## 2.0.0-next.6 | ||
@@ -4,0 +14,0 @@ |
@@ -1,3 +0,3 @@ | ||
import { CompletionItem } from 'vscode-languageserver-types'; | ||
import { DbSchema } from '../dbSchema'; | ||
import { CompletionItem } from '../types'; | ||
export declare function autocomplete(query: string, dbSchema: DbSchema, caretPosition?: number, manual?: boolean): CompletionItem[]; |
@@ -1,4 +0,5 @@ | ||
import { CompletionItem } from 'vscode-languageserver-types'; | ||
import { Token } from 'antlr4'; | ||
import { DbSchema } from '../dbSchema'; | ||
import { ParsedStatement } from '../parserWrapper'; | ||
export declare function completionCoreCompletion(parsingResult: ParsedStatement, dbSchema: DbSchema, manualTrigger?: boolean): CompletionItem[]; | ||
import { CompletionItem } from '../types'; | ||
export declare function completionCoreCompletion(parsingResult: ParsedStatement, dbSchema: DbSchema, caretToken: Token, manualTrigger?: boolean): CompletionItem[]; |
@@ -36,279 +36,283 @@ import { ATN, CharStream, DFA, Lexer } from "antlr4"; | ||
static readonly AT = 33; | ||
static readonly BAR = 34; | ||
static readonly BINDINGS = 35; | ||
static readonly BOOL = 36; | ||
static readonly BOOLEAN = 37; | ||
static readonly BOOSTED = 38; | ||
static readonly BOTH = 39; | ||
static readonly BREAK = 40; | ||
static readonly BRIEF = 41; | ||
static readonly BTREE = 42; | ||
static readonly BUILT = 43; | ||
static readonly BY = 44; | ||
static readonly CALL = 45; | ||
static readonly CASE = 46; | ||
static readonly CHANGE = 47; | ||
static readonly CIDR = 48; | ||
static readonly COLLECT = 49; | ||
static readonly COLON = 50; | ||
static readonly COLONCOLON = 51; | ||
static readonly COMMA = 52; | ||
static readonly COMMAND = 53; | ||
static readonly COMMANDS = 54; | ||
static readonly COMMIT = 55; | ||
static readonly COMPOSITE = 56; | ||
static readonly CONCURRENT = 57; | ||
static readonly CONSTRAINT = 58; | ||
static readonly CONSTRAINTS = 59; | ||
static readonly CONTAINS = 60; | ||
static readonly COPY = 61; | ||
static readonly CONTINUE = 62; | ||
static readonly COUNT = 63; | ||
static readonly CREATE = 64; | ||
static readonly CSV = 65; | ||
static readonly CURRENT = 66; | ||
static readonly DATA = 67; | ||
static readonly DATABASE = 68; | ||
static readonly DATABASES = 69; | ||
static readonly DATE = 70; | ||
static readonly DATETIME = 71; | ||
static readonly DBMS = 72; | ||
static readonly DEALLOCATE = 73; | ||
static readonly DEFAULT = 74; | ||
static readonly DEFINED = 75; | ||
static readonly DELETE = 76; | ||
static readonly DENY = 77; | ||
static readonly DESC = 78; | ||
static readonly DESCENDING = 79; | ||
static readonly DESTROY = 80; | ||
static readonly DETACH = 81; | ||
static readonly DIFFERENT = 82; | ||
static readonly DOLLAR = 83; | ||
static readonly DISTINCT = 84; | ||
static readonly DIVIDE = 85; | ||
static readonly DOT = 86; | ||
static readonly DOTDOT = 87; | ||
static readonly DOUBLEBAR = 88; | ||
static readonly DRIVER = 89; | ||
static readonly DROP = 90; | ||
static readonly DRYRUN = 91; | ||
static readonly DUMP = 92; | ||
static readonly DURATION = 93; | ||
static readonly EACH = 94; | ||
static readonly EDGE = 95; | ||
static readonly ENABLE = 96; | ||
static readonly ELEMENT = 97; | ||
static readonly ELEMENTS = 98; | ||
static readonly ELSE = 99; | ||
static readonly ENCRYPTED = 100; | ||
static readonly END = 101; | ||
static readonly ENDS = 102; | ||
static readonly EQ = 103; | ||
static readonly EXECUTABLE = 104; | ||
static readonly EXECUTE = 105; | ||
static readonly EXIST = 106; | ||
static readonly EXISTENCE = 107; | ||
static readonly EXISTS = 108; | ||
static readonly ERROR = 109; | ||
static readonly FAIL = 110; | ||
static readonly FALSE = 111; | ||
static readonly FIELDTERMINATOR = 112; | ||
static readonly FINISH = 113; | ||
static readonly FLOAT = 114; | ||
static readonly FOR = 115; | ||
static readonly FOREACH = 116; | ||
static readonly FROM = 117; | ||
static readonly FULLTEXT = 118; | ||
static readonly FUNCTION = 119; | ||
static readonly FUNCTIONS = 120; | ||
static readonly GE = 121; | ||
static readonly GRANT = 122; | ||
static readonly GRAPH = 123; | ||
static readonly GRAPHS = 124; | ||
static readonly GROUP = 125; | ||
static readonly GROUPS = 126; | ||
static readonly GT = 127; | ||
static readonly HEADERS = 128; | ||
static readonly HOME = 129; | ||
static readonly IF = 130; | ||
static readonly IMPERSONATE = 131; | ||
static readonly IMMUTABLE = 132; | ||
static readonly IN = 133; | ||
static readonly INDEX = 134; | ||
static readonly INDEXES = 135; | ||
static readonly INF = 136; | ||
static readonly INFINITY = 137; | ||
static readonly INSERT = 138; | ||
static readonly INT = 139; | ||
static readonly INTEGER = 140; | ||
static readonly IS = 141; | ||
static readonly JOIN = 142; | ||
static readonly KEY = 143; | ||
static readonly LABEL = 144; | ||
static readonly LABELS = 145; | ||
static readonly AMPERSAND = 146; | ||
static readonly EXCLAMATION_MARK = 147; | ||
static readonly LBRACKET = 148; | ||
static readonly LCURLY = 149; | ||
static readonly LE = 150; | ||
static readonly LEADING = 151; | ||
static readonly LIMITROWS = 152; | ||
static readonly LIST = 153; | ||
static readonly LOAD = 154; | ||
static readonly LOCAL = 155; | ||
static readonly LOOKUP = 156; | ||
static readonly LPAREN = 157; | ||
static readonly LT = 158; | ||
static readonly MANAGEMENT = 159; | ||
static readonly MAP = 160; | ||
static readonly MATCH = 161; | ||
static readonly MERGE = 162; | ||
static readonly MINUS = 163; | ||
static readonly PERCENT = 164; | ||
static readonly INVALID_NEQ = 165; | ||
static readonly NEQ = 166; | ||
static readonly NAME = 167; | ||
static readonly NAMES = 168; | ||
static readonly NAN = 169; | ||
static readonly NFC = 170; | ||
static readonly NFD = 171; | ||
static readonly NFKC = 172; | ||
static readonly NFKD = 173; | ||
static readonly NEW = 174; | ||
static readonly NODE = 175; | ||
static readonly NODETACH = 176; | ||
static readonly NODES = 177; | ||
static readonly NONE = 178; | ||
static readonly NORMALIZE = 179; | ||
static readonly NORMALIZED = 180; | ||
static readonly NOT = 181; | ||
static readonly NOTHING = 182; | ||
static readonly NOWAIT = 183; | ||
static readonly NULL = 184; | ||
static readonly OF = 185; | ||
static readonly ON = 186; | ||
static readonly ONLY = 187; | ||
static readonly OPTIONAL = 188; | ||
static readonly OPTIONS = 189; | ||
static readonly OPTION = 190; | ||
static readonly OR = 191; | ||
static readonly ORDER = 192; | ||
static readonly OUTPUT = 193; | ||
static readonly PASSWORD = 194; | ||
static readonly PASSWORDS = 195; | ||
static readonly PATH = 196; | ||
static readonly PATHS = 197; | ||
static readonly PERIODIC = 198; | ||
static readonly PLAINTEXT = 199; | ||
static readonly PLUS = 200; | ||
static readonly PLUSEQUAL = 201; | ||
static readonly POINT = 202; | ||
static readonly POPULATED = 203; | ||
static readonly POW = 204; | ||
static readonly PRIMARY = 205; | ||
static readonly PRIMARIES = 206; | ||
static readonly PRIVILEGE = 207; | ||
static readonly PRIVILEGES = 208; | ||
static readonly PROCEDURE = 209; | ||
static readonly PROCEDURES = 210; | ||
static readonly PROPERTIES = 211; | ||
static readonly PROPERTY = 212; | ||
static readonly QUESTION = 213; | ||
static readonly RANGE = 214; | ||
static readonly RBRACKET = 215; | ||
static readonly RCURLY = 216; | ||
static readonly READ = 217; | ||
static readonly REALLOCATE = 218; | ||
static readonly REDUCE = 219; | ||
static readonly RENAME = 220; | ||
static readonly REGEQ = 221; | ||
static readonly REL = 222; | ||
static readonly RELATIONSHIP = 223; | ||
static readonly RELATIONSHIPS = 224; | ||
static readonly REMOVE = 225; | ||
static readonly REPEATABLE = 226; | ||
static readonly REPLACE = 227; | ||
static readonly REPORT = 228; | ||
static readonly REQUIRE = 229; | ||
static readonly REQUIRED = 230; | ||
static readonly RETURN = 231; | ||
static readonly REVOKE = 232; | ||
static readonly ROLE = 233; | ||
static readonly ROLES = 234; | ||
static readonly ROW = 235; | ||
static readonly ROWS = 236; | ||
static readonly RPAREN = 237; | ||
static readonly SCAN = 238; | ||
static readonly SEC = 239; | ||
static readonly SECOND = 240; | ||
static readonly SECONDARY = 241; | ||
static readonly SECONDARIES = 242; | ||
static readonly SECONDS = 243; | ||
static readonly SEEK = 244; | ||
static readonly SEMICOLON = 245; | ||
static readonly SERVER = 246; | ||
static readonly SERVERS = 247; | ||
static readonly SET = 248; | ||
static readonly SETTING = 249; | ||
static readonly SETTINGS = 250; | ||
static readonly SHORTEST_PATH = 251; | ||
static readonly SHORTEST = 252; | ||
static readonly SHOW = 253; | ||
static readonly SIGNED = 254; | ||
static readonly SINGLE = 255; | ||
static readonly SKIPROWS = 256; | ||
static readonly START = 257; | ||
static readonly STARTS = 258; | ||
static readonly STATUS = 259; | ||
static readonly STOP = 260; | ||
static readonly STRING = 261; | ||
static readonly SUPPORTED = 262; | ||
static readonly SUSPENDED = 263; | ||
static readonly TARGET = 264; | ||
static readonly TERMINATE = 265; | ||
static readonly TEXT = 266; | ||
static readonly THEN = 267; | ||
static readonly TIME = 268; | ||
static readonly TIMES = 269; | ||
static readonly TIMESTAMP = 270; | ||
static readonly TIMEZONE = 271; | ||
static readonly TO = 272; | ||
static readonly TOPOLOGY = 273; | ||
static readonly TRAILING = 274; | ||
static readonly TRANSACTION = 275; | ||
static readonly TRANSACTIONS = 276; | ||
static readonly TRAVERSE = 277; | ||
static readonly TRIM = 278; | ||
static readonly TRUE = 279; | ||
static readonly TYPE = 280; | ||
static readonly TYPED = 281; | ||
static readonly TYPES = 282; | ||
static readonly UNION = 283; | ||
static readonly UNIQUE = 284; | ||
static readonly UNIQUENESS = 285; | ||
static readonly UNWIND = 286; | ||
static readonly URL = 287; | ||
static readonly USE = 288; | ||
static readonly USER = 289; | ||
static readonly USERS = 290; | ||
static readonly USING = 291; | ||
static readonly VALUE = 292; | ||
static readonly VARCHAR = 293; | ||
static readonly VECTOR = 294; | ||
static readonly VERBOSE = 295; | ||
static readonly VERTEX = 296; | ||
static readonly WAIT = 297; | ||
static readonly WHEN = 298; | ||
static readonly WHERE = 299; | ||
static readonly WITH = 300; | ||
static readonly WITHOUT = 301; | ||
static readonly WRITE = 302; | ||
static readonly XOR = 303; | ||
static readonly YIELD = 304; | ||
static readonly ZONED = 305; | ||
static readonly IDENTIFIER = 306; | ||
static readonly ARROW_LINE = 307; | ||
static readonly ARROW_LEFT_HEAD = 308; | ||
static readonly ARROW_RIGHT_HEAD = 309; | ||
static readonly ErrorChar = 310; | ||
static readonly AUTH = 34; | ||
static readonly BAR = 35; | ||
static readonly BINDINGS = 36; | ||
static readonly BOOL = 37; | ||
static readonly BOOLEAN = 38; | ||
static readonly BOOSTED = 39; | ||
static readonly BOTH = 40; | ||
static readonly BREAK = 41; | ||
static readonly BRIEF = 42; | ||
static readonly BTREE = 43; | ||
static readonly BUILT = 44; | ||
static readonly BY = 45; | ||
static readonly CALL = 46; | ||
static readonly CASE = 47; | ||
static readonly CHANGE = 48; | ||
static readonly CIDR = 49; | ||
static readonly COLLECT = 50; | ||
static readonly COLON = 51; | ||
static readonly COLONCOLON = 52; | ||
static readonly COMMA = 53; | ||
static readonly COMMAND = 54; | ||
static readonly COMMANDS = 55; | ||
static readonly COMMIT = 56; | ||
static readonly COMPOSITE = 57; | ||
static readonly CONCURRENT = 58; | ||
static readonly CONSTRAINT = 59; | ||
static readonly CONSTRAINTS = 60; | ||
static readonly CONTAINS = 61; | ||
static readonly COPY = 62; | ||
static readonly CONTINUE = 63; | ||
static readonly COUNT = 64; | ||
static readonly CREATE = 65; | ||
static readonly CSV = 66; | ||
static readonly CURRENT = 67; | ||
static readonly DATA = 68; | ||
static readonly DATABASE = 69; | ||
static readonly DATABASES = 70; | ||
static readonly DATE = 71; | ||
static readonly DATETIME = 72; | ||
static readonly DBMS = 73; | ||
static readonly DEALLOCATE = 74; | ||
static readonly DEFAULT = 75; | ||
static readonly DEFINED = 76; | ||
static readonly DELETE = 77; | ||
static readonly DENY = 78; | ||
static readonly DESC = 79; | ||
static readonly DESCENDING = 80; | ||
static readonly DESTROY = 81; | ||
static readonly DETACH = 82; | ||
static readonly DIFFERENT = 83; | ||
static readonly DOLLAR = 84; | ||
static readonly DISTINCT = 85; | ||
static readonly DIVIDE = 86; | ||
static readonly DOT = 87; | ||
static readonly DOTDOT = 88; | ||
static readonly DOUBLEBAR = 89; | ||
static readonly DRIVER = 90; | ||
static readonly DROP = 91; | ||
static readonly DRYRUN = 92; | ||
static readonly DUMP = 93; | ||
static readonly DURATION = 94; | ||
static readonly EACH = 95; | ||
static readonly EDGE = 96; | ||
static readonly ENABLE = 97; | ||
static readonly ELEMENT = 98; | ||
static readonly ELEMENTS = 99; | ||
static readonly ELSE = 100; | ||
static readonly ENCRYPTED = 101; | ||
static readonly END = 102; | ||
static readonly ENDS = 103; | ||
static readonly EQ = 104; | ||
static readonly EXECUTABLE = 105; | ||
static readonly EXECUTE = 106; | ||
static readonly EXIST = 107; | ||
static readonly EXISTENCE = 108; | ||
static readonly EXISTS = 109; | ||
static readonly ERROR = 110; | ||
static readonly FAIL = 111; | ||
static readonly FALSE = 112; | ||
static readonly FIELDTERMINATOR = 113; | ||
static readonly FINISH = 114; | ||
static readonly FLOAT = 115; | ||
static readonly FOR = 116; | ||
static readonly FOREACH = 117; | ||
static readonly FROM = 118; | ||
static readonly FULLTEXT = 119; | ||
static readonly FUNCTION = 120; | ||
static readonly FUNCTIONS = 121; | ||
static readonly GE = 122; | ||
static readonly GRANT = 123; | ||
static readonly GRAPH = 124; | ||
static readonly GRAPHS = 125; | ||
static readonly GROUP = 126; | ||
static readonly GROUPS = 127; | ||
static readonly GT = 128; | ||
static readonly HEADERS = 129; | ||
static readonly HOME = 130; | ||
static readonly ID = 131; | ||
static readonly IF = 132; | ||
static readonly IMPERSONATE = 133; | ||
static readonly IMMUTABLE = 134; | ||
static readonly IN = 135; | ||
static readonly INDEX = 136; | ||
static readonly INDEXES = 137; | ||
static readonly INF = 138; | ||
static readonly INFINITY = 139; | ||
static readonly INSERT = 140; | ||
static readonly INT = 141; | ||
static readonly INTEGER = 142; | ||
static readonly IS = 143; | ||
static readonly JOIN = 144; | ||
static readonly KEY = 145; | ||
static readonly LABEL = 146; | ||
static readonly LABELS = 147; | ||
static readonly AMPERSAND = 148; | ||
static readonly EXCLAMATION_MARK = 149; | ||
static readonly LBRACKET = 150; | ||
static readonly LCURLY = 151; | ||
static readonly LE = 152; | ||
static readonly LEADING = 153; | ||
static readonly LIMITROWS = 154; | ||
static readonly LIST = 155; | ||
static readonly LOAD = 156; | ||
static readonly LOCAL = 157; | ||
static readonly LOOKUP = 158; | ||
static readonly LPAREN = 159; | ||
static readonly LT = 160; | ||
static readonly MANAGEMENT = 161; | ||
static readonly MAP = 162; | ||
static readonly MATCH = 163; | ||
static readonly MERGE = 164; | ||
static readonly MINUS = 165; | ||
static readonly PERCENT = 166; | ||
static readonly INVALID_NEQ = 167; | ||
static readonly NEQ = 168; | ||
static readonly NAME = 169; | ||
static readonly NAMES = 170; | ||
static readonly NAN = 171; | ||
static readonly NFC = 172; | ||
static readonly NFD = 173; | ||
static readonly NFKC = 174; | ||
static readonly NFKD = 175; | ||
static readonly NEW = 176; | ||
static readonly NODE = 177; | ||
static readonly NODETACH = 178; | ||
static readonly NODES = 179; | ||
static readonly NONE = 180; | ||
static readonly NORMALIZE = 181; | ||
static readonly NORMALIZED = 182; | ||
static readonly NOT = 183; | ||
static readonly NOTHING = 184; | ||
static readonly NOWAIT = 185; | ||
static readonly NULL = 186; | ||
static readonly OF = 187; | ||
static readonly ON = 188; | ||
static readonly ONLY = 189; | ||
static readonly OPTIONAL = 190; | ||
static readonly OPTIONS = 191; | ||
static readonly OPTION = 192; | ||
static readonly OR = 193; | ||
static readonly ORDER = 194; | ||
static readonly OUTPUT = 195; | ||
static readonly PASSWORD = 196; | ||
static readonly PASSWORDS = 197; | ||
static readonly PATH = 198; | ||
static readonly PATHS = 199; | ||
static readonly PERIODIC = 200; | ||
static readonly PLAINTEXT = 201; | ||
static readonly PLUS = 202; | ||
static readonly PLUSEQUAL = 203; | ||
static readonly POINT = 204; | ||
static readonly POPULATED = 205; | ||
static readonly POW = 206; | ||
static readonly PRIMARY = 207; | ||
static readonly PRIMARIES = 208; | ||
static readonly PRIVILEGE = 209; | ||
static readonly PRIVILEGES = 210; | ||
static readonly PROCEDURE = 211; | ||
static readonly PROCEDURES = 212; | ||
static readonly PROPERTIES = 213; | ||
static readonly PROPERTY = 214; | ||
static readonly PROVIDER = 215; | ||
static readonly PROVIDERS = 216; | ||
static readonly QUESTION = 217; | ||
static readonly RANGE = 218; | ||
static readonly RBRACKET = 219; | ||
static readonly RCURLY = 220; | ||
static readonly READ = 221; | ||
static readonly REALLOCATE = 222; | ||
static readonly REDUCE = 223; | ||
static readonly RENAME = 224; | ||
static readonly REGEQ = 225; | ||
static readonly REL = 226; | ||
static readonly RELATIONSHIP = 227; | ||
static readonly RELATIONSHIPS = 228; | ||
static readonly REMOVE = 229; | ||
static readonly REPEATABLE = 230; | ||
static readonly REPLACE = 231; | ||
static readonly REPORT = 232; | ||
static readonly REQUIRE = 233; | ||
static readonly REQUIRED = 234; | ||
static readonly RETURN = 235; | ||
static readonly REVOKE = 236; | ||
static readonly ROLE = 237; | ||
static readonly ROLES = 238; | ||
static readonly ROW = 239; | ||
static readonly ROWS = 240; | ||
static readonly RPAREN = 241; | ||
static readonly SCAN = 242; | ||
static readonly SEC = 243; | ||
static readonly SECOND = 244; | ||
static readonly SECONDARY = 245; | ||
static readonly SECONDARIES = 246; | ||
static readonly SECONDS = 247; | ||
static readonly SEEK = 248; | ||
static readonly SEMICOLON = 249; | ||
static readonly SERVER = 250; | ||
static readonly SERVERS = 251; | ||
static readonly SET = 252; | ||
static readonly SETTING = 253; | ||
static readonly SETTINGS = 254; | ||
static readonly SHORTEST_PATH = 255; | ||
static readonly SHORTEST = 256; | ||
static readonly SHOW = 257; | ||
static readonly SIGNED = 258; | ||
static readonly SINGLE = 259; | ||
static readonly SKIPROWS = 260; | ||
static readonly START = 261; | ||
static readonly STARTS = 262; | ||
static readonly STATUS = 263; | ||
static readonly STOP = 264; | ||
static readonly STRING = 265; | ||
static readonly SUPPORTED = 266; | ||
static readonly SUSPENDED = 267; | ||
static readonly TARGET = 268; | ||
static readonly TERMINATE = 269; | ||
static readonly TEXT = 270; | ||
static readonly THEN = 271; | ||
static readonly TIME = 272; | ||
static readonly TIMES = 273; | ||
static readonly TIMESTAMP = 274; | ||
static readonly TIMEZONE = 275; | ||
static readonly TO = 276; | ||
static readonly TOPOLOGY = 277; | ||
static readonly TRAILING = 278; | ||
static readonly TRANSACTION = 279; | ||
static readonly TRANSACTIONS = 280; | ||
static readonly TRAVERSE = 281; | ||
static readonly TRIM = 282; | ||
static readonly TRUE = 283; | ||
static readonly TYPE = 284; | ||
static readonly TYPED = 285; | ||
static readonly TYPES = 286; | ||
static readonly UNION = 287; | ||
static readonly UNIQUE = 288; | ||
static readonly UNIQUENESS = 289; | ||
static readonly UNWIND = 290; | ||
static readonly URL = 291; | ||
static readonly USE = 292; | ||
static readonly USER = 293; | ||
static readonly USERS = 294; | ||
static readonly USING = 295; | ||
static readonly VALUE = 296; | ||
static readonly VARCHAR = 297; | ||
static readonly VECTOR = 298; | ||
static readonly VERBOSE = 299; | ||
static readonly VERTEX = 300; | ||
static readonly WAIT = 301; | ||
static readonly WHEN = 302; | ||
static readonly WHERE = 303; | ||
static readonly WITH = 304; | ||
static readonly WITHOUT = 305; | ||
static readonly WRITE = 306; | ||
static readonly XOR = 307; | ||
static readonly YIELD = 308; | ||
static readonly ZONED = 309; | ||
static readonly IDENTIFIER = 310; | ||
static readonly ARROW_LINE = 311; | ||
static readonly ARROW_LEFT_HEAD = 312; | ||
static readonly ARROW_RIGHT_HEAD = 313; | ||
static readonly ErrorChar = 314; | ||
static readonly EOF: number; | ||
@@ -315,0 +319,0 @@ static readonly channelNames: string[]; |
export type { ParserRuleContext } from 'antlr4'; | ||
export { autocomplete } from './autocompletion/autocompletion'; | ||
export type { DbSchema } from './dbSchema'; | ||
export { _internalFeatureFlags } from './featureFlags'; | ||
export { antlrUtils } from './helpers'; | ||
export { CypherTokenType, lexerSymbols } from './lexerSymbols'; | ||
export { parse, parserWrapper, setConsoleCommandsEnabled, } from './parserWrapper'; | ||
export { parse, parserWrapper } from './parserWrapper'; | ||
export { signatureHelp, toSignatureInformation } from './signatureHelp'; | ||
@@ -13,5 +14,6 @@ export { applySyntaxColouring, mapCypherToSemanticTokenIndex, syntaxColouringLegend, } from './syntaxColouring/syntaxColouring'; | ||
export { testData } from './tests/testData'; | ||
export type { Neo4jFunction, Neo4jProcedure } from './types'; | ||
export { textMateGrammar } from './textMateGrammar'; | ||
export type { CompletionItem, Neo4jFunction, Neo4jProcedure } from './types'; | ||
export { CypherLexer, CypherParser }; | ||
import CypherLexer from './generated-parser/CypherCmdLexer'; | ||
import CypherParser from './generated-parser/CypherCmdParser'; |
@@ -40,1 +40,2 @@ export declare enum CypherTokenType { | ||
export declare const keywordNames: Set<string>; | ||
export declare const operatorSymbols: Set<string>; |
@@ -13,2 +13,3 @@ import type { ParserRuleContext, Token } from 'antlr4'; | ||
collectedVariables: string[]; | ||
collectedFunctions: ParsedFunction[]; | ||
} | ||
@@ -43,2 +44,12 @@ export interface ParsingResult { | ||
}; | ||
export type ParsedFunction = { | ||
parsedName: string; | ||
rawText: string; | ||
line: number; | ||
column: number; | ||
offsets: { | ||
start: number; | ||
end: number; | ||
}; | ||
}; | ||
export declare function createParsingScaffolding(query: string): ParsingScaffolding; | ||
@@ -85,5 +96,3 @@ export declare function parse(query: string): StatementOrCommandContext[]; | ||
} | ||
export declare function setConsoleCommandsEnabled(enabled: boolean): void; | ||
export declare function consoleCommandEnabled(): boolean; | ||
export declare const parserWrapper: ParserWrapper; | ||
export {}; |
@@ -1,3 +0,3 @@ | ||
import { CompletionItem } from 'vscode-languageserver-types'; | ||
import { DbSchema } from '../../dbSchema'; | ||
import { CompletionItem } from '../../types'; | ||
export declare function testCompletionsExactly({ query, offset, dbSchema, expected, }: { | ||
@@ -4,0 +4,0 @@ query: string; |
@@ -0,1 +1,2 @@ | ||
import { CompletionItem as VSCodeCompletionItem } from 'vscode-languageserver-types'; | ||
export type ReturnDescription = { | ||
@@ -34,3 +35,7 @@ name: string; | ||
aggregating: boolean; | ||
isDeprecated: boolean; | ||
}; | ||
export type CompletionItem = VSCodeCompletionItem & { | ||
signature?: string; | ||
}; | ||
export {}; |
@@ -21,3 +21,3 @@ { | ||
], | ||
"version": "2.0.0-canary-a1ed8f3", | ||
"version": "2.0.0-canary-a6f05d1", | ||
"main": "./dist/cjs/index.cjs", | ||
@@ -24,0 +24,0 @@ "module": "./dist/esm/index.mjs", |
@@ -1,6 +0,5 @@ | ||
import { CompletionItem } from 'vscode-languageserver-types'; | ||
import { DbSchema } from '../dbSchema'; | ||
import { findCaret } from '../helpers'; | ||
import { parserWrapper } from '../parserWrapper'; | ||
import { CompletionItem } from '../types'; | ||
import { completionCoreCompletion } from './completionCoreCompletions'; | ||
@@ -15,4 +14,3 @@ | ||
const parsingResult = parserWrapper.parse(query); | ||
/* We try to locate the latest statement by finding the latest available `;` | ||
in the query and take from that point to the end of the query | ||
/* We try to locate the statement where the caret is and the token of the caret | ||
@@ -25,4 +23,2 @@ The reason for doing that is we need a way to "resynchronise" when the | ||
If there was no ;, we don't want to reparse, so we return undefined | ||
inside findLatestStatement | ||
*/ | ||
@@ -32,3 +28,4 @@ const caret = findCaret(parsingResult, caretPosition); | ||
const statement = caret.statement; | ||
return completionCoreCompletion(statement, dbSchema, manual); | ||
const caretToken = caret.token; | ||
return completionCoreCompletion(statement, dbSchema, caretToken, manual); | ||
} | ||
@@ -35,0 +32,0 @@ |
@@ -5,4 +5,4 @@ import { Token } from 'antlr4'; | ||
import { | ||
CompletionItem, | ||
CompletionItemKind, | ||
CompletionItemTag, | ||
InsertTextFormat, | ||
@@ -25,3 +25,4 @@ } from 'vscode-languageserver-types'; | ||
import { consoleCommandEnabled } from '../parserWrapper'; | ||
import { _internalFeatureFlags } from '../featureFlags'; | ||
import { CompletionItem, Neo4jFunction, Neo4jProcedure } from '../types'; | ||
@@ -46,7 +47,7 @@ const uniq = <T>(arr: T[]) => Array.from(new Set(arr)); | ||
dbSchema: DbSchema, | ||
) => | ||
): CompletionItem[] => | ||
namespacedCompletion( | ||
candidateRule, | ||
tokens, | ||
Object.keys(dbSchema?.functions ?? {}), | ||
dbSchema?.functions ?? {}, | ||
'function', | ||
@@ -59,16 +60,54 @@ ); | ||
dbSchema: DbSchema, | ||
) => | ||
): CompletionItem[] => | ||
namespacedCompletion( | ||
candidateRule, | ||
tokens, | ||
Object.keys(dbSchema?.procedures ?? {}), | ||
dbSchema?.procedures ?? {}, | ||
'procedure', | ||
); | ||
function isDeprecated(arg: Neo4jFunction | Neo4jProcedure | undefined) { | ||
if ('option' in arg) { | ||
return arg.option.deprecated; | ||
} else if ('isDeprecated' in arg) { | ||
return arg.isDeprecated; | ||
} else { | ||
return false; | ||
} | ||
} | ||
function getMethodCompletionItem( | ||
label: string, | ||
fullName: string, | ||
signatures: Record<string, Neo4jFunction | Neo4jProcedure>, | ||
type: 'procedure' | 'function', | ||
kind: CompletionItemKind, | ||
): CompletionItem { | ||
const maybeSignature = signatures[fullName]; | ||
const typeDetail = type === 'procedure' ? '(procedure)' : '(function)'; | ||
const deprecated = isDeprecated(maybeSignature); | ||
const maybeTags: { tags?: CompletionItemTag[] } = deprecated | ||
? { tags: [CompletionItemTag.Deprecated] } | ||
: {}; | ||
const maybeMethodSignature = maybeSignature | ||
? { signature: maybeSignature.signature } | ||
: {}; | ||
return { | ||
...maybeTags, | ||
...maybeMethodSignature, | ||
label, | ||
kind, | ||
detail: typeDetail, | ||
documentation: maybeSignature?.description ?? '', | ||
}; | ||
} | ||
const namespacedCompletion = ( | ||
candidateRule: CandidateRule, | ||
tokens: Token[], | ||
fullNames: string[], | ||
signatures: Record<string, Neo4jFunction> | Record<string, Neo4jProcedure>, | ||
type: 'procedure' | 'function', | ||
) => { | ||
): CompletionItem[] => { | ||
const fullNames = Object.keys(signatures); | ||
const namespacePrefix = calculateNamespacePrefix(candidateRule, tokens); | ||
@@ -83,3 +122,2 @@ if (namespacePrefix === null) { | ||
: CompletionItemKind.Function; | ||
const detail = type === 'procedure' ? '(procedure)' : '(function)'; | ||
@@ -93,4 +131,18 @@ if (namespacePrefix === '') { | ||
return uniq(topLevelPrefixes) | ||
.map((label) => ({ label, kind, detail: `(namespace)` })) | ||
.concat(fullNames.map((label) => ({ label, kind, detail }))); | ||
.map( | ||
(label) => ({ label, kind, detail: `(namespace)` } as CompletionItem), | ||
) | ||
.concat( | ||
fullNames.map((label) => { | ||
const result = getMethodCompletionItem( | ||
label, | ||
label, | ||
signatures, | ||
type, | ||
kind, | ||
); | ||
return result; | ||
}), | ||
); | ||
} else { | ||
@@ -100,3 +152,3 @@ // if we have a namespace prefix, complete on the namespace level: | ||
const funcOptions = new Set<string>(); | ||
const funcOptions = new Set<{ completion: string; fullName: string }>(); | ||
const namespaceOptions = new Set<string>(); | ||
@@ -114,3 +166,3 @@ | ||
if (isFunctionName) { | ||
funcOptions.add(option); | ||
funcOptions.add({ completion: option, fullName: name }); | ||
} else { | ||
@@ -124,9 +176,11 @@ namespaceOptions.add(option); | ||
// test handle namespace with same name as function | ||
const functionNameCompletions = Array.from(funcOptions).map((label) => ({ | ||
label, | ||
kind, | ||
detail, | ||
})); | ||
const functionNameCompletions: CompletionItem[] = Array.from( | ||
funcOptions, | ||
).map(({ completion: label, fullName }) => | ||
getMethodCompletionItem(label, fullName, signatures, type, kind), | ||
); | ||
const namespaceCompletions = Array.from(namespaceOptions).map((label) => ({ | ||
const namespaceCompletions: CompletionItem[] = Array.from( | ||
namespaceOptions, | ||
).map((label) => ({ | ||
label, | ||
@@ -311,2 +365,3 @@ kind, | ||
dbSchema: DbSchema, | ||
caretToken: Token, | ||
manualTrigger = false, | ||
@@ -319,6 +374,7 @@ ): CompletionItem[] { | ||
let caretIndex = caretToken.tokenIndex; | ||
// Move the caret index to the end of the query | ||
let caretIndex = tokens.length > 0 ? tokens.length - 1 : 0; | ||
const eofIndex = tokens.length > 0 ? tokens.length - 1 : 0; | ||
const eof = tokens[caretIndex]; | ||
const eof = tokens[eofIndex]; | ||
@@ -328,3 +384,3 @@ // When we have EOF with a different text in the token, it means the parser has failed to parse it. | ||
// point of completion (e.g. an unclosed string) | ||
if (eof.text !== '<EOF>') { | ||
if (eof.type === CypherLexer.EOF && eof.text !== '<EOF>') { | ||
return []; | ||
@@ -361,3 +417,3 @@ } | ||
// or collect all console commands like below with symbolicNameString | ||
...(consoleCommandEnabled() | ||
...(_internalFeatureFlags.consoleCommands | ||
? [ | ||
@@ -579,20 +635,27 @@ CypherParser.RULE_useCompletionRule, | ||
// parameters are valid values in all cases of symbolicAliasName | ||
const baseSuggestions = parameterCompletions( | ||
const parameterSuggestions = parameterCompletions( | ||
dbSchema, | ||
ExpectedParameterType.String, | ||
); | ||
const rulesCreatingNewAliasOrDb = [ | ||
CypherParser.RULE_createAlias, | ||
const rulesCreatingNewDb = [ | ||
CypherParser.RULE_createDatabase, | ||
CypherParser.RULE_createCompositeDatabase, | ||
]; | ||
// avoid suggesting existing database names when creating a new alias or database | ||
// avoid suggesting existing database names when creating a new database | ||
if ( | ||
rulesCreatingNewAliasOrDb.some((rule) => | ||
candidateRule.ruleList.includes(rule), | ||
) | ||
rulesCreatingNewDb.some((rule) => candidateRule.ruleList.includes(rule)) | ||
) { | ||
return baseSuggestions; | ||
return parameterSuggestions; | ||
} | ||
// For `CREATE ALIAS aliasName FOR DATABASE databaseName` | ||
// Should not suggest existing aliases for aliasName but should suggest existing databases for databaseName | ||
// so we return base suggestions if we're at the `aliasName` rule | ||
if ( | ||
candidateRule.ruleList.includes(CypherParser.RULE_createAlias) && | ||
candidateRule.ruleList.includes(CypherParser.RULE_aliasName) | ||
) { | ||
return parameterSuggestions; | ||
} | ||
const rulesThatOnlyAcceptAlias = [ | ||
@@ -609,3 +672,3 @@ CypherParser.RULE_dropAlias, | ||
return [ | ||
...baseSuggestions, | ||
...parameterSuggestions, | ||
...(dbSchema?.aliasNames ?? []).map((aliasName) => ({ | ||
@@ -620,3 +683,3 @@ label: aliasName, | ||
return [ | ||
...baseSuggestions, | ||
...parameterSuggestions, | ||
...(dbSchema.databaseNames ?? []) | ||
@@ -637,3 +700,3 @@ .concat(dbSchema.aliasNames ?? []) | ||
// parameters are valid values in all cases of symbolic name | ||
const baseSuggestions = parameterCompletions( | ||
const parameterSuggestions = parameterCompletions( | ||
dbSchema, | ||
@@ -663,3 +726,3 @@ inferExpectedParameterTypeFromContext(candidateRule), | ||
) { | ||
return baseSuggestions; | ||
return parameterSuggestions; | ||
} | ||
@@ -676,3 +739,3 @@ | ||
const result = [ | ||
...baseSuggestions, | ||
...parameterSuggestions, | ||
...(dbSchema?.userNames ?? []).map((userName) => ({ | ||
@@ -695,3 +758,3 @@ label: userName, | ||
return [ | ||
...baseSuggestions, | ||
...parameterSuggestions, | ||
...(dbSchema?.roleNames ?? []).map((roleName) => ({ | ||
@@ -698,0 +761,0 @@ label: roleName, |
export type { ParserRuleContext } from 'antlr4'; | ||
export { autocomplete } from './autocompletion/autocompletion'; | ||
export type { DbSchema } from './dbSchema'; | ||
export { _internalFeatureFlags } from './featureFlags'; | ||
export { antlrUtils } from './helpers'; | ||
export { CypherTokenType, lexerSymbols } from './lexerSymbols'; | ||
export { | ||
parse, | ||
parserWrapper, | ||
setConsoleCommandsEnabled, | ||
} from './parserWrapper'; | ||
export { parse, parserWrapper } from './parserWrapper'; | ||
export { signatureHelp, toSignatureInformation } from './signatureHelp'; | ||
@@ -25,6 +22,6 @@ export { | ||
export { testData } from './tests/testData'; | ||
export type { Neo4jFunction, Neo4jProcedure } from './types'; | ||
export { textMateGrammar } from './textMateGrammar'; | ||
export type { CompletionItem, Neo4jFunction, Neo4jProcedure } from './types'; | ||
export { CypherLexer, CypherParser }; | ||
import CypherLexer from './generated-parser/CypherCmdLexer'; | ||
import CypherParser from './generated-parser/CypherCmdParser'; |
@@ -118,2 +118,3 @@ import CypherLexer from './generated-parser/CypherCmdLexer'; | ||
CypherLexer.AT, | ||
CypherLexer.AUTH, | ||
CypherLexer.BINDINGS, | ||
@@ -203,2 +204,3 @@ CypherLexer.BOOL, | ||
CypherLexer.HOME, | ||
CypherLexer.ID, | ||
CypherLexer.IF, | ||
@@ -273,2 +275,4 @@ CypherLexer.IMMUTABLE, | ||
CypherLexer.PROPERTY, | ||
CypherLexer.PROVIDER, | ||
CypherLexer.PROVIDERS, | ||
CypherLexer.RANGE, | ||
@@ -412,1 +416,4 @@ CypherLexer.READ, | ||
export const keywordNames = new Set(lexerKeywords.map((i) => tokenNames[i])); | ||
export const operatorSymbols = new Set( | ||
lexerOperators.map((i) => literalNames[i].replaceAll("'", '')), | ||
); |
@@ -7,5 +7,7 @@ import type { ParserRuleContext, Token } from 'antlr4'; | ||
import { DiagnosticSeverity, Position } from 'vscode-languageserver-types'; | ||
import { _internalFeatureFlags } from './featureFlags'; | ||
import { | ||
ClauseContext, | ||
default as CypherParser, | ||
FunctionNameContext, | ||
LabelNameContext, | ||
@@ -16,2 +18,3 @@ LabelNameIsContext, | ||
StatementsOrCommandsContext, | ||
SymbolicNameStringContext, | ||
VariableContext, | ||
@@ -44,2 +47,3 @@ } from './generated-parser/CypherCmdParser'; | ||
collectedVariables: string[]; | ||
collectedFunctions: ParsedFunction[]; | ||
} | ||
@@ -97,2 +101,13 @@ | ||
export type ParsedFunction = { | ||
parsedName: string; | ||
rawText: string; | ||
line: number; | ||
column: number; | ||
offsets: { | ||
start: number; | ||
end: number; | ||
}; | ||
}; | ||
export function createParsingScaffolding(query: string): ParsingScaffolding { | ||
@@ -140,4 +155,9 @@ const inputStream = CharStreams.fromString(query); | ||
const variableFinder = new VariableCollector(); | ||
const functionFinder = new FunctionCollector(tokens); | ||
const errorListener = new SyntaxErrorsListener(tokens); | ||
parser._parseListeners = [labelsCollector, variableFinder]; | ||
parser._parseListeners = [ | ||
labelsCollector, | ||
variableFinder, | ||
functionFinder, | ||
]; | ||
parser.addErrorListener(errorListener); | ||
@@ -153,3 +173,3 @@ const ctx = parser.statementsOrCommands(); | ||
if (!consoleCommandEnabled()) { | ||
if (!_internalFeatureFlags.consoleCommands) { | ||
diagnostics.push(...errorOnNonCypherCommands(collectedCommand)); | ||
@@ -167,2 +187,3 @@ } | ||
collectedVariables: variableFinder.variables, | ||
collectedFunctions: functionFinder.functions, | ||
}; | ||
@@ -179,3 +200,3 @@ }); | ||
// This listener is collects all labels and relationship types | ||
// This listener collects all labels and relationship types | ||
class LabelAndRelTypesCollector extends ParseTreeListener { | ||
@@ -277,2 +298,75 @@ labelOrRelTypes: LabelOrRelType[] = []; | ||
// This listener collects all functions | ||
class FunctionCollector extends ParseTreeListener { | ||
public functions: ParsedFunction[] = []; | ||
private tokens: Token[]; | ||
constructor(tokens: Token[]) { | ||
super(); | ||
this.tokens = tokens; | ||
} | ||
enterEveryRule() { | ||
/* no-op */ | ||
} | ||
visitTerminal() { | ||
/* no-op */ | ||
} | ||
visitErrorNode() { | ||
/* no-op */ | ||
} | ||
exitEveryRule(ctx: unknown) { | ||
if (ctx instanceof FunctionNameContext) { | ||
const functionName = this.getNormalizedFunctionName(ctx); | ||
const startTokenIndex = ctx.start.tokenIndex; | ||
const stopTokenIndex = ctx.stop.tokenIndex; | ||
const rawText = this.tokens | ||
.slice(startTokenIndex, stopTokenIndex + 1) | ||
.map((token) => { | ||
return token.text; | ||
}) | ||
.join(''); | ||
this.functions.push({ | ||
parsedName: functionName, | ||
rawText: rawText, | ||
line: ctx.start.line, | ||
column: ctx.start.column, | ||
offsets: { | ||
start: ctx.start.start, | ||
end: ctx.stop.stop + 1, | ||
}, | ||
}); | ||
} | ||
} | ||
private getNormalizedFunctionName(ctx: FunctionNameContext): string { | ||
const namespaces = ctx.namespace().symbolicNameString_list(); | ||
const functionName = ctx.symbolicNameString(); | ||
const normalizedName = [...namespaces, functionName] | ||
.map((symbolicName) => { | ||
return this.getFunctionNamespaceString(symbolicName); | ||
}) | ||
.join('.'); | ||
return normalizedName; | ||
} | ||
private getFunctionNamespaceString(ctx: SymbolicNameStringContext): string { | ||
const text = ctx.getText(); | ||
const isEscaped = Boolean(ctx.escapedSymbolicNameString()); | ||
const hasDot = text.includes('.'); | ||
if (isEscaped && !hasDot) { | ||
return text.slice(1, -1); | ||
} | ||
return text; | ||
} | ||
} | ||
type CypherCmd = { type: 'cypher'; query: string }; | ||
@@ -454,18 +548,2 @@ type RuleTokens = { | ||
/* | ||
Because the parserWrapper is done as a single-ton global variable, the setting for | ||
console commands was also easiest to do as a global variable as it avoid messing with the cache | ||
It would make sense for the client to initialize and own the ParserWrapper, then each editor can have | ||
it's own cache and preference on if console commands are enabled or not. | ||
*/ | ||
let enableConsoleCommands = false; | ||
export function setConsoleCommandsEnabled(enabled: boolean) { | ||
enableConsoleCommands = enabled; | ||
} | ||
export function consoleCommandEnabled() { | ||
return enableConsoleCommands; | ||
} | ||
export const parserWrapper = new ParserWrapper(); |
@@ -73,3 +73,3 @@ import { | ||
exitExpression = (ctx: ExpressionContext) => { | ||
enterExpression = (ctx: ExpressionContext) => { | ||
// If the caret is at ( | ||
@@ -110,3 +110,3 @@ if (this.caretToken.type === CypherParser.LPAREN) { | ||
exitFunctionInvocation = (ctx: FunctionInvocationContext) => { | ||
enterFunctionInvocation = (ctx: FunctionInvocationContext) => { | ||
if ( | ||
@@ -132,3 +132,3 @@ ctx.start.start <= this.caretToken.start && | ||
exitCallClause = (ctx: CallClauseContext) => { | ||
enterCallClause = (ctx: CallClauseContext) => { | ||
if ( | ||
@@ -135,0 +135,0 @@ ctx.start.start <= this.caretToken.start && |
@@ -5,2 +5,3 @@ import { Token } from 'antlr4'; | ||
import { distance } from 'fastest-levenshtein'; | ||
import { _internalFeatureFlags } from '../featureFlags'; | ||
import CypherLexer from '../generated-parser/CypherCmdLexer'; | ||
@@ -14,3 +15,2 @@ import CypherParser from '../generated-parser/CypherCmdParser'; | ||
} from '../lexerSymbols'; | ||
import { consoleCommandEnabled } from '../parserWrapper'; | ||
@@ -51,3 +51,3 @@ /* | ||
// or collect all console commands like below with symbolicNameString | ||
...(consoleCommandEnabled() | ||
...(_internalFeatureFlags.consoleCommands | ||
? { | ||
@@ -54,0 +54,0 @@ [CypherParser.RULE_useCompletionRule]: 'use', |
@@ -8,5 +8,7 @@ import { DiagnosticSeverity, Position } from 'vscode-languageserver-types'; | ||
LabelType, | ||
ParsedFunction, | ||
ParsedStatement, | ||
parserWrapper, | ||
} from '../parserWrapper'; | ||
import { Neo4jFunction } from '../types'; | ||
import { | ||
@@ -61,2 +63,52 @@ SemanticAnalysisElement, | ||
function detectNonDeclaredFunction( | ||
parsedFunction: ParsedFunction, | ||
functionsSchema: Record<string, Neo4jFunction>, | ||
): SyntaxDiagnostic | undefined { | ||
const lowercaseFunctionName = parsedFunction.parsedName.toLowerCase(); | ||
const caseInsensitiveFunctionInDatabase = | ||
functionsSchema[lowercaseFunctionName]; | ||
// Built-in functions are case-insensitive in the database | ||
if ( | ||
caseInsensitiveFunctionInDatabase && | ||
caseInsensitiveFunctionInDatabase.isBuiltIn | ||
) { | ||
return undefined; | ||
} | ||
const functionExistsWithExactName = Boolean( | ||
functionsSchema[parsedFunction.parsedName], | ||
); | ||
if (!functionExistsWithExactName) { | ||
return generateFunctionNotFoundWarning(parsedFunction); | ||
} | ||
} | ||
function generateFunctionNotFoundWarning( | ||
parsedFunction: ParsedFunction, | ||
): SyntaxDiagnostic { | ||
const rawText = parsedFunction.rawText; | ||
const nameChunks = rawText.split('\n'); | ||
const linesOffset = nameChunks.length - 1; | ||
const lineIndex = parsedFunction.line - 1; | ||
const startColumn = parsedFunction.column; | ||
const endColumn = | ||
linesOffset == 0 | ||
? startColumn + rawText.length | ||
: nameChunks.at(-1)?.length ?? 0; | ||
const warning: SyntaxDiagnostic = { | ||
severity: DiagnosticSeverity.Warning, | ||
range: { | ||
start: Position.create(lineIndex, startColumn), | ||
end: Position.create(lineIndex + linesOffset, endColumn), | ||
}, | ||
offsets: parsedFunction.offsets, | ||
message: `Function ${parsedFunction.parsedName} is not present in the database. Make sure you didn't misspell it or that it is available when you run this statement in your application`, | ||
}; | ||
return warning; | ||
} | ||
function warnOnUndeclaredLabels( | ||
@@ -198,3 +250,7 @@ parsingResult: ParsedStatement, | ||
const labelWarnings = warnOnUndeclaredLabels(statement, dbSchema); | ||
return diagnostics.concat(labelWarnings).sort(sortByPositionAndMessage); | ||
const functionWarnings = warnOnUndeclaredFunctions(statement, dbSchema); | ||
return diagnostics | ||
.concat(labelWarnings, functionWarnings) | ||
.sort(sortByPositionAndMessage); | ||
}); | ||
@@ -240,1 +296,23 @@ | ||
} | ||
function warnOnUndeclaredFunctions( | ||
parsingResult: ParsedStatement, | ||
dbSchema: DbSchema, | ||
): SyntaxDiagnostic[] { | ||
const warnings: SyntaxDiagnostic[] = []; | ||
if (dbSchema.functions) { | ||
const functionsInQuery = parsingResult.collectedFunctions; | ||
functionsInQuery.forEach((parsedFunction) => { | ||
const warning = detectNonDeclaredFunction( | ||
parsedFunction, | ||
dbSchema.functions, | ||
); | ||
if (warning) warnings.push(warning); | ||
}); | ||
} | ||
return warnings; | ||
} |
@@ -1,4 +0,4 @@ | ||
import { CompletionItem } from 'vscode-languageserver-types'; | ||
import { autocomplete } from '../../autocompletion/autocompletion'; | ||
import { DbSchema } from '../../dbSchema'; | ||
import { CompletionItem } from '../../types'; | ||
@@ -5,0 +5,0 @@ export function testCompletionsExactly({ |
@@ -114,2 +114,48 @@ import { CompletionItemKind } from 'vscode-languageserver-types'; | ||
test('Correctly completes database name even in a create alias statement', () => { | ||
testCompletions({ | ||
query: 'CREATE ALIAS fo for DATABASE ', | ||
dbSchema, | ||
expected: [ | ||
{ label: 'db1', kind: CompletionItemKind.Value }, | ||
{ label: 'db2', kind: CompletionItemKind.Value }, | ||
{ label: 'movies', kind: CompletionItemKind.Value }, | ||
{ label: 'myMovies', kind: CompletionItemKind.Value }, | ||
{ label: 'scoped.alias', kind: CompletionItemKind.Value }, | ||
{ label: 'a.b.c.d', kind: CompletionItemKind.Value }, | ||
{ label: '$param1', kind: CompletionItemKind.Variable }, | ||
], | ||
excluded: [ | ||
// validate invalid keyword bug isn't present | ||
{ label: '', kind: CompletionItemKind.Keyword }, | ||
// do not suggest non-string parameters | ||
{ label: '$param2', kind: CompletionItemKind.Variable }, | ||
{ label: '$param3', kind: CompletionItemKind.Variable }, | ||
], | ||
}); | ||
}); | ||
test('Correctly completes database name even in a create alias statement including extra of spaces', () => { | ||
testCompletions({ | ||
query: 'CREATE ALIAS foo FOR DATABASE ', | ||
dbSchema, | ||
expected: [ | ||
{ label: 'db1', kind: CompletionItemKind.Value }, | ||
{ label: 'db2', kind: CompletionItemKind.Value }, | ||
{ label: 'movies', kind: CompletionItemKind.Value }, | ||
{ label: 'myMovies', kind: CompletionItemKind.Value }, | ||
{ label: 'scoped.alias', kind: CompletionItemKind.Value }, | ||
{ label: 'a.b.c.d', kind: CompletionItemKind.Value }, | ||
{ label: '$param1', kind: CompletionItemKind.Variable }, | ||
], | ||
excluded: [ | ||
// validate invalid keyword bug isn't present | ||
{ label: '', kind: CompletionItemKind.Keyword }, | ||
// do not suggest non-string parameters | ||
{ label: '$param2', kind: CompletionItemKind.Variable }, | ||
{ label: '$param3', kind: CompletionItemKind.Variable }, | ||
], | ||
}); | ||
}); | ||
test('Suggests only aliases when dropping alias', () => { | ||
@@ -116,0 +162,0 @@ const query = 'DROP ALIAS '; |
@@ -1,2 +0,5 @@ | ||
import { CompletionItemKind } from 'vscode-languageserver-types'; | ||
import { | ||
CompletionItemKind, | ||
CompletionItemTag, | ||
} from 'vscode-languageserver-types'; | ||
import { DbSchema } from '../../dbSchema'; | ||
@@ -8,2 +11,3 @@ import { testData } from '../testData'; | ||
const dbSchema: DbSchema = testData.mockSchema; | ||
const functions = dbSchema.functions; | ||
@@ -20,2 +24,4 @@ test('Correctly completes unstarted function name in left hand side of WHERE', () => { | ||
detail: '(function)', | ||
signature: functions['acos'].signature, | ||
documentation: functions['acos'].description, | ||
}, | ||
@@ -31,2 +37,4 @@ { | ||
detail: '(function)', | ||
signature: functions['apoc.agg.graph'].signature, | ||
documentation: functions['apoc.agg.graph'].description, | ||
}, | ||
@@ -37,3 +45,13 @@ { | ||
detail: '(function)', | ||
signature: functions['apoc.coll.pairs'].signature, | ||
documentation: functions['apoc.coll.pairs'].description, | ||
}, | ||
{ | ||
label: 'apoc.create.uuid', | ||
kind: CompletionItemKind.Function, | ||
detail: '(function)', | ||
signature: functions['apoc.create.uuid'].signature, | ||
documentation: functions['apoc.create.uuid'].description, | ||
tags: [CompletionItemTag.Deprecated], | ||
}, | ||
], | ||
@@ -53,2 +71,4 @@ }); | ||
detail: '(function)', | ||
signature: functions['acos'].signature, | ||
documentation: functions['acos'].description, | ||
}, | ||
@@ -59,2 +79,4 @@ { | ||
detail: '(function)', | ||
signature: functions['apoc.agg.graph'].signature, | ||
documentation: functions['apoc.agg.graph'].description, | ||
}, | ||
@@ -65,3 +87,13 @@ { | ||
detail: '(function)', | ||
signature: functions['apoc.coll.pairs'].signature, | ||
documentation: functions['apoc.coll.pairs'].description, | ||
}, | ||
{ | ||
label: 'apoc.create.uuid', | ||
kind: CompletionItemKind.Function, | ||
detail: '(function)', | ||
signature: functions['apoc.create.uuid'].signature, | ||
documentation: functions['apoc.create.uuid'].description, | ||
tags: [CompletionItemTag.Deprecated], | ||
}, | ||
], | ||
@@ -88,3 +120,9 @@ }); | ||
], | ||
excluded: [{ label: 'acos', kind: CompletionItemKind.Function }], | ||
excluded: [ | ||
{ label: 'acos', kind: CompletionItemKind.Function }, | ||
{ | ||
label: 'agg.graph', | ||
kind: CompletionItemKind.Function, | ||
}, | ||
], | ||
}); | ||
@@ -103,2 +141,4 @@ }); | ||
detail: '(function)', | ||
signature: functions['apoc.agg.first'].signature, | ||
documentation: functions['apoc.agg.first'].description, | ||
}, | ||
@@ -109,2 +149,4 @@ { | ||
detail: '(function)', | ||
signature: functions['apoc.agg.last'].signature, | ||
documentation: functions['apoc.agg.last'].description, | ||
}, | ||
@@ -115,2 +157,4 @@ { | ||
detail: '(function)', | ||
signature: functions['apoc.agg.slice'].signature, | ||
documentation: functions['apoc.agg.slice'].description, | ||
}, | ||
@@ -148,12 +192,18 @@ ], | ||
detail: '(function)', | ||
signature: functions['apoc.agg.first'].signature, | ||
documentation: functions['apoc.agg.first'].description, | ||
}, | ||
{ | ||
label: 'first', | ||
label: 'last', | ||
kind: CompletionItemKind.Function, | ||
detail: '(function)', | ||
signature: functions['apoc.agg.last'].signature, | ||
documentation: functions['apoc.agg.last'].description, | ||
}, | ||
{ | ||
label: 'first', | ||
label: 'slice', | ||
kind: CompletionItemKind.Function, | ||
detail: '(function)', | ||
signature: functions['apoc.agg.slice'].signature, | ||
documentation: functions['apoc.agg.slice'].description, | ||
}, | ||
@@ -271,2 +321,4 @@ ], | ||
detail: '(function)', | ||
signature: functions['apoc.agg.percentiles'].signature, | ||
documentation: functions['apoc.agg.percentiles'].description, | ||
}, | ||
@@ -277,2 +329,4 @@ { | ||
detail: '(function)', | ||
signature: functions['acos'].signature, | ||
documentation: functions['acos'].description, | ||
}, | ||
@@ -293,2 +347,4 @@ ], | ||
detail: '(function)', | ||
signature: functions['apoc.agg.percentiles'].signature, | ||
documentation: functions['apoc.agg.percentiles'].description, | ||
}, | ||
@@ -304,2 +360,4 @@ { | ||
detail: '(function)', | ||
signature: functions['acos'].signature, | ||
documentation: functions['acos'].description, | ||
}, | ||
@@ -330,2 +388,4 @@ ], | ||
detail: '(function)', | ||
documentation: '', | ||
signature: '', | ||
}, | ||
@@ -335,2 +395,20 @@ ], | ||
}); | ||
test('Correctly completes deprecated functions when namespace started', () => { | ||
const query = 'RETURN apoc.create.'; | ||
testCompletions({ | ||
query, | ||
dbSchema, | ||
expected: [ | ||
{ | ||
label: 'uuid', | ||
kind: CompletionItemKind.Function, | ||
detail: '(function)', | ||
signature: functions['apoc.create.uuid'].signature, | ||
documentation: functions['apoc.create.uuid'].description, | ||
tags: [CompletionItemTag.Deprecated], | ||
}, | ||
], | ||
}); | ||
}); | ||
}); |
@@ -66,2 +66,34 @@ import { CompletionItemKind } from 'vscode-languageserver-types'; | ||
test('Correctly completes unstarted label when caret is passed', () => { | ||
const query = 'MATCH (n:)'; | ||
testCompletions({ | ||
query, | ||
offset: query.length - 1, | ||
dbSchema: { labels: ['Cat', 'Person', 'Dog'] }, | ||
expected: [{ label: 'Person', kind: CompletionItemKind.TypeParameter }], | ||
}); | ||
}); | ||
test.only('Correctly completes unstarted label when caret is passed and there is a space', () => { | ||
const query = 'MATCH (n : '; | ||
testCompletions({ | ||
query, | ||
dbSchema: { labels: ['Cat', 'Person', 'Dog'] }, | ||
expected: [{ label: 'Person', kind: CompletionItemKind.TypeParameter }], | ||
}); | ||
}); | ||
test('Correctly completes unstarted label for a first statement when caret is passed', () => { | ||
const query = 'MATCH (n:); MATCH (m:)'; | ||
testCompletions({ | ||
query, | ||
offset: 'MATCH (n:)'.length - 1, | ||
dbSchema: { labels: ['Cat', 'Person', 'Dog'] }, | ||
expected: [{ label: 'Person', kind: CompletionItemKind.TypeParameter }], | ||
}); | ||
}); | ||
test('Correctly completes started barred label inside a node pattern', () => { | ||
@@ -68,0 +100,0 @@ const query = 'MATCH (n:A|B'; |
@@ -1,2 +0,5 @@ | ||
import { CompletionItemKind } from 'vscode-languageserver-types'; | ||
import { | ||
CompletionItemKind, | ||
CompletionItemTag, | ||
} from 'vscode-languageserver-types'; | ||
import { DbSchema } from '../../dbSchema'; | ||
@@ -7,5 +10,14 @@ import { testData } from '../testData'; | ||
describe('Procedures auto-completion', () => { | ||
const procedures = testData.mockSchema.procedures; | ||
const dbSchema: DbSchema = { | ||
procedures: { | ||
'tx.getMetaData': { ...testData.emptyProcedure, name: 'tx.getMetaData' }, | ||
'tx.getMetaData': procedures['tx.getMetaData'], | ||
'db.index.fulltext.awaitEventuallyConsistentIndexRefresh': | ||
procedures['db.index.fulltext.awaitEventuallyConsistentIndexRefresh'], | ||
'db.ping': procedures['db.ping'], | ||
'db.stats.retrieve': procedures['db.stats.retrieve'], | ||
'db.stats.collect': procedures['db.stats.collect'], | ||
'db.stats.clear': procedures['db.stats.clear'], | ||
'cdc.current': procedures['cdc.current'], | ||
'jwt.security.requestAccess': { | ||
@@ -15,16 +27,2 @@ ...testData.emptyProcedure, | ||
}, | ||
'db.index.fulltext.awaitEventuallyConsistentIndexRefresh': { | ||
...testData.emptyProcedure, | ||
name: 'db.index.fulltext.awaitEventuallyConsistentIndexRefresh', | ||
}, | ||
'db.ping': { ...testData.emptyProcedure, name: 'db.ping' }, | ||
'db.stats.retrieve': { | ||
...testData.emptyProcedure, | ||
name: 'db.stats.retrieve', | ||
}, | ||
'db.stats.collect': { | ||
...testData.emptyProcedure, | ||
name: 'db.stats.collect', | ||
}, | ||
'db.stats.clear': { ...testData.emptyProcedure, name: 'db.stats.clear' }, | ||
}, | ||
@@ -71,7 +69,19 @@ }; | ||
detail: '(procedure)', | ||
signature: procedures['tx.getMetaData'].signature, | ||
documentation: procedures['tx.getMetaData'].description, | ||
}, | ||
{ | ||
label: 'cdc.current', | ||
kind: CompletionItemKind.Method, | ||
detail: '(procedure)', | ||
signature: procedures['cdc.current'].signature, | ||
documentation: procedures['cdc.current'].description, | ||
tags: [CompletionItemTag.Deprecated], | ||
}, | ||
{ | ||
label: 'jwt.security.requestAccess', | ||
kind: CompletionItemKind.Method, | ||
detail: '(procedure)', | ||
documentation: '', | ||
signature: '', | ||
}, | ||
@@ -97,2 +107,4 @@ ], | ||
detail: '(procedure)', | ||
signature: procedures['db.ping'].signature, | ||
documentation: procedures['db.ping'].description, | ||
}, | ||
@@ -118,2 +130,4 @@ ], | ||
detail: '(procedure)', | ||
signature: procedures['db.stats.retrieve'].signature, | ||
documentation: procedures['db.stats.retrieve'].description, | ||
}, | ||
@@ -124,2 +138,4 @@ { | ||
detail: '(procedure)', | ||
signature: procedures['db.stats.collect'].signature, | ||
documentation: procedures['db.stats.collect'].description, | ||
}, | ||
@@ -130,2 +146,4 @@ { | ||
detail: '(procedure)', | ||
signature: procedures['db.stats.clear'].signature, | ||
documentation: procedures['db.stats.clear'].description, | ||
}, | ||
@@ -163,2 +181,4 @@ ], | ||
detail: '(procedure)', | ||
signature: procedures['db.stats.retrieve'].signature, | ||
documentation: procedures['db.stats.retrieve'].description, | ||
}, | ||
@@ -169,2 +189,4 @@ { | ||
detail: '(procedure)', | ||
signature: procedures['db.stats.collect'].signature, | ||
documentation: procedures['db.stats.collect'].description, | ||
}, | ||
@@ -175,2 +197,4 @@ { | ||
detail: '(procedure)', | ||
signature: procedures['db.stats.clear'].signature, | ||
documentation: procedures['db.stats.clear'].description, | ||
}, | ||
@@ -247,2 +271,4 @@ ], | ||
detail: '(procedure)', | ||
signature: procedures['db.ping'].signature, | ||
documentation: procedures['db.ping'].description, | ||
}, | ||
@@ -258,2 +284,20 @@ { | ||
}); | ||
test('Correctly completes deprecated procedures when namespace started', () => { | ||
const query = 'CALL cdc.'; | ||
testCompletions({ | ||
query, | ||
dbSchema, | ||
expected: [ | ||
{ | ||
label: 'current', | ||
kind: CompletionItemKind.Method, | ||
detail: '(procedure)', | ||
signature: procedures['cdc.current'].signature, | ||
documentation: procedures['cdc.current'].description, | ||
tags: [CompletionItemTag.Deprecated], | ||
}, | ||
], | ||
}); | ||
}); | ||
}); |
import { autocomplete } from '../autocompletion/autocompletion'; | ||
import { | ||
ParsedCommandNoPosition, | ||
parserWrapper, | ||
setConsoleCommandsEnabled, | ||
} from '../parserWrapper'; | ||
import { _internalFeatureFlags } from '../featureFlags'; | ||
import { ParsedCommandNoPosition, parserWrapper } from '../parserWrapper'; | ||
import { applySyntaxColouring } from '../syntaxColouring/syntaxColouring'; | ||
@@ -43,6 +40,6 @@ import { testData } from './testData'; | ||
beforeAll(() => { | ||
setConsoleCommandsEnabled(true); | ||
_internalFeatureFlags.consoleCommands = true; | ||
}); | ||
afterAll(() => { | ||
setConsoleCommandsEnabled(false); | ||
_internalFeatureFlags.consoleCommands = false; | ||
}); | ||
@@ -149,6 +146,6 @@ | ||
beforeAll(() => { | ||
setConsoleCommandsEnabled(true); | ||
_internalFeatureFlags.consoleCommands = true; | ||
}); | ||
afterAll(() => { | ||
setConsoleCommandsEnabled(false); | ||
_internalFeatureFlags.consoleCommands = false; | ||
}); | ||
@@ -216,6 +213,6 @@ test('parses without arg', () => { | ||
beforeAll(() => { | ||
setConsoleCommandsEnabled(true); | ||
_internalFeatureFlags.consoleCommands = true; | ||
}); | ||
afterAll(() => { | ||
setConsoleCommandsEnabled(false); | ||
_internalFeatureFlags.consoleCommands = false; | ||
}); | ||
@@ -268,3 +265,9 @@ test('basic param usage', () => { | ||
{ detail: '(namespace)', kind: 3, label: 'duration' }, | ||
{ detail: '(function)', kind: 3, label: 'duration.inSeconds' }, | ||
{ | ||
detail: '(function)', | ||
kind: 3, | ||
label: 'duration.inSeconds', | ||
signature: '', | ||
documentation: '', | ||
}, | ||
{ kind: 14, label: 'TRUE' }, | ||
@@ -454,6 +457,6 @@ { kind: 14, label: 'FALSE' }, | ||
beforeAll(() => { | ||
setConsoleCommandsEnabled(true); | ||
_internalFeatureFlags.consoleCommands = true; | ||
}); | ||
afterAll(() => { | ||
setConsoleCommandsEnabled(false); | ||
_internalFeatureFlags.consoleCommands = false; | ||
}); | ||
@@ -460,0 +463,0 @@ test('parses cypher', () => { |
@@ -221,2 +221,10 @@ import { SignatureHelp } from 'vscode-languageserver-types'; | ||
}); | ||
test('Provides signature help for procedures when another argument is a function', () => { | ||
testSignatureHelp( | ||
'CALL apoc.do.when(apoc.coll.combinations(coll, something), ', | ||
dbSchema, | ||
expectedArgIndex(1), | ||
); | ||
}); | ||
}); | ||
@@ -393,2 +401,18 @@ | ||
}); | ||
test('Provides signature help for functions inside procedures, first argument', () => { | ||
testSignatureHelp( | ||
'CALL apoc.do.when(apoc.coll.combinations(', | ||
dbSchema, | ||
expectedArgIndex(0), | ||
); | ||
}); | ||
test('Provides signature help for functions inside procedures, second argument', () => { | ||
testSignatureHelp( | ||
'CALL apoc.do.when(apoc.coll.combinations(coll,', | ||
dbSchema, | ||
expectedArgIndex(1), | ||
); | ||
}); | ||
}); |
@@ -1,2 +0,2 @@ | ||
import { setConsoleCommandsEnabled } from '../../parserWrapper'; | ||
import { _internalFeatureFlags } from '../../featureFlags'; | ||
import { testData } from '../testData'; | ||
@@ -1177,3 +1177,3 @@ import { getDiagnosticsForQuery } from './helpers'; | ||
message: | ||
'A pattern expression should only be used in order to test the existence of a pattern. It can no longer be used inside the function size(), an alternative is to replace size() with COUNT {}.', | ||
'A pattern expression should only be used in order to test the existence of a pattern. It should therefore only be used in contexts that evaluate to a boolean, e.g. inside the function exists() or in a WHERE-clause. No other uses are allowed, instead they should be replaced by a pattern comprehension.', | ||
offsets: { | ||
@@ -1256,3 +1256,4 @@ end: 29, | ||
test('gives error on console commands when they are disabled', () => { | ||
setConsoleCommandsEnabled(true); | ||
_internalFeatureFlags.consoleCommands = true; | ||
expect( | ||
@@ -1298,7 +1299,7 @@ getDiagnosticsForQuery({ query: 'RETURN a;:clear; RETURN b;:history;' }), | ||
]); | ||
setConsoleCommandsEnabled(false); | ||
_internalFeatureFlags.consoleCommands = false; | ||
}); | ||
test('Handles multiple cypher statements in a single query', () => { | ||
setConsoleCommandsEnabled(true); | ||
_internalFeatureFlags.consoleCommands = true; | ||
expect(getDiagnosticsForQuery({ query: 'RETURN a; RETURN b;' })).toEqual([ | ||
@@ -1342,7 +1343,7 @@ { | ||
]); | ||
setConsoleCommandsEnabled(false); | ||
_internalFeatureFlags.consoleCommands = false; | ||
}); | ||
test('Handles cypher mixed with client commands', () => { | ||
setConsoleCommandsEnabled(true); | ||
_internalFeatureFlags.consoleCommands = true; | ||
expect( | ||
@@ -1390,7 +1391,7 @@ getDiagnosticsForQuery({ | ||
]); | ||
setConsoleCommandsEnabled(false); | ||
_internalFeatureFlags.consoleCommands = false; | ||
}); | ||
test('Handles cypher mixed with complex client command', () => { | ||
setConsoleCommandsEnabled(true); | ||
_internalFeatureFlags.consoleCommands = true; | ||
expect( | ||
@@ -1426,3 +1427,3 @@ getDiagnosticsForQuery({ | ||
]); | ||
setConsoleCommandsEnabled(false); | ||
_internalFeatureFlags.consoleCommands = false; | ||
}); | ||
@@ -1429,0 +1430,0 @@ |
@@ -0,1 +1,2 @@ | ||
import { testData } from '../testData'; | ||
import { getDiagnosticsForQuery } from './helpers'; | ||
@@ -815,3 +816,3 @@ | ||
{ | ||
message: 'Expected a string or a parameter', | ||
message: 'Expected any of CHANGE, a string or a parameter', | ||
offsets: { | ||
@@ -980,2 +981,457 @@ end: 39, | ||
}); | ||
test('Syntax validation warns on missing function when database can be contacted', () => { | ||
const query = `RETURN dontpanic("marvin")`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([ | ||
{ | ||
offsets: { | ||
end: 16, | ||
start: 7, | ||
}, | ||
message: | ||
"Function dontpanic is not present in the database. Make sure you didn't misspell it or that it is available when you run this statement in your application", | ||
range: { | ||
end: { | ||
character: 16, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 7, | ||
line: 0, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
]); | ||
}); | ||
test('Syntax validation does not warn on existing function when database can be contacted', () => { | ||
const query = `RETURN abs(4)`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([]); | ||
}); | ||
test('Syntax validation warns on missing function with namespace when database can be contacted', () => { | ||
const query = `RETURN test.dontpanic("marvin")`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([ | ||
{ | ||
offsets: { | ||
end: 21, | ||
start: 7, | ||
}, | ||
message: | ||
"Function test.dontpanic is not present in the database. Make sure you didn't misspell it or that it is available when you run this statement in your application", | ||
range: { | ||
end: { | ||
character: 21, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 7, | ||
line: 0, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
]); | ||
}); | ||
test('Syntax validation does not warn on existing function with namespace when database can be contacted', () => { | ||
const query = `RETURN apoc.text.decapitalize("Marvin")`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([]); | ||
}); | ||
test('Syntax validation warns on missing function with namespace split in multiple lines when database can be contacted', () => { | ||
const query = `RETURN test. | ||
dontpanic | ||
("marvin") | ||
`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([ | ||
{ | ||
offsets: { | ||
end: 26, | ||
start: 7, | ||
}, | ||
message: | ||
"Function test.dontpanic is not present in the database. Make sure you didn't misspell it or that it is available when you run this statement in your application", | ||
range: { | ||
end: { | ||
character: 13, | ||
line: 1, | ||
}, | ||
start: { | ||
character: 7, | ||
line: 0, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
]); | ||
}); | ||
test('Syntax validation does not warn on existing function with namespace split in multiple lines when database can be contacted', () => { | ||
const query = ` | ||
RETURN apoc.text. | ||
capitalize | ||
("marvin") | ||
`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([]); | ||
}); | ||
test('Syntax validation is case insensitive on built-in functions', () => { | ||
const query = ` | ||
RETURN aBS(123) | ||
`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([]); | ||
}); | ||
test('Syntax validation is not case insensitive on user defined functions', () => { | ||
const query = ` | ||
RETURN apoc.text.capiTALize("marvin") | ||
`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([ | ||
{ | ||
message: | ||
"Function apoc.text.capiTALize is not present in the database. Make sure you didn't misspell it or that it is available when you run this statement in your application", | ||
offsets: { | ||
end: 32, | ||
start: 12, | ||
}, | ||
range: { | ||
end: { | ||
character: 31, | ||
line: 1, | ||
}, | ||
start: { | ||
character: 11, | ||
line: 1, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
]); | ||
}); | ||
test('Syntax validation does not warn on existing function with spaces when database can be contacted', () => { | ||
const query = `RETURN apoc. text. decapitalize ("Marvin")`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([]); | ||
}); | ||
test('Syntax validation warns with correct positions with spaces when database can be contacted', () => { | ||
const query = `RETURN apoc. text. dontpanic ("Marvin")`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([ | ||
{ | ||
message: | ||
"Function apoc.text.dontpanic is not present in the database. Make sure you didn't misspell it or that it is available when you run this statement in your application", | ||
offsets: { | ||
end: 31, | ||
start: 7, | ||
}, | ||
range: { | ||
end: { | ||
character: 31, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 7, | ||
line: 0, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
]); | ||
}); | ||
test('Syntax validation does not warn on existing function with new lines when database can be contacted', () => { | ||
const query = `RETURN apoc. | ||
text. | ||
decapitalize | ||
("Marvin")`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([]); | ||
}); | ||
test('Syntax validation warns with correct positions with spaces when database can be contacted', () => { | ||
const query = `RETURN apoc. text. | ||
dontpanic | ||
("Marvin")`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([ | ||
{ | ||
message: | ||
"Function apoc.text.dontpanic is not present in the database. Make sure you didn't misspell it or that it is available when you run this statement in your application", | ||
offsets: { | ||
end: 36, | ||
start: 7, | ||
}, | ||
range: { | ||
end: { | ||
character: 14, | ||
line: 1, | ||
}, | ||
start: { | ||
character: 7, | ||
line: 0, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
]); | ||
}); | ||
test('Syntax validation should recognize escaped function names', () => { | ||
const query = ` | ||
RETURN \`abs\`(123) | ||
`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([]); | ||
}); | ||
test('Syntax validation should fail on escaped function names that do not exist', () => { | ||
const query = ` | ||
RETURN \`dontpanic\`(123) | ||
`; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([ | ||
{ | ||
message: | ||
"Function dontpanic is not present in the database. Make sure you didn't misspell it or that it is available when you run this statement in your application", | ||
offsets: { | ||
end: 23, | ||
start: 12, | ||
}, | ||
range: { | ||
end: { | ||
character: 22, | ||
line: 1, | ||
}, | ||
start: { | ||
character: 11, | ||
line: 1, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
]); | ||
}); | ||
test('Syntax validation should pass on escaped function names with namespaces', () => { | ||
const query = "RETURN `apoc`.text.`capitalize`('Marvin');"; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([]); | ||
}); | ||
test('Syntax validation should fail on escaped function names with namespaces that do not exist', () => { | ||
const query = "RETURN `apoc`.text.`dontpanic`('Marvin');"; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([ | ||
{ | ||
message: | ||
"Function apoc.text.dontpanic is not present in the database. Make sure you didn't misspell it or that it is available when you run this statement in your application", | ||
offsets: { | ||
end: 30, | ||
start: 7, | ||
}, | ||
range: { | ||
end: { | ||
character: 30, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 7, | ||
line: 0, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
]); | ||
}); | ||
test('Syntax validation should fail if whole name and namespaces are escaped', () => { | ||
const query = "RETURN `apoc.text.capitalize`('Marvin');"; | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
dbSchema: { | ||
labels: ['Dog', 'Cat'], | ||
relationshipTypes: ['Person'], | ||
functions: testData.mockSchema.functions, | ||
}, | ||
}), | ||
).toEqual([ | ||
{ | ||
message: | ||
"Function `apoc.text.capitalize` is not present in the database. Make sure you didn't misspell it or that it is available when you run this statement in your application", | ||
offsets: { | ||
end: 29, | ||
start: 7, | ||
}, | ||
range: { | ||
end: { | ||
character: 29, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 7, | ||
line: 0, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
]); | ||
}); | ||
}); |
@@ -0,1 +1,3 @@ | ||
import { CompletionItem as VSCodeCompletionItem } from 'vscode-languageserver-types'; | ||
export type ReturnDescription = { | ||
@@ -37,2 +39,7 @@ name: string; | ||
aggregating: boolean; | ||
isDeprecated: boolean; | ||
}; | ||
export type CompletionItem = VSCodeCompletionItem & { | ||
signature?: string; | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
142193715
126
153357