@neo4j-cypher/language-support
Advanced tools
Comparing version 2.0.0-canary-dbe560f to 2.0.0-canary-dda9a15
@@ -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,4 @@ | ||
import { CompletionItem } from 'vscode-languageserver-types'; | ||
import { DbSchema } from '../dbSchema'; | ||
import { ParsedStatement } from '../parserWrapper'; | ||
import { CompletionItem } from '../types'; | ||
export declare function completionCoreCompletion(parsingResult: ParsedStatement, dbSchema: DbSchema, manualTrigger?: boolean): CompletionItem[]; |
@@ -14,5 +14,6 @@ export type { ParserRuleContext } from 'antlr4'; | ||
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>; |
@@ -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-dbe560f", | ||
"version": "2.0.0-canary-dda9a15", | ||
"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'; | ||
@@ -7,0 +6,0 @@ |
@@ -5,4 +5,4 @@ import { Token } from 'antlr4'; | ||
import { | ||
CompletionItem, | ||
CompletionItemKind, | ||
CompletionItemTag, | ||
InsertTextFormat, | ||
@@ -26,2 +26,3 @@ } from 'vscode-languageserver-types'; | ||
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, | ||
@@ -133,0 +187,0 @@ kind, |
@@ -22,5 +22,6 @@ export type { ParserRuleContext } from 'antlr4'; | ||
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'; |
@@ -409,1 +409,4 @@ import CypherLexer from './generated-parser/CypherCmdLexer'; | ||
export const keywordNames = new Set(lexerKeywords.map((i) => tokenNames[i])); | ||
export const operatorSymbols = new Set( | ||
lexerOperators.map((i) => literalNames[i].replaceAll("'", '')), | ||
); |
@@ -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({ |
@@ -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], | ||
}, | ||
], | ||
}); | ||
}); | ||
}); |
@@ -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], | ||
}, | ||
], | ||
}); | ||
}); | ||
}); |
@@ -262,3 +262,9 @@ import { autocomplete } from '../autocompletion/autocompletion'; | ||
{ 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' }, | ||
@@ -265,0 +271,0 @@ { kind: 14, label: 'FALSE' }, |
@@ -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 not supported yet
Sorry, the diff of this file is too big to display
141751145
126
150306