Skip to content

Commit 8434951

Browse files
authored
Clean schema cache if file was deleted (#511)
* Clean schema cache if file was deleted Signed-off-by: Yevhen Vydolob <yvydolob@redhat.com> * Fix eslint warnings Signed-off-by: Yevhen Vydolob <yvydolob@redhat.com>
1 parent fec9024 commit 8434951

File tree

6 files changed

+98
-11
lines changed

6 files changed

+98
-11
lines changed

.vscode/launch.json

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,6 @@
1313
"outFiles": ["${workspaceRoot}/out/src/**/*.js"],
1414
"preLaunchTask": "compile typescript"
1515
},
16-
{
17-
// A launch configuration that compiles the extension and runs mocha unit tests
18-
"type": "node",
19-
"request": "launch",
20-
"name": "Launch Tests",
21-
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
22-
"args": ["-u", "tdd", "--timeout", "999999", "--colors", "-r", "ts-node/register", "${workspaceRoot}/test/*.test.ts"],
23-
"preLaunchTask": "compile typescript"
24-
},
2516
{
2617
"name": "Extension Tests",
2718
"type": "extensionHost",

.vscode/tasks.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"command": "yarn run compile",
1313
// show the output window only if unrecognized errors occur.
1414
"presentation": {
15-
"reveal": "silent"
15+
"reveal": "never"
1616
},
1717
// The tsc compiler is started in watching mode
1818
"isBackground": true,

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export async function activate(context: ExtensionContext): Promise<SchemaExtensi
121121
// Create the language client and start it
122122
client = new LanguageClient('yaml', lsName, serverOptions, clientOptions);
123123

124-
const schemaCache = new JSONSchemaCache(context.globalStoragePath, context.globalState, client.outputChannel);
124+
const schemaCache = new JSONSchemaCache(context.globalStorageUri.fsPath, context.globalState, client.outputChannel);
125125
const disposable = client.start();
126126

127127
const schemaExtensionAPI = new SchemaExtensionAPI(client);

src/json-schema-cache.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ export class JSONSchemaCache {
3333

3434
private async init(): Promise<void> {
3535
await fs.ensureDir(this.cachePath);
36+
const cachedFiles = await fs.readdir(this.cachePath);
37+
// clean up memento if cached files was deleted from fs
38+
const cachedValues = cachedFiles.map((it) => path.join(this.cachePath, it));
39+
for (const key in this.cache) {
40+
if (Object.prototype.hasOwnProperty.call(this.cache, key)) {
41+
const cacheEntry = this.cache[key];
42+
if (!cachedValues.includes(cacheEntry.schemaPath)) {
43+
delete this.cache[key];
44+
}
45+
}
46+
}
47+
await this.memento.update(CACHE_KEY, this.cache);
3648
this.isInitialized = true;
3749
}
3850

@@ -44,6 +56,9 @@ export class JSONSchemaCache {
4456
}
4557

4658
getETag(schemaUri: string): string | undefined {
59+
if (!this.isInitialized) {
60+
return undefined;
61+
}
4762
return this.cache[schemaUri]?.eTag;
4863
}
4964

test/helper.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,16 @@ export async function testDiagnostics(docUri: vscode.Uri, expectedDiagnostics: v
123123
assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity);
124124
});
125125
}
126+
127+
export class TestMemento implements vscode.Memento {
128+
get<T>(key: string): T;
129+
get<T>(key: string, defaultValue: T): T;
130+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
131+
get<T>(key: string, defaultValue?: T): T | undefined {
132+
throw new Error('Method not implemented.');
133+
}
134+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
135+
update(key: string, value: unknown): Thenable<void> {
136+
throw new Error('Method not implemented.');
137+
}
138+
}

test/json-schema-cache.test.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import * as sinon from 'sinon';
7+
import * as sinonChai from 'sinon-chai';
8+
import * as chai from 'chai';
9+
import * as vscode from 'vscode';
10+
import * as fs from 'fs-extra';
11+
import { JSONSchemaCache } from '../src/json-schema-cache';
12+
import { TestMemento } from './helper';
13+
14+
const expect = chai.expect;
15+
chai.use(sinonChai);
16+
describe('JSON Schema Cache Tests', () => {
17+
const sandbox = sinon.createSandbox();
18+
let memento: sinon.SinonStubbedInstance<vscode.Memento>;
19+
let ensureDirStub: sinon.SinonStub;
20+
let readdirStub: sinon.SinonStub;
21+
let pathExistsStub: sinon.SinonStub;
22+
let readFileStub: sinon.SinonStub;
23+
24+
afterEach(() => {
25+
sandbox.restore();
26+
});
27+
28+
beforeEach(() => {
29+
memento = sandbox.stub(new TestMemento());
30+
ensureDirStub = sandbox.stub(fs, 'ensureDir');
31+
readdirStub = sandbox.stub(fs, 'readdir');
32+
pathExistsStub = sandbox.stub(fs, 'pathExists');
33+
readFileStub = sandbox.stub(fs, 'readFile');
34+
});
35+
36+
it('should clean up cache if there are no schema file', async () => {
37+
memento.get.returns({ somePath: { schemaPath: '/foo/path/' } });
38+
memento.update.resolves();
39+
40+
ensureDirStub.resolves();
41+
readdirStub.resolves([]);
42+
43+
pathExistsStub.resolves(false);
44+
readFileStub.resolves();
45+
46+
const cache = new JSONSchemaCache('/some/path/', (memento as unknown) as vscode.Memento, {} as vscode.OutputChannel);
47+
const result = await cache.getSchema('/some/uri');
48+
expect(result).is.undefined;
49+
expect(memento.update).calledOnceWith('json-schema-key', {});
50+
});
51+
52+
it('should check cache', async () => {
53+
const mementoData = { somePath: { schemaPath: '/some/path/foo.json' } };
54+
memento.get.returns(mementoData);
55+
memento.update.resolves();
56+
57+
ensureDirStub.resolves();
58+
readdirStub.resolves(['foo.json']);
59+
60+
pathExistsStub.resolves(false);
61+
readFileStub.resolves();
62+
63+
const cache = new JSONSchemaCache('/some/path/', (memento as unknown) as vscode.Memento, {} as vscode.OutputChannel);
64+
const result = await cache.getSchema('/some/uri');
65+
expect(result).is.undefined;
66+
expect(memento.update).calledOnceWith('json-schema-key', mementoData);
67+
});
68+
});

0 commit comments

Comments
 (0)