@neo4j-cypher/language-support
Advanced tools
Comparing version 2.0.0-canary-0d0dce4 to 2.0.0-canary-0d4fb85
# @neo4j-cypher/language-support | ||
## 2.0.0-next.8 | ||
### Patch Changes | ||
- 05663bd: Fixes bug using non language keywords (EXPLAIN, PROFILE, etc) as symbolic names | ||
## 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 +20,0 @@ |
@@ -49,270 +49,274 @@ import { ATN, CharStream, DFA, Lexer } from "antlr4"; | ||
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 CASCADE = 47; | ||
static readonly CASE = 48; | ||
static readonly CHANGE = 49; | ||
static readonly CIDR = 50; | ||
static readonly COLLECT = 51; | ||
static readonly COLON = 52; | ||
static readonly COLONCOLON = 53; | ||
static readonly COMMA = 54; | ||
static readonly COMMAND = 55; | ||
static readonly COMMANDS = 56; | ||
static readonly COMMIT = 57; | ||
static readonly COMPOSITE = 58; | ||
static readonly CONCURRENT = 59; | ||
static readonly CONSTRAINT = 60; | ||
static readonly CONSTRAINTS = 61; | ||
static readonly CONTAINS = 62; | ||
static readonly COPY = 63; | ||
static readonly CONTINUE = 64; | ||
static readonly COUNT = 65; | ||
static readonly CREATE = 66; | ||
static readonly CSV = 67; | ||
static readonly CURRENT = 68; | ||
static readonly DATA = 69; | ||
static readonly DATABASE = 70; | ||
static readonly DATABASES = 71; | ||
static readonly DATE = 72; | ||
static readonly DATETIME = 73; | ||
static readonly DBMS = 74; | ||
static readonly DEALLOCATE = 75; | ||
static readonly DEFAULT = 76; | ||
static readonly DEFINED = 77; | ||
static readonly DELETE = 78; | ||
static readonly DENY = 79; | ||
static readonly DESC = 80; | ||
static readonly DESCENDING = 81; | ||
static readonly DESTROY = 82; | ||
static readonly DETACH = 83; | ||
static readonly DIFFERENT = 84; | ||
static readonly DOLLAR = 85; | ||
static readonly DISTINCT = 86; | ||
static readonly DIVIDE = 87; | ||
static readonly DOT = 88; | ||
static readonly DOTDOT = 89; | ||
static readonly DOUBLEBAR = 90; | ||
static readonly DRIVER = 91; | ||
static readonly DROP = 92; | ||
static readonly DRYRUN = 93; | ||
static readonly DUMP = 94; | ||
static readonly DURATION = 95; | ||
static readonly EACH = 96; | ||
static readonly EDGE = 97; | ||
static readonly ENABLE = 98; | ||
static readonly ELEMENT = 99; | ||
static readonly ELEMENTS = 100; | ||
static readonly ELSE = 101; | ||
static readonly ENCRYPTED = 102; | ||
static readonly END = 103; | ||
static readonly ENDS = 104; | ||
static readonly EQ = 105; | ||
static readonly EXECUTABLE = 106; | ||
static readonly EXECUTE = 107; | ||
static readonly EXIST = 108; | ||
static readonly EXISTENCE = 109; | ||
static readonly EXISTS = 110; | ||
static readonly ERROR = 111; | ||
static readonly FAIL = 112; | ||
static readonly FALSE = 113; | ||
static readonly FIELDTERMINATOR = 114; | ||
static readonly FINISH = 115; | ||
static readonly FLOAT = 116; | ||
static readonly FOR = 117; | ||
static readonly FOREACH = 118; | ||
static readonly FROM = 119; | ||
static readonly FULLTEXT = 120; | ||
static readonly FUNCTION = 121; | ||
static readonly FUNCTIONS = 122; | ||
static readonly GE = 123; | ||
static readonly GRANT = 124; | ||
static readonly GRAPH = 125; | ||
static readonly GRAPHS = 126; | ||
static readonly GROUP = 127; | ||
static readonly GROUPS = 128; | ||
static readonly GT = 129; | ||
static readonly HEADERS = 130; | ||
static readonly HOME = 131; | ||
static readonly ID = 132; | ||
static readonly IF = 133; | ||
static readonly IMPERSONATE = 134; | ||
static readonly IMMUTABLE = 135; | ||
static readonly IN = 136; | ||
static readonly INDEX = 137; | ||
static readonly INDEXES = 138; | ||
static readonly INF = 139; | ||
static readonly INFINITY = 140; | ||
static readonly INSERT = 141; | ||
static readonly INT = 142; | ||
static readonly INTEGER = 143; | ||
static readonly IS = 144; | ||
static readonly JOIN = 145; | ||
static readonly KEY = 146; | ||
static readonly LABEL = 147; | ||
static readonly LABELS = 148; | ||
static readonly AMPERSAND = 149; | ||
static readonly EXCLAMATION_MARK = 150; | ||
static readonly LBRACKET = 151; | ||
static readonly LCURLY = 152; | ||
static readonly LE = 153; | ||
static readonly LEADING = 154; | ||
static readonly LIMITROWS = 155; | ||
static readonly LIST = 156; | ||
static readonly LOAD = 157; | ||
static readonly LOCAL = 158; | ||
static readonly LOOKUP = 159; | ||
static readonly LPAREN = 160; | ||
static readonly LT = 161; | ||
static readonly MANAGEMENT = 162; | ||
static readonly MAP = 163; | ||
static readonly MATCH = 164; | ||
static readonly MERGE = 165; | ||
static readonly MINUS = 166; | ||
static readonly PERCENT = 167; | ||
static readonly INVALID_NEQ = 168; | ||
static readonly NEQ = 169; | ||
static readonly NAME = 170; | ||
static readonly NAMES = 171; | ||
static readonly NAN = 172; | ||
static readonly NFC = 173; | ||
static readonly NFD = 174; | ||
static readonly NFKC = 175; | ||
static readonly NFKD = 176; | ||
static readonly NEW = 177; | ||
static readonly NODE = 178; | ||
static readonly NODETACH = 179; | ||
static readonly NODES = 180; | ||
static readonly NONE = 181; | ||
static readonly NORMALIZE = 182; | ||
static readonly NORMALIZED = 183; | ||
static readonly NOT = 184; | ||
static readonly NOTHING = 185; | ||
static readonly NOWAIT = 186; | ||
static readonly NULL = 187; | ||
static readonly OF = 188; | ||
static readonly OFFSET = 189; | ||
static readonly ON = 190; | ||
static readonly ONLY = 191; | ||
static readonly OPTIONAL = 192; | ||
static readonly OPTIONS = 193; | ||
static readonly OPTION = 194; | ||
static readonly OR = 195; | ||
static readonly ORDER = 196; | ||
static readonly OUTPUT = 197; | ||
static readonly PASSWORD = 198; | ||
static readonly PASSWORDS = 199; | ||
static readonly PATH = 200; | ||
static readonly PATHS = 201; | ||
static readonly PERIODIC = 202; | ||
static readonly PLAINTEXT = 203; | ||
static readonly PLUS = 204; | ||
static readonly PLUSEQUAL = 205; | ||
static readonly POINT = 206; | ||
static readonly POPULATED = 207; | ||
static readonly POW = 208; | ||
static readonly PRIMARY = 209; | ||
static readonly PRIMARIES = 210; | ||
static readonly PRIVILEGE = 211; | ||
static readonly PRIVILEGES = 212; | ||
static readonly PROCEDURE = 213; | ||
static readonly PROCEDURES = 214; | ||
static readonly PROPERTIES = 215; | ||
static readonly PROPERTY = 216; | ||
static readonly PROVIDER = 217; | ||
static readonly PROVIDERS = 218; | ||
static readonly QUESTION = 219; | ||
static readonly RANGE = 220; | ||
static readonly RBRACKET = 221; | ||
static readonly RCURLY = 222; | ||
static readonly READ = 223; | ||
static readonly REALLOCATE = 224; | ||
static readonly REDUCE = 225; | ||
static readonly RENAME = 226; | ||
static readonly REGEQ = 227; | ||
static readonly REL = 228; | ||
static readonly RELATIONSHIP = 229; | ||
static readonly RELATIONSHIPS = 230; | ||
static readonly REMOVE = 231; | ||
static readonly REPEATABLE = 232; | ||
static readonly REPLACE = 233; | ||
static readonly REPORT = 234; | ||
static readonly REQUIRE = 235; | ||
static readonly REQUIRED = 236; | ||
static readonly RESTRICT = 237; | ||
static readonly RETURN = 238; | ||
static readonly REVOKE = 239; | ||
static readonly ROLE = 240; | ||
static readonly ROLES = 241; | ||
static readonly ROW = 242; | ||
static readonly ROWS = 243; | ||
static readonly RPAREN = 244; | ||
static readonly SCAN = 245; | ||
static readonly SEC = 246; | ||
static readonly SECOND = 247; | ||
static readonly SECONDARY = 248; | ||
static readonly SECONDARIES = 249; | ||
static readonly SECONDS = 250; | ||
static readonly SEEK = 251; | ||
static readonly SEMICOLON = 252; | ||
static readonly SERVER = 253; | ||
static readonly SERVERS = 254; | ||
static readonly SET = 255; | ||
static readonly SETTING = 256; | ||
static readonly SETTINGS = 257; | ||
static readonly SHORTEST_PATH = 258; | ||
static readonly SHORTEST = 259; | ||
static readonly SHOW = 260; | ||
static readonly SIGNED = 261; | ||
static readonly SINGLE = 262; | ||
static readonly SKIPROWS = 263; | ||
static readonly START = 264; | ||
static readonly STARTS = 265; | ||
static readonly STATUS = 266; | ||
static readonly STOP = 267; | ||
static readonly STRING = 268; | ||
static readonly SUPPORTED = 269; | ||
static readonly SUSPENDED = 270; | ||
static readonly TARGET = 271; | ||
static readonly TERMINATE = 272; | ||
static readonly TEXT = 273; | ||
static readonly THEN = 274; | ||
static readonly TIME = 275; | ||
static readonly TIMES = 276; | ||
static readonly TIMESTAMP = 277; | ||
static readonly TIMEZONE = 278; | ||
static readonly TO = 279; | ||
static readonly TOPOLOGY = 280; | ||
static readonly TRAILING = 281; | ||
static readonly TRANSACTION = 282; | ||
static readonly TRANSACTIONS = 283; | ||
static readonly TRAVERSE = 284; | ||
static readonly TRIM = 285; | ||
static readonly TRUE = 286; | ||
static readonly TYPE = 287; | ||
static readonly TYPED = 288; | ||
static readonly TYPES = 289; | ||
static readonly UNION = 290; | ||
static readonly UNIQUE = 291; | ||
static readonly UNIQUENESS = 292; | ||
static readonly UNWIND = 293; | ||
static readonly URL = 294; | ||
static readonly USE = 295; | ||
static readonly USER = 296; | ||
static readonly USERS = 297; | ||
static readonly USING = 298; | ||
static readonly VALUE = 299; | ||
static readonly VARCHAR = 300; | ||
static readonly VECTOR = 301; | ||
static readonly VERBOSE = 302; | ||
static readonly VERTEX = 303; | ||
static readonly WAIT = 304; | ||
static readonly WHEN = 305; | ||
static readonly WHERE = 306; | ||
static readonly WITH = 307; | ||
static readonly WITHOUT = 308; | ||
static readonly WRITE = 309; | ||
static readonly XOR = 310; | ||
static readonly YIELD = 311; | ||
static readonly ZONE = 312; | ||
static readonly ZONED = 313; | ||
static readonly IDENTIFIER = 314; | ||
static readonly ARROW_LINE = 315; | ||
static readonly ARROW_LEFT_HEAD = 316; | ||
static readonly ARROW_RIGHT_HEAD = 317; | ||
static readonly ErrorChar = 318; | ||
static readonly EOF: number; | ||
@@ -319,0 +323,0 @@ static readonly channelNames: string[]; |
@@ -7,3 +7,3 @@ export type { ParserRuleContext } from 'antlr4'; | ||
export { CypherTokenType, lexerSymbols } from './lexerSymbols'; | ||
export { parse, parserWrapper } from './parserWrapper'; | ||
export { parse, parserWrapper, parseStatementsStrs } from './parserWrapper'; | ||
export { signatureHelp, toSignatureInformation } from './signatureHelp'; | ||
@@ -10,0 +10,0 @@ export { applySyntaxColouring, mapCypherToSemanticTokenIndex, syntaxColouringLegend, } from './syntaxColouring/syntaxColouring'; |
@@ -9,3 +9,3 @@ import type { ParserRuleContext, Token } from 'antlr4'; | ||
ctx: StatementsOrCommandsContext; | ||
diagnostics: SyntaxDiagnostic[]; | ||
syntaxErrors: SyntaxDiagnostic[]; | ||
stopNode: ParserRuleContext; | ||
@@ -15,2 +15,3 @@ collectedLabelOrRelTypes: LabelOrRelType[]; | ||
collectedFunctions: ParsedFunction[]; | ||
collectedProcedures: ParsedProcedure[]; | ||
} | ||
@@ -46,3 +47,3 @@ export interface ParsingResult { | ||
export type ParsedFunction = { | ||
parsedName: string; | ||
name: string; | ||
rawText: string; | ||
@@ -56,3 +57,5 @@ line: number; | ||
}; | ||
export type ParsedProcedure = ParsedFunction; | ||
export declare function createParsingScaffolding(query: string): ParsingScaffolding; | ||
export declare function parseStatementsStrs(query: string): string[]; | ||
export declare function parse(query: string): StatementOrCommandContext[]; | ||
@@ -59,0 +62,0 @@ export declare function createParsingResult(query: string): ParsingResult; |
@@ -21,3 +21,3 @@ { | ||
], | ||
"version": "2.0.0-canary-0d0dce4", | ||
"version": "2.0.0-canary-0d4fb85", | ||
"main": "./dist/cjs/index.cjs", | ||
@@ -59,9 +59,8 @@ "module": "./dist/esm/index.mjs", | ||
"clean": "rm -rf {dist,src/generated-parser}", | ||
"test": "jest" | ||
"test": "vitest run" | ||
}, | ||
"devDependencies": { | ||
"@types/benchmark": "^2.1.5", | ||
"@types/jest": "^29.5.5", | ||
"benchmark": "^2.1.4" | ||
} | ||
} |
@@ -7,3 +7,3 @@ export type { ParserRuleContext } from 'antlr4'; | ||
export { CypherTokenType, lexerSymbols } from './lexerSymbols'; | ||
export { parse, parserWrapper } from './parserWrapper'; | ||
export { parse, parserWrapper, parseStatementsStrs } from './parserWrapper'; | ||
export { signatureHelp, toSignatureInformation } from './signatureHelp'; | ||
@@ -10,0 +10,0 @@ export { |
@@ -130,2 +130,3 @@ import CypherLexer from './generated-parser/CypherCmdLexer'; | ||
CypherLexer.CALL, | ||
CypherLexer.CASCADE, | ||
CypherLexer.CASE, | ||
@@ -250,2 +251,3 @@ CypherLexer.CIDR, | ||
CypherLexer.OF, | ||
CypherLexer.OFFSET, | ||
CypherLexer.ON, | ||
@@ -291,2 +293,3 @@ CypherLexer.ONLY, | ||
CypherLexer.REQUIRED, | ||
CypherLexer.RESTRICT, | ||
CypherLexer.RETURN, | ||
@@ -363,2 +366,3 @@ CypherLexer.REVOKE, | ||
CypherLexer.YIELD, | ||
CypherLexer.ZONE, | ||
CypherLexer.ZONED, | ||
@@ -365,0 +369,0 @@ // Preparser tokens |
@@ -15,2 +15,3 @@ import type { ParserRuleContext, Token } from 'antlr4'; | ||
LabelOrRelTypeContext, | ||
ProcedureNameContext, | ||
StatementOrCommandContext, | ||
@@ -24,2 +25,3 @@ StatementsOrCommandsContext, | ||
findStopNode, | ||
getTokens, | ||
inNodeLabel, | ||
@@ -43,3 +45,3 @@ inRelationshipType, | ||
ctx: StatementsOrCommandsContext; | ||
diagnostics: SyntaxDiagnostic[]; | ||
syntaxErrors: SyntaxDiagnostic[]; | ||
stopNode: ParserRuleContext; | ||
@@ -49,2 +51,3 @@ collectedLabelOrRelTypes: LabelOrRelType[]; | ||
collectedFunctions: ParsedFunction[]; | ||
collectedProcedures: ParsedProcedure[]; | ||
} | ||
@@ -103,3 +106,3 @@ | ||
export type ParsedFunction = { | ||
parsedName: string; | ||
name: string; | ||
rawText: string; | ||
@@ -113,2 +116,3 @@ line: number; | ||
}; | ||
export type ParsedProcedure = ParsedFunction; | ||
@@ -139,2 +143,24 @@ export function createParsingScaffolding(query: string): ParsingScaffolding { | ||
export function parseStatementsStrs(query: string): string[] { | ||
const statements = parse(query); | ||
const result: string[] = []; | ||
for (const statement of statements) { | ||
const tokenStream = statement.parser?.getTokenStream() ?? []; | ||
const tokens = getTokens(tokenStream as CommonTokenStream); | ||
const statementStr = tokens | ||
.filter((token) => token.type !== CypherLexer.EOF) | ||
.map((token) => token.text) | ||
.join(''); | ||
// Do not return empty statements | ||
if (statementStr.trimLeft().length != 0) { | ||
result.push(statementStr); | ||
} | ||
} | ||
return result; | ||
} | ||
/* Parses a query without storing it in the cache */ | ||
export function parse(query: string): StatementOrCommandContext[] { | ||
@@ -158,9 +184,5 @@ const statementScaffolding = | ||
const variableFinder = new VariableCollector(); | ||
const functionFinder = new FunctionCollector(tokens); | ||
const methodsFinder = new MethodsCollector(tokens); | ||
const errorListener = new SyntaxErrorsListener(tokens); | ||
parser._parseListeners = [ | ||
labelsCollector, | ||
variableFinder, | ||
functionFinder, | ||
]; | ||
parser._parseListeners = [labelsCollector, variableFinder, methodsFinder]; | ||
parser.addErrorListener(errorListener); | ||
@@ -173,7 +195,7 @@ const ctx = parser.statementsOrCommands(); | ||
) === undefined; | ||
const diagnostics = isEmptyStatement ? [] : errorListener.errors; | ||
const syntaxErrors = isEmptyStatement ? [] : errorListener.errors; | ||
const collectedCommand = parseToCommand(ctx, isEmptyStatement); | ||
if (!_internalFeatureFlags.consoleCommands) { | ||
diagnostics.push(...errorOnNonCypherCommands(collectedCommand)); | ||
syntaxErrors.push(...errorOnNonCypherCommands(collectedCommand)); | ||
} | ||
@@ -185,3 +207,3 @@ | ||
tokens: tokens, | ||
diagnostics: diagnostics, | ||
syntaxErrors: syntaxErrors, | ||
ctx: ctx, | ||
@@ -191,3 +213,4 @@ stopNode: findStopNode(ctx), | ||
collectedVariables: variableFinder.variables, | ||
collectedFunctions: functionFinder.functions, | ||
collectedFunctions: methodsFinder.functions, | ||
collectedProcedures: methodsFinder.procedures, | ||
}; | ||
@@ -301,4 +324,5 @@ }); | ||
// This listener collects all functions | ||
class FunctionCollector extends ParseTreeListener { | ||
// This listener collects all functions and procedures | ||
class MethodsCollector extends ParseTreeListener { | ||
public procedures: ParsedProcedure[] = []; | ||
public functions: ParsedFunction[] = []; | ||
@@ -323,4 +347,7 @@ private tokens: Token[]; | ||
exitEveryRule(ctx: unknown) { | ||
if (ctx instanceof FunctionNameContext) { | ||
const functionName = this.getNormalizedFunctionName(ctx); | ||
if ( | ||
ctx instanceof FunctionNameContext || | ||
ctx instanceof ProcedureNameContext | ||
) { | ||
const methodName = this.getMethodName(ctx); | ||
@@ -337,4 +364,4 @@ const startTokenIndex = ctx.start.tokenIndex; | ||
this.functions.push({ | ||
parsedName: functionName, | ||
const result = { | ||
name: methodName, | ||
rawText: rawText, | ||
@@ -347,13 +374,21 @@ line: ctx.start.line, | ||
}, | ||
}); | ||
}; | ||
if (ctx instanceof FunctionNameContext) { | ||
this.functions.push(result); | ||
} else { | ||
this.procedures.push(result); | ||
} | ||
} | ||
} | ||
private getNormalizedFunctionName(ctx: FunctionNameContext): string { | ||
private getMethodName( | ||
ctx: ProcedureNameContext | FunctionNameContext, | ||
): string { | ||
const namespaces = ctx.namespace().symbolicNameString_list(); | ||
const functionName = ctx.symbolicNameString(); | ||
const methodName = ctx.symbolicNameString(); | ||
const normalizedName = [...namespaces, functionName] | ||
const normalizedName = [...namespaces, methodName] | ||
.map((symbolicName) => { | ||
return this.getFunctionNamespaceString(symbolicName); | ||
return this.getNamespaceString(symbolicName); | ||
}) | ||
@@ -365,3 +400,3 @@ .join('.'); | ||
private getFunctionNamespaceString(ctx: SymbolicNameStringContext): string { | ||
private getNamespaceString(ctx: SymbolicNameStringContext): string { | ||
const text = ctx.getText(); | ||
@@ -368,0 +403,0 @@ const isEscaped = Boolean(ctx.escapedSymbolicNameString()); |
@@ -37,8 +37,6 @@ /* eslint-disable @typescript-eslint/no-unsafe-call */ | ||
if (dbSchema.functions && dbSchema.procedures) { | ||
updateSignatureResolver({ | ||
procedures: Object.values(dbSchema.procedures), | ||
functions: Object.values(dbSchema.functions), | ||
}); | ||
} | ||
updateSignatureResolver({ | ||
procedures: Object.values(dbSchema.procedures ?? {}), | ||
functions: Object.values(dbSchema.functions ?? {}), | ||
}); | ||
semanticAnalysis([query], (a) => { | ||
@@ -45,0 +43,0 @@ semanticErrorsResult = a; |
@@ -9,2 +9,3 @@ import { DiagnosticSeverity, Position } from 'vscode-languageserver-types'; | ||
ParsedFunction, | ||
ParsedProcedure, | ||
ParsedStatement, | ||
@@ -67,3 +68,3 @@ parserWrapper, | ||
): SyntaxDiagnostic | undefined { | ||
const lowercaseFunctionName = parsedFunction.parsedName.toLowerCase(); | ||
const lowercaseFunctionName = parsedFunction.name.toLowerCase(); | ||
const caseInsensitiveFunctionInDatabase = | ||
@@ -81,10 +82,10 @@ functionsSchema[lowercaseFunctionName]; | ||
const functionExistsWithExactName = Boolean( | ||
functionsSchema[parsedFunction.parsedName], | ||
functionsSchema[parsedFunction.name], | ||
); | ||
if (!functionExistsWithExactName) { | ||
return generateFunctionNotFoundWarning(parsedFunction); | ||
return generateFunctionNotFoundError(parsedFunction); | ||
} | ||
} | ||
function generateFunctionNotFoundWarning( | ||
function generateFunctionNotFoundError( | ||
parsedFunction: ParsedFunction, | ||
@@ -102,4 +103,4 @@ ): SyntaxDiagnostic { | ||
const warning: SyntaxDiagnostic = { | ||
severity: DiagnosticSeverity.Warning, | ||
const error: SyntaxDiagnostic = { | ||
severity: DiagnosticSeverity.Error, | ||
range: { | ||
@@ -110,8 +111,34 @@ start: Position.create(lineIndex, startColumn), | ||
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`, | ||
message: `Function ${parsedFunction.name} 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; | ||
return error; | ||
} | ||
function generateProcedureNotFoundError( | ||
parsedProcedure: ParsedProcedure, | ||
): SyntaxDiagnostic { | ||
const rawText = parsedProcedure.rawText; | ||
const nameChunks = rawText.split('\n'); | ||
const linesOffset = nameChunks.length - 1; | ||
const lineIndex = parsedProcedure.line - 1; | ||
const startColumn = parsedProcedure.column; | ||
const endColumn = | ||
linesOffset == 0 | ||
? startColumn + rawText.length | ||
: nameChunks.at(-1)?.length ?? 0; | ||
const error: SyntaxDiagnostic = { | ||
severity: DiagnosticSeverity.Error, | ||
range: { | ||
start: Position.create(lineIndex, startColumn), | ||
end: Position.create(lineIndex + linesOffset, endColumn), | ||
}, | ||
offsets: parsedProcedure.offsets, | ||
message: `Procedure ${parsedProcedure.name} 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 error; | ||
} | ||
function warnOnUndeclaredLabels( | ||
@@ -234,3 +261,4 @@ parsingResult: ParsedStatement, | ||
const syntaxErrors = validateSyntax(query, dbSchema); | ||
if (syntaxErrors.length > 0) { | ||
// If there are any syntactic errors in the query, do not run the semantic validation | ||
if (syntaxErrors.find((d) => d.severity === DiagnosticSeverity.Error)) { | ||
return syntaxErrors; | ||
@@ -240,3 +268,3 @@ } | ||
const semanticErrors = validateSemantics(query, dbSchema); | ||
return semanticErrors; | ||
return syntaxErrors.concat(semanticErrors); | ||
} | ||
@@ -253,9 +281,5 @@ | ||
const result = statements.statementsParsing.flatMap((statement) => { | ||
const diagnostics = statement.diagnostics; | ||
const syntaxErrors = statement.syntaxErrors; | ||
const labelWarnings = warnOnUndeclaredLabels(statement, dbSchema); | ||
const functionWarnings = warnOnUndeclaredFunctions(statement, dbSchema); | ||
return diagnostics | ||
.concat(labelWarnings, functionWarnings) | ||
.sort(sortByPositionAndMessage); | ||
return syntaxErrors.concat(labelWarnings).sort(sortByPositionAndMessage); | ||
}); | ||
@@ -277,5 +301,11 @@ | ||
const semanticErrors = statements.flatMap((current) => { | ||
if (current.diagnostics.length === 0) { | ||
if (current.syntaxErrors.length === 0) { | ||
const cmd = current.command; | ||
if (cmd.type === 'cypher' && cmd.statement.length > 0) { | ||
const functionErrors = errorOnUndeclaredFunctions(current, dbSchema); | ||
const procedureErrors = errorOnUndeclaredProcedures( | ||
current, | ||
dbSchema, | ||
); | ||
const { notifications, errors } = wrappedSemanticAnalysis( | ||
@@ -287,7 +317,9 @@ cmd.statement, | ||
const elements = notifications.concat(errors); | ||
const result = fixSemanticAnalysisPositions({ | ||
const semanticDiagnostics = fixSemanticAnalysisPositions({ | ||
semanticElements: elements, | ||
parseResult: current, | ||
}).sort(sortByPositionAndMessage); | ||
return result; | ||
}); | ||
return semanticDiagnostics | ||
.concat(functionErrors, procedureErrors) | ||
.sort(sortByPositionAndMessage); | ||
} | ||
@@ -304,3 +336,3 @@ } | ||
function warnOnUndeclaredFunctions( | ||
function errorOnUndeclaredFunctions( | ||
parsingResult: ParsedStatement, | ||
@@ -326,1 +358,23 @@ dbSchema: DbSchema, | ||
} | ||
function errorOnUndeclaredProcedures( | ||
parsingResult: ParsedStatement, | ||
dbSchema: DbSchema, | ||
): SyntaxDiagnostic[] { | ||
const errors: SyntaxDiagnostic[] = []; | ||
if (dbSchema.procedures) { | ||
const proceduresInQuery = parsingResult.collectedProcedures; | ||
proceduresInQuery.forEach((parsedProcedure) => { | ||
const procedureExists = Boolean( | ||
dbSchema.procedures[parsedProcedure.name], | ||
); | ||
if (!procedureExists) { | ||
errors.push(generateProcedureNotFoundError(parsedProcedure)); | ||
} | ||
}); | ||
} | ||
return errors; | ||
} |
@@ -13,3 +13,3 @@ import { | ||
} from 'vscode-languageserver-types'; | ||
import { CypherLexer } from '..'; | ||
import CypherLexer from '../generated-parser/CypherCmdLexer'; | ||
import CypherParser from '../generated-parser/CypherCmdParser'; | ||
@@ -16,0 +16,0 @@ import { isCommentOpener } from '../helpers'; |
@@ -62,3 +62,3 @@ import { autocomplete } from '../../autocompletion/autocompletion'; | ||
const unexpectedCompletions = excluded.map((notExpectedItem) => | ||
const unexpectedCompletions = excluded.filter((notExpectedItem) => | ||
actualCompletionList.find((value) => { | ||
@@ -65,0 +65,0 @@ // if label is left out -> only check kind and vice versa |
@@ -49,11 +49,2 @@ import { CompletionItemKind } from 'vscode-languageserver-types'; | ||
describe('Auto completion of back to back keywords', () => { | ||
test('Correctly completes OPTIONAL MATCH', () => { | ||
const query = 'OP'; | ||
testCompletions({ | ||
query, | ||
expected: [{ label: 'OPTIONAL MATCH', kind: CompletionItemKind.Keyword }], | ||
}); | ||
}); | ||
test('Correctly completes DEFAULT DATABASE and HOME DATABASE', () => { | ||
@@ -60,0 +51,0 @@ const query = 'SHOW '; |
@@ -14,8 +14,11 @@ import { CompletionItemKind } from 'vscode-languageserver-types'; | ||
test('Correctly completes OPTIONAL MATCH', () => { | ||
const query = 'OP'; | ||
test('Correctly completes OPTIONAL MATCH and OPTIONAL CALL', () => { | ||
const query = 'OPTIONAL '; | ||
testCompletions({ | ||
query, | ||
expected: [{ label: 'OPTIONAL MATCH', kind: CompletionItemKind.Keyword }], | ||
expected: [ | ||
{ label: 'MATCH', kind: CompletionItemKind.Keyword }, | ||
{ label: 'CALL', kind: CompletionItemKind.Keyword }, | ||
], | ||
}); | ||
@@ -78,3 +81,3 @@ }); | ||
test.only('Correctly completes unstarted label when caret is passed and there is a space', () => { | ||
test('Correctly completes unstarted label when caret is passed and there is a space', () => { | ||
const query = 'MATCH (n : '; | ||
@@ -81,0 +84,0 @@ |
@@ -13,3 +13,3 @@ import { autocomplete } from '../autocompletion/autocompletion'; | ||
expect( | ||
result.statementsParsing.flatMap((statement) => statement.diagnostics), | ||
result.statementsParsing.flatMap((statement) => statement.syntaxErrors), | ||
).toEqual([]); | ||
@@ -34,3 +34,3 @@ expect( | ||
result.statementsParsing | ||
.flatMap((statement) => statement.diagnostics) | ||
.flatMap((statement) => statement.syntaxErrors) | ||
.map((e) => e.message), | ||
@@ -37,0 +37,0 @@ ).toContain(msg); |
@@ -116,2 +116,21 @@ import { _internalFeatureFlags } from '../../featureFlags'; | ||
message: | ||
'CALL subquery without a variable scope clause is now deprecated. Use CALL () { ... }', | ||
offsets: { | ||
end: 100, | ||
start: 26, | ||
}, | ||
range: { | ||
end: { | ||
character: 5, | ||
line: 5, | ||
}, | ||
start: { | ||
character: 4, | ||
line: 2, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
{ | ||
message: | ||
'Variable in subquery is shadowing a variable with the same name from the outer scope. If you want to use that variable instead, it must be imported into the subquery using importing WITH clause. (the shadowing variable is: shadowed)', | ||
@@ -138,3 +157,3 @@ offsets: { | ||
test('Accumulates several semantic errors', () => { | ||
const query = `CALL { MATCH (n) RETURN m} IN TRANSACTIONS OF -1 ROWS`; | ||
const query = `CALL () { MATCH (n) RETURN m} IN TRANSACTIONS OF -1 ROWS`; | ||
@@ -146,3 +165,3 @@ expect(getDiagnosticsForQuery({ query })).toEqual([ | ||
offsets: { | ||
end: 53, | ||
end: 56, | ||
start: 0, | ||
@@ -152,3 +171,3 @@ }, | ||
end: { | ||
character: 53, | ||
character: 56, | ||
line: 0, | ||
@@ -166,12 +185,12 @@ }, | ||
offsets: { | ||
end: 25, | ||
start: 24, | ||
end: 28, | ||
start: 27, | ||
}, | ||
range: { | ||
end: { | ||
character: 25, | ||
character: 28, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 24, | ||
character: 27, | ||
line: 0, | ||
@@ -186,12 +205,12 @@ }, | ||
offsets: { | ||
end: 48, | ||
start: 46, | ||
end: 51, | ||
start: 49, | ||
}, | ||
range: { | ||
end: { | ||
character: 48, | ||
character: 51, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 46, | ||
character: 49, | ||
line: 0, | ||
@@ -206,6 +225,6 @@ }, | ||
test('Shows errors for CALL IN TXs used in UNION', () => { | ||
const query = `CALL { CREATE (x) } IN TRANSACTIONS | ||
const query = `CALL () { CREATE (x) } IN TRANSACTIONS | ||
RETURN 1 AS result | ||
UNION | ||
CALL { CREATE (x) } IN TRANSACTIONS | ||
CALL () { CREATE (x) } IN TRANSACTIONS | ||
RETURN 2 AS result`; | ||
@@ -217,3 +236,3 @@ | ||
offsets: { | ||
end: 139, | ||
end: 145, | ||
start: 0, | ||
@@ -236,4 +255,4 @@ }, | ||
offsets: { | ||
end: 139, | ||
start: 79, | ||
end: 145, | ||
start: 82, | ||
}, | ||
@@ -257,3 +276,3 @@ range: { | ||
const query = `WITH 1 AS i | ||
CALL { | ||
CALL () { | ||
WITH 2 AS i | ||
@@ -269,25 +288,6 @@ RETURN * | ||
{ | ||
message: | ||
'Variable in subquery is shadowing a variable with the same name from the outer scope. If you want to use that variable instead, it must be imported into the subquery using importing WITH clause. (the shadowing variable is: i)', | ||
offsets: { | ||
end: 44, | ||
start: 43, | ||
}, | ||
range: { | ||
end: { | ||
character: 19, | ||
line: 2, | ||
}, | ||
start: { | ||
character: 18, | ||
line: 2, | ||
}, | ||
}, | ||
severity: 2, | ||
}, | ||
{ | ||
message: 'Variable `i` already declared in outer scope', | ||
offsets: { | ||
end: 61, | ||
start: 53, | ||
end: 64, | ||
start: 56, | ||
}, | ||
@@ -309,4 +309,4 @@ range: { | ||
offsets: { | ||
end: 61, | ||
start: 60, | ||
end: 64, | ||
start: 63, | ||
}, | ||
@@ -326,19 +326,18 @@ range: { | ||
{ | ||
message: | ||
'Variable in subquery is shadowing a variable with the same name from the outer scope. If you want to use that variable instead, it must be imported into the subquery using importing WITH clause. (the shadowing variable is: i)', | ||
message: 'Variable `i` already declared', | ||
offsets: { | ||
end: 97, | ||
start: 96, | ||
end: 117, | ||
start: 75, | ||
}, | ||
range: { | ||
end: { | ||
character: 19, | ||
line: 5, | ||
character: 16, | ||
line: 6, | ||
}, | ||
start: { | ||
character: 18, | ||
line: 5, | ||
character: 10, | ||
line: 4, | ||
}, | ||
}, | ||
severity: 2, | ||
severity: 1, | ||
}, | ||
@@ -348,4 +347,4 @@ { | ||
offsets: { | ||
end: 114, | ||
start: 106, | ||
end: 117, | ||
start: 109, | ||
}, | ||
@@ -367,4 +366,4 @@ range: { | ||
offsets: { | ||
end: 114, | ||
start: 113, | ||
end: 117, | ||
start: 116, | ||
}, | ||
@@ -387,3 +386,3 @@ range: { | ||
test('Shows errors for subquery with only WITH', () => { | ||
const query = 'WITH 1 AS a CALL { WITH a } RETURN a'; | ||
const query = 'WITH 1 AS a CALL (a) { WITH a } RETURN a'; | ||
@@ -393,14 +392,14 @@ expect(getDiagnosticsForQuery({ query })).toEqual([ | ||
message: | ||
'Query must conclude with a RETURN clause, a FINISH clause, an update clause, a unit subquery call, or a procedure call with no YIELD.', | ||
'Query cannot conclude with WITH (must be a RETURN clause, a FINISH clause, an update clause, a unit subquery call, or a procedure call with no YIELD).', | ||
offsets: { | ||
end: 25, | ||
start: 19, | ||
end: 29, | ||
start: 23, | ||
}, | ||
range: { | ||
end: { | ||
character: 25, | ||
character: 29, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 19, | ||
character: 23, | ||
line: 0, | ||
@@ -417,3 +416,3 @@ }, | ||
WITH 1 AS a | ||
CALL { | ||
CALL () { | ||
USE x | ||
@@ -430,3 +429,3 @@ RETURN 2 AS b | ||
WITH 1 AS a | ||
CALL { | ||
CALL () { | ||
USE other | ||
@@ -442,4 +441,4 @@ RETURN 2 AS b | ||
offsets: { | ||
end: 88, | ||
start: 55, | ||
end: 91, | ||
start: 58, | ||
}, | ||
@@ -665,4 +664,3 @@ range: { | ||
UNWIND [0, 1, 2] AS x | ||
CALL { | ||
WITH x | ||
CALL (x) { | ||
RETURN x * 10 AS y | ||
@@ -678,4 +676,4 @@ } | ||
offsets: { | ||
end: 137, | ||
start: 136, | ||
end: 120, | ||
start: 119, | ||
}, | ||
@@ -685,7 +683,7 @@ range: { | ||
character: 32, | ||
line: 5, | ||
line: 4, | ||
}, | ||
start: { | ||
character: 31, | ||
line: 5, | ||
line: 4, | ||
}, | ||
@@ -771,14 +769,15 @@ }, | ||
{ | ||
message: 'Path selectors such as `ANY 2 PATHS` are not supported yet', | ||
message: | ||
'Multiple path patterns cannot be used in the same clause in combination with a selective path selector.', | ||
offsets: { | ||
end: 32, | ||
start: 21, | ||
end: 82, | ||
start: 16, | ||
}, | ||
range: { | ||
end: { | ||
character: 26, | ||
line: 1, | ||
character: 31, | ||
line: 2, | ||
}, | ||
start: { | ||
character: 15, | ||
character: 10, | ||
line: 1, | ||
@@ -916,4 +915,3 @@ }, | ||
{ | ||
message: | ||
'Type mismatch: p defined with conflicting type List<T> (expected Path)', | ||
message: 'Variable `p` already declared', | ||
offsets: { | ||
@@ -1202,3 +1200,3 @@ end: 35, | ||
message: | ||
'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.', | ||
'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 {}.', | ||
offsets: { | ||
@@ -1451,6 +1449,9 @@ end: 29, | ||
test('Does not provide semantic validation for pluggeable functions when schema is not available', () => { | ||
test('Does not error on SHORTEST k', () => { | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query: `RETURN apoc.coll.sum(['a', 'b'])`, | ||
query: `MATCH p = SHORTEST 2 (a)-[]-+(b) | ||
WHERE a.name = "foo" AND b.name = "bar" | ||
RETURN [n in nodes(p) | n.name] AS stops;`, | ||
dbSchema: testData.mockSchema, | ||
}), | ||
@@ -1460,147 +1461,17 @@ ).toEqual([]); | ||
test('Provides semantic validation for built-in functions', () => { | ||
test('Does not error on dynamic labels', () => { | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query: `WITH character_length() AS a | ||
WITH character_length(1) AS b, a | ||
RETURN a,b`, | ||
}), | ||
).toEqual([ | ||
{ | ||
message: "Insufficient parameters for function 'character_length'", | ||
offsets: { | ||
end: 28, | ||
start: 5, | ||
}, | ||
range: { | ||
end: { | ||
character: 28, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 5, | ||
line: 0, | ||
}, | ||
}, | ||
severity: 1, | ||
}, | ||
{ | ||
message: 'Type mismatch: expected String but was Integer', | ||
offsets: { | ||
end: 60, | ||
start: 59, | ||
}, | ||
range: { | ||
end: { | ||
character: 31, | ||
line: 1, | ||
}, | ||
start: { | ||
character: 30, | ||
line: 1, | ||
}, | ||
}, | ||
severity: 1, | ||
}, | ||
]); | ||
}); | ||
test('Provides semantic validation for procedures when a schema is available', () => { | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query: ` | ||
CALL db.awaitIndex('index', 'time') | ||
CALL db.awaitIndex() | ||
`, | ||
query: `MATCH (n) | ||
SET n:$("label")`, | ||
dbSchema: testData.mockSchema, | ||
}), | ||
).toEqual([ | ||
{ | ||
message: 'Type mismatch: expected Integer but was String', | ||
offsets: { | ||
end: 43, | ||
start: 37, | ||
}, | ||
range: { | ||
end: { | ||
character: 42, | ||
line: 1, | ||
}, | ||
start: { | ||
character: 36, | ||
line: 1, | ||
}, | ||
}, | ||
severity: 1, | ||
}, | ||
{ | ||
message: `Procedure call does not provide the required number of arguments: got 0 expected at least 1 (total: 2, 1 of which have default values). | ||
Procedure db.awaitIndex has signature: db.awaitIndex(indexName :: STRING, timeOutSeconds = 300 :: INTEGER) :: | ||
meaning that it expects at least 1 argument of type STRING | ||
`, | ||
offsets: { | ||
end: 73, | ||
start: 53, | ||
}, | ||
range: { | ||
end: { | ||
character: 28, | ||
line: 2, | ||
}, | ||
start: { | ||
character: 8, | ||
line: 2, | ||
}, | ||
}, | ||
severity: 1, | ||
}, | ||
]); | ||
}); | ||
test('Shows default values correctly for external procedures', () => { | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query: 'CALL apoc.load.xml()', | ||
dbSchema: testData.mockSchema, | ||
}), | ||
).toEqual([ | ||
{ | ||
message: `Procedure call does not provide the required number of arguments: got 0 expected at least 1 (total: 4, 3 of which have default values). | ||
Procedure apoc.load.xml has signature: apoc.load.xml(urlOrBinary :: ANY, path = / :: STRING, config = {} :: MAP, simple = false :: BOOLEAN) :: value :: MAP | ||
meaning that it expects at least 1 argument of type ANY | ||
`, | ||
offsets: { | ||
end: 20, | ||
start: 0, | ||
}, | ||
range: { | ||
end: { | ||
character: 20, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 0, | ||
line: 0, | ||
}, | ||
}, | ||
severity: 1, | ||
}, | ||
]); | ||
}); | ||
test('Does not fail if default arguments for procedure not provided', () => { | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query: `CALL apoc.load.xml('url', '/path')`, | ||
dbSchema: testData.mockSchema, | ||
}), | ||
).toEqual([]); | ||
}); | ||
test('Does not fail semantic validation for functions that expect LIST<ANY>', () => { | ||
test('Does not error on dynamic properties', () => { | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query: `RETURN apoc.coll.max(['a'])`, | ||
query: `MATCH (n) | ||
SET n["prop"] = "some value"`, | ||
dbSchema: testData.mockSchema, | ||
@@ -1611,6 +1482,6 @@ }), | ||
test('Provides semantic validation for functions that expect LIST<NUMBER>', () => { | ||
test('Shows deprecation for CALL IN TXs without parentheses', () => { | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query: `RETURN apoc.coll.sum(['a', 'b'])`, | ||
query: `CALL { MATCH (n) RETURN n} IN TRANSACTIONS OF 50 ROWS RETURN 1`, | ||
dbSchema: testData.mockSchema, | ||
@@ -1621,18 +1492,18 @@ }), | ||
message: | ||
'Type mismatch: expected List<Float>, List<Integer> or List<Number> but was List<String>', | ||
'CALL subquery without a variable scope clause is now deprecated. Use CALL () { ... }', | ||
offsets: { | ||
end: 31, | ||
start: 21, | ||
end: 62, | ||
start: 0, | ||
}, | ||
range: { | ||
end: { | ||
character: 31, | ||
character: 62, | ||
line: 0, | ||
}, | ||
start: { | ||
character: 21, | ||
character: 0, | ||
line: 0, | ||
}, | ||
}, | ||
severity: 1, | ||
severity: 2, | ||
}, | ||
@@ -1642,52 +1513,12 @@ ]); | ||
// TODO This doesn't seem to warn on deprecated | ||
// arguments for either functions or procedures, | ||
// needs to be solved in the database first | ||
test('Notifies of deprecated returns in procedures', () => { | ||
test('Shows deprecation for CALL without parentheses', () => { | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query: `CALL apoc.meta.graphSample({})`, | ||
dbSchema: { | ||
functions: {}, | ||
procedures: { | ||
'apoc.meta.graphSample': { | ||
name: 'apoc.meta.graphSample', | ||
description: | ||
'Examines the full graph and returns a meta-graph.\nUnlike `apoc.meta.graph`, this procedure does not filter away non-existing paths.', | ||
mode: 'DEFAULT', | ||
worksOnSystem: false, | ||
argumentDescription: [ | ||
{ | ||
isDeprecated: false, | ||
default: 'DefaultParameterValue{value={}, type=MAP}', | ||
description: 'config = {} :: MAP', | ||
name: 'config', | ||
type: 'MAP', | ||
}, | ||
], | ||
signature: | ||
'apoc.meta.graphSample(config = {} :: MAP) :: (nodes :: LIST<NODE>, relationships :: LIST<RELATIONSHIP>)', | ||
returnDescription: [ | ||
{ | ||
isDeprecated: true, | ||
description: 'nodes :: LIST<NODE>', | ||
name: 'nodes', | ||
type: 'LIST<NODE>', | ||
}, | ||
{ | ||
isDeprecated: false, | ||
description: 'relationships :: LIST<RELATIONSHIP>', | ||
name: 'relationships', | ||
type: 'LIST<RELATIONSHIP>', | ||
}, | ||
], | ||
admin: false, | ||
option: { | ||
deprecated: false, | ||
}, | ||
}, | ||
}, | ||
}, | ||
query: `WITH 1 AS i | ||
CALL { | ||
RETURN 3 AS j | ||
} | ||
RETURN i | ||
`, | ||
dbSchema: testData.mockSchema, | ||
}), | ||
@@ -1697,15 +1528,15 @@ ).toEqual([ | ||
message: | ||
"The query used a deprecated field from a procedure. ('nodes' returned by 'apoc.meta.graphSample' is deprecated.)", | ||
'CALL subquery without a variable scope clause is now deprecated. Use CALL () { ... }', | ||
offsets: { | ||
end: 30, | ||
start: 0, | ||
end: 67, | ||
start: 22, | ||
}, | ||
range: { | ||
end: { | ||
character: 30, | ||
line: 0, | ||
character: 11, | ||
line: 3, | ||
}, | ||
start: { | ||
character: 0, | ||
line: 0, | ||
character: 10, | ||
line: 1, | ||
}, | ||
@@ -1712,0 +1543,0 @@ }, |
@@ -1,2 +0,1 @@ | ||
import { testData } from '../testData'; | ||
import { getDiagnosticsForQuery } from './helpers'; | ||
@@ -40,3 +39,3 @@ | ||
message: | ||
'Expected any of ALTER, CALL, CREATE, DEALLOCATE, DELETE, DENY, DETACH, DROP, DRYRUN, ENABLE, EXPLAIN, FINISH, FOREACH, GRANT, INSERT, LOAD, MATCH, MERGE, NODETACH, OPTIONAL, PROFILE, REALLOCATE, REMOVE, RENAME, RETURN, REVOKE, SET, SHOW, START, STOP, TERMINATE, UNWIND, USE, USING or WITH', | ||
'Expected any of ALTER, CALL, CREATE, DEALLOCATE, DELETE, DENY, DETACH, DROP, DRYRUN, ENABLE, EXPLAIN, FINISH, FOREACH, GRANT, INSERT, LIMIT, LOAD, MATCH, MERGE, NODETACH, OFFSET, OPTIONAL, ORDER, PROFILE, REALLOCATE, REMOVE, RENAME, RETURN, REVOKE, SET, SHOW, SKIP, START, STOP, TERMINATE, UNWIND, USE, USING or WITH', | ||
range: { | ||
@@ -121,3 +120,3 @@ end: { | ||
message: | ||
"Expected any of '}', AND, CALL, CREATE, DELETE, DETACH, FINISH, FOREACH, INSERT, LOAD, MATCH, MERGE, NODETACH, OPTIONAL, OR, REMOVE, RETURN, SET, UNION, UNWIND, USE, WITH, XOR or an expression", | ||
"Expected any of '}', AND, CALL, CREATE, DELETE, DETACH, FINISH, FOREACH, INSERT, LIMIT, LOAD, MATCH, MERGE, NODETACH, OFFSET, OPTIONAL, OR, ORDER, REMOVE, RETURN, SET, SKIP, UNION, UNWIND, USE, WITH, XOR or an expression", | ||
range: { | ||
@@ -701,3 +700,3 @@ end: { | ||
{ | ||
message: "Expected '{' or a procedure name", | ||
message: "Expected any of '{', '(' or a procedure name", | ||
offsets: { | ||
@@ -984,456 +983,16 @@ end: 6, | ||
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, | ||
}, | ||
]); | ||
}); | ||
test.each([ | ||
`MATCH (n:Test1) RETURN n.profile`, | ||
`CREATE (n:Test1 {explain: 'Explain'});`, | ||
`RETURN { clear: 'Clear', params: 'params', history: 'history'}`, | ||
])( | ||
'Syntax validation should not fail if cmd keywords are used in map properties %s', | ||
(query) => { | ||
expect( | ||
getDiagnosticsForQuery({ | ||
query, | ||
}), | ||
).toEqual([]); | ||
}, | ||
); | ||
}); |
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 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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
159543869
2
130
157371
2