@neo4j-cypher/language-server 2.0.0-next.4 → 2.0.0-next.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +377 -1
- package/dist/cypher-language-server +2134 -73
- package/dist/server.js +210 -0
- package/package.json +35 -33
- package/src/autocompletion.ts +44 -20
- package/src/descriptionToMarkdown.ts +55 -0
- package/src/formatting.ts +34 -0
- package/src/hoverInfo.ts +29 -0
- package/src/hoverMarkdown.ts +56 -0
- package/src/linting.ts +87 -31
- package/src/server.ts +237 -52
- package/src/signatureHelp.ts +7 -7
- package/src/{syntaxColouring.ts → syntaxHighlighting.ts} +6 -8
- package/src/tests/descriptionToMarkdown.test.ts +157 -0
- package/src/tests/hoverMarkdown.test.ts +232 -0
- package/src/types.ts +24 -4
- package/src/lint-worker.ts +0 -14
package/src/linting.ts
CHANGED
|
@@ -1,57 +1,113 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
|
+
SymbolTable,
|
|
3
|
+
SyntaxDiagnostic,
|
|
4
|
+
} from '@neo4j-cypher/language-support';
|
|
5
|
+
import {
|
|
6
|
+
clampUnsafePositions,
|
|
7
|
+
isNotParamError,
|
|
8
|
+
} from '@neo4j-cypher/language-support';
|
|
9
|
+
import type { Neo4jSchemaPoller } from '@neo4j-cypher/query-tools';
|
|
2
10
|
import debounce from 'lodash.debounce';
|
|
3
11
|
import { join } from 'path';
|
|
4
|
-
import { Diagnostic
|
|
5
|
-
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
12
|
+
import type { Diagnostic } from 'vscode-languageserver';
|
|
13
|
+
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
6
14
|
import workerpool from 'workerpool';
|
|
7
|
-
import { LinterTask, LintWorker } from '
|
|
15
|
+
import type { LinterTask, LintWorker } from '@neo4j-cypher/lint-worker';
|
|
16
|
+
import { convertDbSchema } from '@neo4j-cypher/lint-worker';
|
|
17
|
+
import { languageService } from './server';
|
|
8
18
|
|
|
9
|
-
const
|
|
19
|
+
const defaultWorkerPath = join(__dirname, 'lintWorker.cjs');
|
|
20
|
+
|
|
21
|
+
let pool = workerpool.pool(defaultWorkerPath, {
|
|
10
22
|
minWorkers: 2,
|
|
11
|
-
workerTerminateTimeout:
|
|
23
|
+
workerTerminateTimeout: 0,
|
|
12
24
|
});
|
|
13
|
-
|
|
25
|
+
let linterVersion: string | undefined = undefined;
|
|
14
26
|
let lastSemanticJob: LinterTask | undefined;
|
|
15
27
|
|
|
28
|
+
/**Sets the lintworker to the one specified by the given path, reverting to default if the path is undefined */
|
|
29
|
+
export async function setLintWorker(
|
|
30
|
+
lintWorkerPath: string | undefined = defaultWorkerPath,
|
|
31
|
+
linter: string | undefined,
|
|
32
|
+
) {
|
|
33
|
+
await cleanupWorkers();
|
|
34
|
+
linterVersion = linter;
|
|
35
|
+
pool = workerpool.pool(lintWorkerPath, {
|
|
36
|
+
minWorkers: 2,
|
|
37
|
+
workerTerminateTimeout: 0,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
16
41
|
async function rawLintDocument(
|
|
17
|
-
|
|
42
|
+
document: TextDocument,
|
|
18
43
|
sendDiagnostics: (diagnostics: Diagnostic[]) => void,
|
|
44
|
+
notifySymbolTableDone: (symbolTable: SymbolTable[]) => Promise<void>,
|
|
45
|
+
neo4j: Neo4jSchemaPoller,
|
|
19
46
|
) {
|
|
20
|
-
const { document } = change;
|
|
21
|
-
|
|
22
47
|
const query = document.getText();
|
|
23
48
|
if (query.length === 0) {
|
|
49
|
+
sendDiagnostics([]);
|
|
24
50
|
return;
|
|
25
51
|
}
|
|
26
52
|
|
|
27
|
-
const
|
|
53
|
+
const dbSchema = neo4j.metadata?.dbSchema ?? {};
|
|
54
|
+
try {
|
|
55
|
+
if (lastSemanticJob !== undefined && !lastSemanticJob.resolved) {
|
|
56
|
+
void lastSemanticJob.cancel();
|
|
57
|
+
}
|
|
28
58
|
|
|
29
|
-
|
|
59
|
+
const proxyWorker = (await pool.proxy()) as unknown as LintWorker;
|
|
30
60
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
61
|
+
const fixedDbSchema = convertDbSchema(dbSchema, linterVersion);
|
|
62
|
+
lastSemanticJob = proxyWorker.lintCypherQuery(query, fixedDbSchema, {
|
|
63
|
+
consoleCommands: false,
|
|
64
|
+
});
|
|
65
|
+
const result = await lastSemanticJob;
|
|
36
66
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
67
|
+
// Pass the computed symbol tables to the parser
|
|
68
|
+
if (result.symbolTables) {
|
|
69
|
+
languageService.setSymbolsInfo(
|
|
70
|
+
{
|
|
71
|
+
query,
|
|
72
|
+
symbolTables: result.symbolTables,
|
|
73
|
+
},
|
|
74
|
+
notifySymbolTableDone,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
40
77
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
78
|
+
sendDiagnostics(
|
|
79
|
+
filterLintResult(
|
|
80
|
+
result.diagnostics,
|
|
81
|
+
dbSchema?.databaseNames?.length ? false : true,
|
|
82
|
+
document,
|
|
83
|
+
),
|
|
84
|
+
);
|
|
85
|
+
} catch (err) {
|
|
86
|
+
if (!(err instanceof workerpool.Promise.CancellationError)) {
|
|
87
|
+
console.error(err);
|
|
46
88
|
}
|
|
47
89
|
}
|
|
48
90
|
}
|
|
49
91
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
92
|
+
function filterLintResult(
|
|
93
|
+
diagnostics: SyntaxDiagnostic[],
|
|
94
|
+
dontWarnOnParams: boolean,
|
|
95
|
+
document: TextDocument,
|
|
96
|
+
) {
|
|
97
|
+
return dontWarnOnParams
|
|
98
|
+
? clampUnsafePositions(diagnostics.filter(isNotParamError), document)
|
|
99
|
+
: clampUnsafePositions(diagnostics, document);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const lintDocument: typeof rawLintDocument = debounce(
|
|
103
|
+
rawLintDocument,
|
|
104
|
+
600,
|
|
105
|
+
{
|
|
106
|
+
leading: false,
|
|
107
|
+
trailing: true,
|
|
108
|
+
},
|
|
109
|
+
);
|
|
54
110
|
|
|
55
|
-
export const cleanupWorkers = () => {
|
|
56
|
-
|
|
111
|
+
export const cleanupWorkers = async () => {
|
|
112
|
+
await pool.terminate();
|
|
57
113
|
};
|
package/src/server.ts
CHANGED
|
@@ -1,32 +1,161 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Diagnostic,
|
|
3
|
+
Hover,
|
|
4
|
+
HoverParams,
|
|
5
|
+
InitializeResult,
|
|
6
|
+
SemanticTokensRegistrationOptions,
|
|
7
|
+
} from 'vscode-languageserver/node';
|
|
1
8
|
import {
|
|
2
9
|
createConnection,
|
|
3
|
-
Diagnostic,
|
|
4
10
|
DidChangeConfigurationNotification,
|
|
5
|
-
InitializeResult,
|
|
6
11
|
ProposedFeatures,
|
|
7
|
-
SemanticTokensRegistrationOptions,
|
|
8
12
|
SemanticTokensRegistrationType,
|
|
9
13
|
TextDocuments,
|
|
10
14
|
TextDocumentSyncKind,
|
|
11
15
|
} from 'vscode-languageserver/node';
|
|
12
16
|
|
|
13
17
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
|
|
18
|
+
import type { DbSchema, SymbolTable } from '@neo4j-cypher/language-support';
|
|
19
|
+
import {
|
|
20
|
+
syntaxHighlightingLegend,
|
|
21
|
+
CypherLanguageService,
|
|
22
|
+
} from '@neo4j-cypher/language-support';
|
|
23
|
+
import { Neo4jSchemaPoller } from '@neo4j-cypher/query-tools';
|
|
17
24
|
import { doAutoCompletion } from './autocompletion';
|
|
25
|
+
import { formatDocument } from './formatting';
|
|
26
|
+
import { cleanupWorkers, lintDocument, setLintWorker } from './linting';
|
|
18
27
|
import { doSignatureHelp } from './signatureHelp';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
28
|
+
import { highlightSyntaxForDocument } from './syntaxHighlighting';
|
|
29
|
+
import type {
|
|
30
|
+
LintWorkerSettings,
|
|
31
|
+
Neo4jConnectionSettings,
|
|
32
|
+
Neo4jParameters,
|
|
33
|
+
Neo4jSettings,
|
|
34
|
+
} from './types';
|
|
35
|
+
import workerpool from 'workerpool';
|
|
36
|
+
import type { LintWorker } from '@neo4j-cypher/lint-worker';
|
|
37
|
+
import { convertDbSchema } from '@neo4j-cypher/lint-worker';
|
|
38
|
+
import { join } from 'path';
|
|
39
|
+
import { doHoverInfo } from './hoverInfo.js';
|
|
21
40
|
|
|
22
|
-
const
|
|
41
|
+
const defaultWorkerPath: string = join(__dirname, 'lintWorker.cjs');
|
|
42
|
+
let workerPath = defaultWorkerPath;
|
|
43
|
+
export const languageService = new CypherLanguageService({
|
|
44
|
+
consoleCommandsEnabled: false,
|
|
45
|
+
});
|
|
23
46
|
|
|
24
|
-
|
|
47
|
+
class SymbolFetcher {
|
|
48
|
+
private processing = false;
|
|
49
|
+
private nextJob:
|
|
50
|
+
| {
|
|
51
|
+
query: string;
|
|
52
|
+
uri: string;
|
|
53
|
+
schema: DbSchema;
|
|
54
|
+
}
|
|
55
|
+
| undefined;
|
|
56
|
+
private symbolTablePool = workerpool.pool(defaultWorkerPath, {
|
|
57
|
+
maxWorkers: 1,
|
|
58
|
+
workerTerminateTimeout: 0,
|
|
59
|
+
});
|
|
60
|
+
private linterVersion: string | undefined;
|
|
61
|
+
|
|
62
|
+
public setLintWorker(
|
|
63
|
+
lintWorkerPath: string | undefined = defaultWorkerPath,
|
|
64
|
+
linterVersion: string | undefined,
|
|
65
|
+
) {
|
|
66
|
+
this.linterVersion = linterVersion;
|
|
67
|
+
this.symbolTablePool = workerpool.pool(lintWorkerPath, {
|
|
68
|
+
maxWorkers: 1,
|
|
69
|
+
workerTerminateTimeout: 0,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public queueSymbolJob(query: string, uri: string, schema: DbSchema) {
|
|
74
|
+
this.nextJob = { query, uri, schema };
|
|
75
|
+
if (!this.processing) {
|
|
76
|
+
void this.processJobQueue();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private async processJobQueue() {
|
|
81
|
+
this.processing = true;
|
|
82
|
+
while (this.nextJob) {
|
|
83
|
+
try {
|
|
84
|
+
const query = this.nextJob.query;
|
|
85
|
+
const dbSchema = this.nextJob.schema;
|
|
86
|
+
const docUri = this.nextJob.uri;
|
|
87
|
+
this.nextJob = undefined;
|
|
88
|
+
const proxyWorker =
|
|
89
|
+
(await this.symbolTablePool.proxy()) as unknown as LintWorker;
|
|
90
|
+
const fixedDbSchema = convertDbSchema(dbSchema, this.linterVersion);
|
|
91
|
+
|
|
92
|
+
const result = await proxyWorker.lintCypherQuery(query, fixedDbSchema);
|
|
93
|
+
|
|
94
|
+
if (
|
|
95
|
+
//if this.nextJob has new doc, our result is no longer valid
|
|
96
|
+
result.symbolTables &&
|
|
97
|
+
!(this.nextJob && this.nextJob.uri != docUri)
|
|
98
|
+
) {
|
|
99
|
+
languageService.setSymbolsInfo(
|
|
100
|
+
{
|
|
101
|
+
query,
|
|
102
|
+
symbolTables: result.symbolTables,
|
|
103
|
+
},
|
|
104
|
+
async (symbolTables: SymbolTable[]) =>
|
|
105
|
+
await connection.sendNotification('symbolTableDone', {
|
|
106
|
+
symbolTables,
|
|
107
|
+
}),
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
} catch {
|
|
111
|
+
//eslint-disable-next-line
|
|
112
|
+
console.log('Symbol table calculation failed');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
this.processing = false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const connection = createConnection(ProposedFeatures.all);
|
|
120
|
+
let settings: Neo4jSettings | undefined = undefined;
|
|
25
121
|
|
|
26
122
|
// Create a simple text document manager.
|
|
27
123
|
const documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
|
|
124
|
+
const neo4jSchemaPoller = new Neo4jSchemaPoller();
|
|
125
|
+
const symbolFetcher = new SymbolFetcher();
|
|
126
|
+
|
|
127
|
+
async function lintSingleDocument(document: TextDocument): Promise<void> {
|
|
128
|
+
symbolFetcher.queueSymbolJob(
|
|
129
|
+
document.getText(),
|
|
130
|
+
document.uri,
|
|
131
|
+
neo4jSchemaPoller?.metadata?.dbSchema,
|
|
132
|
+
);
|
|
133
|
+
if (settings?.features?.linting) {
|
|
134
|
+
return lintDocument(
|
|
135
|
+
document,
|
|
136
|
+
(diagnostics: Diagnostic[]) => {
|
|
137
|
+
void connection.sendDiagnostics({
|
|
138
|
+
uri: document.uri,
|
|
139
|
+
diagnostics,
|
|
140
|
+
});
|
|
141
|
+
},
|
|
142
|
+
async (symbolTables: SymbolTable[]) =>
|
|
143
|
+
await connection.sendNotification('symbolTableDone', {
|
|
144
|
+
symbolTables: symbolTables,
|
|
145
|
+
}),
|
|
146
|
+
neo4jSchemaPoller,
|
|
147
|
+
);
|
|
148
|
+
} else {
|
|
149
|
+
void connection.sendDiagnostics({
|
|
150
|
+
uri: document.uri,
|
|
151
|
+
diagnostics: [],
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
28
155
|
|
|
29
|
-
|
|
156
|
+
function relintAllDocuments() {
|
|
157
|
+
void documents.all().map(lintSingleDocument);
|
|
158
|
+
}
|
|
30
159
|
|
|
31
160
|
connection.onInitialize(() => {
|
|
32
161
|
const result: InitializeResult = {
|
|
@@ -35,11 +164,11 @@ connection.onInitialize(() => {
|
|
|
35
164
|
// Tell the client what features does the server support
|
|
36
165
|
completionProvider: {
|
|
37
166
|
resolveProvider: false,
|
|
38
|
-
triggerCharacters: ['.'],
|
|
167
|
+
triggerCharacters: ['.', ':', '{', '$', ')', ' ', ']', '-', '<'],
|
|
39
168
|
},
|
|
40
169
|
semanticTokensProvider: {
|
|
41
|
-
documentSelector:
|
|
42
|
-
legend:
|
|
170
|
+
documentSelector: [{ language: 'cypher' }],
|
|
171
|
+
legend: syntaxHighlightingLegend,
|
|
43
172
|
range: false,
|
|
44
173
|
full: {
|
|
45
174
|
delta: false,
|
|
@@ -48,6 +177,8 @@ connection.onInitialize(() => {
|
|
|
48
177
|
signatureHelpProvider: {
|
|
49
178
|
triggerCharacters: ['(', ',', ')'],
|
|
50
179
|
},
|
|
180
|
+
hoverProvider: true,
|
|
181
|
+
documentFormattingProvider: true,
|
|
51
182
|
},
|
|
52
183
|
};
|
|
53
184
|
|
|
@@ -60,8 +191,8 @@ connection.onInitialized(() => {
|
|
|
60
191
|
});
|
|
61
192
|
|
|
62
193
|
const registrationOptions: SemanticTokensRegistrationOptions = {
|
|
63
|
-
documentSelector:
|
|
64
|
-
legend:
|
|
194
|
+
documentSelector: [{ language: 'cypher' }],
|
|
195
|
+
legend: syntaxHighlightingLegend,
|
|
65
196
|
range: false,
|
|
66
197
|
full: {
|
|
67
198
|
delta: false,
|
|
@@ -73,53 +204,107 @@ connection.onInitialized(() => {
|
|
|
73
204
|
);
|
|
74
205
|
});
|
|
75
206
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
diagnostics,
|
|
81
|
-
});
|
|
82
|
-
}),
|
|
83
|
-
);
|
|
207
|
+
connection.onDidChangeConfiguration((params) => {
|
|
208
|
+
settings = params.settings?.neo4j as Neo4jSettings;
|
|
209
|
+
relintAllDocuments();
|
|
210
|
+
});
|
|
84
211
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
);
|
|
212
|
+
documents.onDidChangeContent((change) => lintSingleDocument(change.document));
|
|
213
|
+
|
|
214
|
+
// Trigger the syntax highlighting
|
|
215
|
+
connection.languages.semanticTokens.on(highlightSyntaxForDocument(documents));
|
|
89
216
|
|
|
90
217
|
// Trigger the signature help, providing info about functions / procedures
|
|
91
|
-
connection.onSignatureHelp(doSignatureHelp(documents,
|
|
218
|
+
connection.onSignatureHelp(doSignatureHelp(documents, neo4jSchemaPoller));
|
|
92
219
|
// Trigger the auto completion
|
|
93
|
-
connection.onCompletion(doAutoCompletion(documents,
|
|
94
|
-
|
|
95
|
-
connection.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
void neo4jSdk.persistentConnect(
|
|
108
|
-
neo4jConfig.URL,
|
|
109
|
-
{
|
|
110
|
-
username: neo4jConfig.user,
|
|
111
|
-
password: neo4jConfig.password,
|
|
112
|
-
},
|
|
113
|
-
{ appName: 'cypher-language-server' },
|
|
114
|
-
);
|
|
220
|
+
connection.onCompletion(doAutoCompletion(documents, neo4jSchemaPoller));
|
|
221
|
+
|
|
222
|
+
connection.onNotification(
|
|
223
|
+
'updateLintWorker',
|
|
224
|
+
(linterSettings: LintWorkerSettings) => {
|
|
225
|
+
const lintWorkerPath = linterSettings.lintWorkerPath;
|
|
226
|
+
const linterVersion = linterSettings.linterVersion;
|
|
227
|
+
if (lintWorkerPath !== workerPath) {
|
|
228
|
+
workerPath = lintWorkerPath;
|
|
229
|
+
void (async () => {
|
|
230
|
+
symbolFetcher.setLintWorker(workerPath, linterVersion);
|
|
231
|
+
await setLintWorker(workerPath, linterVersion);
|
|
232
|
+
relintAllDocuments();
|
|
233
|
+
})();
|
|
115
234
|
}
|
|
116
235
|
},
|
|
117
236
|
);
|
|
118
237
|
|
|
238
|
+
connection.onNotification(
|
|
239
|
+
'connectionUpdated',
|
|
240
|
+
(connectionSettings: Neo4jConnectionSettings) => {
|
|
241
|
+
changeConnection(connectionSettings);
|
|
242
|
+
neo4jSchemaPoller.events.once('schemaFetched', relintAllDocuments);
|
|
243
|
+
},
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
connection.onHover((params: HoverParams): Hover | null => {
|
|
247
|
+
return doHoverInfo(documents, neo4jSchemaPoller, params);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
connection.onNotification(
|
|
251
|
+
'fetchSymbolTable',
|
|
252
|
+
(params: {
|
|
253
|
+
query: string;
|
|
254
|
+
uri: string;
|
|
255
|
+
version: number;
|
|
256
|
+
schema: DbSchema;
|
|
257
|
+
}) => {
|
|
258
|
+
neo4jSchemaPoller.events.once('schemaFetched', () =>
|
|
259
|
+
symbolFetcher.queueSymbolJob(params.query, params.uri, params.schema),
|
|
260
|
+
);
|
|
261
|
+
},
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
connection.onNotification('updateParameters', (parameters: Neo4jParameters) => {
|
|
265
|
+
neo4jSchemaPoller.setParameters(parameters);
|
|
266
|
+
relintAllDocuments();
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
connection.onDocumentFormatting((params) => {
|
|
270
|
+
return formatDocument(params, documents);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
connection.onNotification('connectionDisconnected', () => {
|
|
274
|
+
disconnect();
|
|
275
|
+
relintAllDocuments();
|
|
276
|
+
});
|
|
277
|
+
|
|
119
278
|
documents.listen(connection);
|
|
120
279
|
|
|
121
280
|
connection.listen();
|
|
122
281
|
|
|
123
282
|
connection.onExit(() => {
|
|
124
|
-
cleanupWorkers();
|
|
283
|
+
void cleanupWorkers();
|
|
125
284
|
});
|
|
285
|
+
|
|
286
|
+
const changeConnection = (connectionSettings: Neo4jConnectionSettings) => {
|
|
287
|
+
disconnect();
|
|
288
|
+
|
|
289
|
+
if (
|
|
290
|
+
neo4jSchemaPoller.connection === undefined &&
|
|
291
|
+
connectionSettings.connect &&
|
|
292
|
+
connectionSettings.password &&
|
|
293
|
+
connectionSettings.connectURL &&
|
|
294
|
+
connectionSettings.user
|
|
295
|
+
) {
|
|
296
|
+
void neo4jSchemaPoller.persistentConnect(
|
|
297
|
+
connectionSettings.connectURL,
|
|
298
|
+
{
|
|
299
|
+
username: connectionSettings.user,
|
|
300
|
+
password: connectionSettings.password,
|
|
301
|
+
},
|
|
302
|
+
{ appName: 'cypher-language-server' },
|
|
303
|
+
connectionSettings.database,
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const disconnect = () => {
|
|
309
|
+
neo4jSchemaPoller.disconnect();
|
|
310
|
+
};
|
package/src/signatureHelp.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type {
|
|
3
2
|
SignatureHelp,
|
|
4
3
|
SignatureHelpParams,
|
|
5
4
|
TextDocuments,
|
|
6
5
|
} from 'vscode-languageserver/node';
|
|
7
6
|
|
|
8
|
-
import { Neo4jSchemaPoller } from '@neo4j-cypher/
|
|
9
|
-
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
7
|
+
import type { Neo4jSchemaPoller } from '@neo4j-cypher/query-tools';
|
|
8
|
+
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
9
|
+
import { languageService } from './server';
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const emptyResult: SignatureHelp = {
|
|
12
12
|
signatures: [],
|
|
13
13
|
activeSignature: undefined,
|
|
14
14
|
activeParameter: undefined,
|
|
@@ -26,10 +26,10 @@ export function doSignatureHelp(
|
|
|
26
26
|
const position = params.position;
|
|
27
27
|
const offset = textDocument.offsetAt(position);
|
|
28
28
|
|
|
29
|
-
return
|
|
29
|
+
return languageService.getSignatureHelp(
|
|
30
30
|
textDocument.getText(),
|
|
31
31
|
neo4j.metadata?.dbSchema ?? {},
|
|
32
|
-
offset,
|
|
32
|
+
{ caretPosition: offset },
|
|
33
33
|
);
|
|
34
34
|
};
|
|
35
35
|
}
|
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
mapCypherToSemanticTokenIndex,
|
|
4
|
-
} from '@neo4j-cypher/language-support';
|
|
5
|
-
import {
|
|
6
|
-
SemanticTokensBuilder,
|
|
1
|
+
import { mapCypherToSemanticTokenIndex } from '@neo4j-cypher/language-support';
|
|
2
|
+
import type {
|
|
7
3
|
SemanticTokensParams,
|
|
8
4
|
TextDocument,
|
|
9
5
|
TextDocuments,
|
|
10
6
|
} from 'vscode-languageserver';
|
|
7
|
+
import { SemanticTokensBuilder } from 'vscode-languageserver';
|
|
8
|
+
import { languageService } from './server';
|
|
11
9
|
|
|
12
|
-
export function
|
|
10
|
+
export function highlightSyntaxForDocument(
|
|
13
11
|
documents: TextDocuments<TextDocument>,
|
|
14
12
|
) {
|
|
15
13
|
return (params: SemanticTokensParams) => {
|
|
16
14
|
const textDocument = documents.get(params.textDocument.uri);
|
|
17
15
|
if (textDocument === undefined) return { data: [] };
|
|
18
16
|
|
|
19
|
-
const tokens =
|
|
17
|
+
const tokens = languageService.highlightSyntax(textDocument.getText());
|
|
20
18
|
|
|
21
19
|
const builder = new SemanticTokensBuilder();
|
|
22
20
|
|