Skip to content

Commit

Permalink
Clean schema cache if file was deleted (#511)
Browse files Browse the repository at this point in the history
* Clean schema cache if file was deleted

Signed-off-by: Yevhen Vydolob <[email protected]>

* Fix eslint warnings

Signed-off-by: Yevhen Vydolob <[email protected]>
  • Loading branch information
evidolob authored May 19, 2021
1 parent fec9024 commit 8434951
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 11 deletions.
9 changes: 0 additions & 9 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,6 @@
"outFiles": ["${workspaceRoot}/out/src/**/*.js"],
"preLaunchTask": "compile typescript"
},
{
// A launch configuration that compiles the extension and runs mocha unit tests
"type": "node",
"request": "launch",
"name": "Launch Tests",
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
"args": ["-u", "tdd", "--timeout", "999999", "--colors", "-r", "ts-node/register", "${workspaceRoot}/test/*.test.ts"],
"preLaunchTask": "compile typescript"
},
{
"name": "Extension Tests",
"type": "extensionHost",
Expand Down
2 changes: 1 addition & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"command": "yarn run compile",
// show the output window only if unrecognized errors occur.
"presentation": {
"reveal": "silent"
"reveal": "never"
},
// The tsc compiler is started in watching mode
"isBackground": true,
Expand Down
2 changes: 1 addition & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export async function activate(context: ExtensionContext): Promise<SchemaExtensi
// Create the language client and start it
client = new LanguageClient('yaml', lsName, serverOptions, clientOptions);

const schemaCache = new JSONSchemaCache(context.globalStoragePath, context.globalState, client.outputChannel);
const schemaCache = new JSONSchemaCache(context.globalStorageUri.fsPath, context.globalState, client.outputChannel);
const disposable = client.start();

const schemaExtensionAPI = new SchemaExtensionAPI(client);
Expand Down
15 changes: 15 additions & 0 deletions src/json-schema-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ export class JSONSchemaCache {

private async init(): Promise<void> {
await fs.ensureDir(this.cachePath);
const cachedFiles = await fs.readdir(this.cachePath);
// clean up memento if cached files was deleted from fs
const cachedValues = cachedFiles.map((it) => path.join(this.cachePath, it));
for (const key in this.cache) {
if (Object.prototype.hasOwnProperty.call(this.cache, key)) {
const cacheEntry = this.cache[key];
if (!cachedValues.includes(cacheEntry.schemaPath)) {
delete this.cache[key];
}
}
}
await this.memento.update(CACHE_KEY, this.cache);
this.isInitialized = true;
}

Expand All @@ -44,6 +56,9 @@ export class JSONSchemaCache {
}

getETag(schemaUri: string): string | undefined {
if (!this.isInitialized) {
return undefined;
}
return this.cache[schemaUri]?.eTag;
}

Expand Down
13 changes: 13 additions & 0 deletions test/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,16 @@ export async function testDiagnostics(docUri: vscode.Uri, expectedDiagnostics: v
assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity);
});
}

export class TestMemento implements vscode.Memento {
get<T>(key: string): T;
get<T>(key: string, defaultValue: T): T;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
get<T>(key: string, defaultValue?: T): T | undefined {
throw new Error('Method not implemented.');
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
update(key: string, value: unknown): Thenable<void> {
throw new Error('Method not implemented.');
}
}
68 changes: 68 additions & 0 deletions test/json-schema-cache.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as sinon from 'sinon';
import * as sinonChai from 'sinon-chai';
import * as chai from 'chai';
import * as vscode from 'vscode';
import * as fs from 'fs-extra';
import { JSONSchemaCache } from '../src/json-schema-cache';
import { TestMemento } from './helper';

const expect = chai.expect;
chai.use(sinonChai);
describe('JSON Schema Cache Tests', () => {
const sandbox = sinon.createSandbox();
let memento: sinon.SinonStubbedInstance<vscode.Memento>;
let ensureDirStub: sinon.SinonStub;
let readdirStub: sinon.SinonStub;
let pathExistsStub: sinon.SinonStub;
let readFileStub: sinon.SinonStub;

afterEach(() => {
sandbox.restore();
});

beforeEach(() => {
memento = sandbox.stub(new TestMemento());
ensureDirStub = sandbox.stub(fs, 'ensureDir');
readdirStub = sandbox.stub(fs, 'readdir');
pathExistsStub = sandbox.stub(fs, 'pathExists');
readFileStub = sandbox.stub(fs, 'readFile');
});

it('should clean up cache if there are no schema file', async () => {
memento.get.returns({ somePath: { schemaPath: '/foo/path/' } });
memento.update.resolves();

ensureDirStub.resolves();
readdirStub.resolves([]);

pathExistsStub.resolves(false);
readFileStub.resolves();

const cache = new JSONSchemaCache('/some/path/', (memento as unknown) as vscode.Memento, {} as vscode.OutputChannel);
const result = await cache.getSchema('/some/uri');
expect(result).is.undefined;
expect(memento.update).calledOnceWith('json-schema-key', {});
});

it('should check cache', async () => {
const mementoData = { somePath: { schemaPath: '/some/path/foo.json' } };
memento.get.returns(mementoData);
memento.update.resolves();

ensureDirStub.resolves();
readdirStub.resolves(['foo.json']);

pathExistsStub.resolves(false);
readFileStub.resolves();

const cache = new JSONSchemaCache('/some/path/', (memento as unknown) as vscode.Memento, {} as vscode.OutputChannel);
const result = await cache.getSchema('/some/uri');
expect(result).is.undefined;
expect(memento.update).calledOnceWith('json-schema-key', mementoData);
});
});

0 comments on commit 8434951

Please sign in to comment.