@knip/language-server 3.1.2 → 3.1.3
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/README.md +2 -1
- package/package.json +2 -2
- package/src/server.js +7 -2
- package/test/lifecycle.test.js +48 -0
package/README.md
CHANGED
|
@@ -108,7 +108,8 @@ Optionally, the client can implement:
|
|
|
108
108
|
- Show contention: ambiguous or shadowed exports behind re-exports
|
|
109
109
|
- Show contention: converged (diamond-shaped) re-export paths
|
|
110
110
|
|
|
111
|
-
Each `File.contention[name].sites` entry describes where contention occurs, its
|
|
111
|
+
Each `File.contention[name].sites` entry describes where contention occurs, its
|
|
112
|
+
kind, and the originating bindings.
|
|
112
113
|
|
|
113
114
|
Example:
|
|
114
115
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knip/language-server",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/webpro-nl/knip.git",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"./constants": "./src/constants.js"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"knip": "^6.44.
|
|
21
|
+
"knip": "^6.44.1",
|
|
22
22
|
"vscode-languageserver": "^10.1.2",
|
|
23
23
|
"vscode-languageserver-textdocument": "^1.0.16"
|
|
24
24
|
},
|
package/src/server.js
CHANGED
|
@@ -100,6 +100,10 @@ export class LanguageServer {
|
|
|
100
100
|
session;
|
|
101
101
|
|
|
102
102
|
revision = 0;
|
|
103
|
+
|
|
104
|
+
/** @type {undefined | number} */
|
|
105
|
+
failedRevision;
|
|
106
|
+
|
|
103
107
|
/** @type {Rules} */
|
|
104
108
|
rules = {};
|
|
105
109
|
|
|
@@ -276,6 +280,7 @@ export class LanguageServer {
|
|
|
276
280
|
this.connection.sendNotification(NOTIFICATION_MODULE_GRAPH_BUILT, { duration: Date.now() - start });
|
|
277
281
|
} catch (_error) {
|
|
278
282
|
if (revision !== this.revision) return;
|
|
283
|
+
this.failedRevision = revision;
|
|
279
284
|
this.connection.console.error(`Error: ${_error}`);
|
|
280
285
|
}
|
|
281
286
|
}
|
|
@@ -308,8 +313,8 @@ export class LanguageServer {
|
|
|
308
313
|
async handleFileChanges(params) {
|
|
309
314
|
this.fileCache = undefined;
|
|
310
315
|
this.packageJsonCache = undefined;
|
|
311
|
-
if (!this.session) return;
|
|
312
316
|
const session = this.session;
|
|
317
|
+
if (!session && this.failedRevision !== this.revision) return;
|
|
313
318
|
|
|
314
319
|
const cwd = this.cwd ?? process.cwd();
|
|
315
320
|
|
|
@@ -325,7 +330,7 @@ export class LanguageServer {
|
|
|
325
330
|
changes.push({ type, filePath });
|
|
326
331
|
}
|
|
327
332
|
|
|
328
|
-
if (changes.length === 0) return;
|
|
333
|
+
if (!session || changes.length === 0) return;
|
|
329
334
|
|
|
330
335
|
try {
|
|
331
336
|
const result = await session.handleFileChanges(changes);
|
package/test/lifecycle.test.js
CHANGED
|
@@ -27,6 +27,7 @@ const cwd = mkdtempSync(path.join(tmpdir(), 'knip-ls-lifecycle-'));
|
|
|
27
27
|
after(() => rmSync(cwd, { recursive: true, force: true }));
|
|
28
28
|
const filePath = path.join(cwd, 'value.js');
|
|
29
29
|
const changes = { changes: [{ uri: pathToFileURL(filePath).href, type: 2 }] };
|
|
30
|
+
const changed = file => ({ changes: [{ uri: pathToFileURL(path.join(cwd, file)).href, type: 2 }] });
|
|
30
31
|
const updated = { duration: 1, mem: 1024 };
|
|
31
32
|
const config = { editor: { exports: { quickfix: { enabled: true } } } };
|
|
32
33
|
const options = { rules: { exports: 'warn' } };
|
|
@@ -134,6 +135,53 @@ test('overlapping starts retain the latest session and ignore obsolete startup e
|
|
|
134
135
|
assert.equal(connection.sendNotification.mock.callCount(), 1);
|
|
135
136
|
});
|
|
136
137
|
|
|
138
|
+
for (const file of ['knip.json', 'package.json']) {
|
|
139
|
+
test(`${file} change restarts after a failed start`, { timeout: 3000 }, async t => {
|
|
140
|
+
const server = setup(t);
|
|
141
|
+
let calls = 0;
|
|
142
|
+
t.mock.method(knip, 'createOptions', async () => {
|
|
143
|
+
if (++calls === 1) throw new Error('invalid config');
|
|
144
|
+
return options;
|
|
145
|
+
});
|
|
146
|
+
await server.start();
|
|
147
|
+
assert.equal(server.getResults(), null);
|
|
148
|
+
assert.equal(connection.console.error.mock.callCount(), 1);
|
|
149
|
+
await server.handleFileChanges(changed(file));
|
|
150
|
+
assert.equal(calls, 2);
|
|
151
|
+
assert.deepEqual(server.getResults(), { name: 'current' });
|
|
152
|
+
assert.equal(connection.sendNotification.mock.callCount(), 1);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
test('config change does not start a server stopped after a failed start', { timeout: 3000 }, async t => {
|
|
157
|
+
const server = setup(t);
|
|
158
|
+
let calls = 0;
|
|
159
|
+
t.mock.method(knip, 'createOptions', async () => {
|
|
160
|
+
calls++;
|
|
161
|
+
throw new Error('invalid config');
|
|
162
|
+
});
|
|
163
|
+
await server.start();
|
|
164
|
+
server.stop();
|
|
165
|
+
await server.handleFileChanges(changed('knip.json'));
|
|
166
|
+
assert.equal(calls, 1);
|
|
167
|
+
assert.equal(server.getResults(), null);
|
|
168
|
+
assert.equal(connection.sendNotification.mock.callCount(), 0);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test('source change after a failed start neither restarts nor updates', { timeout: 3000 }, async t => {
|
|
172
|
+
const server = setup(t);
|
|
173
|
+
let calls = 0;
|
|
174
|
+
t.mock.method(knip, 'createOptions', async () => {
|
|
175
|
+
calls++;
|
|
176
|
+
throw new Error('invalid config');
|
|
177
|
+
});
|
|
178
|
+
await server.start();
|
|
179
|
+
await server.handleFileChanges(changes);
|
|
180
|
+
assert.equal(calls, 1);
|
|
181
|
+
assert.equal(server.getResults(), null);
|
|
182
|
+
assert.equal(connection.console.error.mock.callCount(), 1);
|
|
183
|
+
});
|
|
184
|
+
|
|
137
185
|
test('graph updates invalidate descriptors requested during the update and notify without diagnostics', async t => {
|
|
138
186
|
const server = setup(t);
|
|
139
187
|
let session = createSession('before');
|