Skip to content

Commit

Permalink
more improvements and coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
acao committed Feb 5, 2024
1 parent fee38c7 commit 04000ca
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 70 deletions.
23 changes: 12 additions & 11 deletions packages/graphql-language-service-server/src/GraphQLCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ export class GraphQLCache implements GraphQLCacheInterface {
query,
};
} catch {
console.log('parse error');
return { ast: null, query };
}
});
Expand Down Expand Up @@ -664,14 +665,14 @@ export class GraphQLCache implements GraphQLCacheInterface {
schemaCacheKey = schemaKey as string;

// Maybe use cache
if (this._schemaMap.has(schemaCacheKey)) {
schema = this._schemaMap.get(schemaCacheKey);
if (schema) {
return queryHasExtensions
? this._extendSchema(schema, schemaPath, schemaCacheKey)
: schema;
}
}
// if (this._schemaMap.has(schemaCacheKey)) {
// schema = this._schemaMap.get(schemaCacheKey);
// if (schema) {
// return queryHasExtensions
// ? this._extendSchema(schema, schemaPath, schemaCacheKey)
// : schema;
// }
// }

// Read from disk
schema = await projectConfig.getSchema();
Expand All @@ -691,9 +692,9 @@ export class GraphQLCache implements GraphQLCacheInterface {
schema = this._extendSchema(schema, schemaPath, schemaCacheKey);
}

if (schemaCacheKey) {
this._schemaMap.set(schemaCacheKey, schema);
}
// if (schemaCacheKey) {
// this._schemaMap.set(schemaCacheKey, schema);
// }
return schema;
};

Expand Down
45 changes: 27 additions & 18 deletions packages/graphql-language-service-server/src/MessageProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export class MessageProcessor {
}

if (!existsSync(this._tmpDirBase)) {
mkdirSync(this._tmpDirBase);
void mkdirSync(this._tmpDirBase);
}
}
get connection(): Connection {
Expand Down Expand Up @@ -671,9 +671,13 @@ export class MessageProcessor {
) {
const { uri } = change;

const text = readFileSync(URI.parse(uri).fsPath, 'utf-8');
const text = await readFile(URI.parse(uri).fsPath, 'utf-8');
const contents = this._parser(text, uri);

await this._invalidateCache(
{ uri, version: 0 },
URI.parse(uri).fsPath,
contents,
);
await this._updateFragmentDefinition(uri, contents);
await this._updateObjectTypeDefinition(uri, contents);

Expand Down Expand Up @@ -720,16 +724,8 @@ export class MessageProcessor {
}
}
if (change.type === FileChangeTypeKind.Deleted) {
await this._graphQLCache.updateFragmentDefinitionCache(
this._graphQLCache.getGraphQLConfig().dirpath,
change.uri,
false,
);
await this._graphQLCache.updateObjectTypeDefinitionCache(
this._graphQLCache.getGraphQLConfig().dirpath,
change.uri,
false,
);
await this._updateFragmentDefinition(change.uri, []);
await this._updateObjectTypeDefinition(change.uri, []);
}
}),
);
Expand Down Expand Up @@ -1132,9 +1128,15 @@ export class MessageProcessor {
uri: Uri,
contents: CachedContent[],
): Promise<void> {
const rootDir = this._graphQLCache.getGraphQLConfig().dirpath;

await this._graphQLCache.updateFragmentDefinition(rootDir, uri, contents);
const project = this._graphQLCache.getProjectForFile(uri);
if (project) {
const cacheKey = this._graphQLCache._cacheKeyForProject(project);
await this._graphQLCache.updateFragmentDefinition(
cacheKey,
uri,
contents,
);
}
}

private async _updateSchemaIfChanged(
Expand Down Expand Up @@ -1189,9 +1191,16 @@ export class MessageProcessor {
uri: Uri,
contents: CachedContent[],
): Promise<void> {
const rootDir = this._graphQLCache.getGraphQLConfig().dirpath;
const project = await this._graphQLCache.getProjectForFile(uri);
if (project) {
const cacheKey = this._graphQLCache._cacheKeyForProject(project);

await this._graphQLCache.updateObjectTypeDefinition(rootDir, uri, contents);
await this._graphQLCache.updateObjectTypeDefinition(
cacheKey,
uri,
contents,
);
}
}

private _getCachedDocument(uri: string): CachedDocumentType | null {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import mockfs from 'mock-fs';
import { join } from 'node:path';
import { MockProject } from './__utils__/MockProject';
import { readFileSync } from 'node:fs';
import { FileChangeTypeKind } from 'graphql-language-service';
import { FileChangeType } from 'vscode-languageserver';
import { readFile } from 'node:fs/promises';

describe('MessageProcessor with no config', () => {
let messageProcessor: MessageProcessor;
Expand Down Expand Up @@ -168,11 +171,11 @@ describe('MessageProcessor with no config', () => {
});
});

describe('project with simple config', () => {
describe('project with simple config and graphql files', () => {
afterEach(() => {
mockfs.restore();
});
it('caches files and schema with .graphql file config', async () => {
it.only('caches files and schema with .graphql file config', async () => {
const project = new MockProject({
files: [
[
Expand All @@ -183,7 +186,8 @@ describe('project with simple config', () => {
'schema.graphql',
'type Query { foo: Foo }\n\ntype Foo { bar: String }',
],
['query.graphql', 'query { bar }'],
['query.graphql', 'query { bar ...B }'],
['fragments.graphql', 'fragment B on Foo { bar }'],
],
});
await project.lsp.handleInitializeRequest({
Expand All @@ -199,9 +203,41 @@ describe('project with simple config', () => {
expect(project.lsp._logger.error).not.toHaveBeenCalled();
// console.log(project.lsp._graphQLCache.getSchema('schema.graphql'));
expect(await project.lsp._graphQLCache.getSchema()).toBeDefined();
expect(Array.from(project.lsp._textDocumentCache)[0][0]).toEqual(
project.uri('query.graphql'),
// TODO: for some reason the cache result formats the graphql query??
expect(
project.lsp._textDocumentCache.get(project.uri('query.graphql'))
.contents[0].query,
).toContain('...B');
const definitions = await project.lsp.handleDefinitionRequest({
textDocument: { uri: project.uri('fragments.graphql') },
position: { character: 16, line: 0 },
});
expect(definitions[0].uri).toEqual(project.uri('schema.graphql'));
expect(JSON.parse(JSON.stringify(definitions[0].range.end))).toEqual({
line: 2,
character: 24,
});
// TODO: get mockfs working so we can change watched files.
// currently, when I run this, it removes the file entirely
project.changeFile(
'schema.graphql',
'type Query { foo: Foo }\n\n type Test { test: String }\n\n\n\n\ntype Foo { bad: Int, bar: String }',
);
await project.lsp.handleWatchedFilesChangedNotification({
changes: [
{ uri: project.uri('schema.graphql'), type: FileChangeType.Changed },
],
});
const definitionsAgain = await project.lsp.handleDefinitionRequest({
textDocument: { uri: project.uri('fragments.graphql') },
position: { character: 16, line: 0 },
});
expect(definitionsAgain[0].uri).toEqual(project.uri('schema.graphql'));
// TODO: this should change when a watched file changes???
expect(JSON.parse(JSON.stringify(definitions[0].range.end))).toEqual({
line: 2,
character: 24,
});
});
it('caches files and schema with a URL config', async () => {
const project = new MockProject({
Expand All @@ -212,7 +248,7 @@ describe('project with simple config', () => {
],

['query.graphql', 'query { bar }'],
['fragments.graphql', 'fragment Ep on Episode { created }'],
['fragments.graphql', 'fragment Ep on Episode {\n created \n}'],
],
});
await project.lsp.handleInitializeRequest({
Expand All @@ -237,7 +273,7 @@ describe('project with simple config', () => {
'/tmp/graphql-language-service/test/projects/default/generated-schema.graphql',
),
);
expect(file.toString('utf-8').length).toBeGreaterThan(0);
expect(file.toString('utf-8').split('\n').length).toBeGreaterThan(10);
const hover = await project.lsp.handleHoverRequest({
position: {
character: 10,
Expand All @@ -252,6 +288,17 @@ describe('project with simple config', () => {
textDocument: { uri: project.uri('query.graphql') },
position: { character: 33, line: 0 },
});
// ensure that fragment definitions work
expect(definitions[0].uri).toEqual(project.uri('fragments.graphql'));
expect(JSON.parse(JSON.stringify(definitions[0].range))).toEqual({
start: {
line: 0,
character: 0,
},
end: {
line: 2,
character: 1,
},
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,50 +10,49 @@ export class MockLogger implements VSCodeLogger {
log = jest.fn();
}

const defaultMocks = {
'node_modules/parse-json': mockfs.load('node_modules/parse-json'),
'node_modules/error-ex': mockfs.load('node_modules/error-ex'),
'node_modules/is-arrayish': mockfs.load('node_modules/is-arrayish'),
'node_modules/json-parse-even-better-errors': mockfs.load(
'node_modules/json-parse-even-better-errors',
),
'node_modules/lines-and-columns': mockfs.load(
'node_modules/lines-and-columns',
),
'node_modules/@babel/code-frame': mockfs.load(
'node_modules/@babel/code-frame',
),
'node_modules/@babel/highlight': mockfs.load('node_modules/@babel/highlight'),
'node_modules/jest-message-util': mockfs.load(
'node_modules/jest-message-util',
),
// 'node_modules/jest-message-util/node_modules/stack-util': mockfs.load(
// 'node_modules/jest-message-util/node_modules/stack-util',
// ),
// 'node_modules/stack-util': mockfs.load('node_modules/stack-util'),
// '/tmp/graphql-language-service/test/projects': mockfs.directory({
// mode: 0o777,
// }),
};
// when using mockfs with cosmic-config, a dynamic inline
// require of parse-json creates the necessity for loading in the actual
// modules to the mocked filesystem
const modules = [
'parse-json',
'error-ex',
'is-arrayish',
'json-parse-even-better-errors',
'lines-and-columns',
'@babel/code-frame',
'@babel/highlight',
// these i think are just required by jest when you console log from a test
'jest-message-util',
'stack-utils',
'pretty-format',
'ansi-regex',
'js-tokens',
'escape-string-regexp',
];
const defaultMocks = modules.reduce((acc, module) => {
acc[`node_modules/${module}`] = mockfs.load(`node_modules/${module}`);
return acc;
}, {});

type Files = [filename: string, text: string][];

export class MockProject {
private root: string;
private files: Files;
private messageProcessor: MessageProcessor;
constructor({
files = [],
root = '/tmp/test',
settings,
}: {
files: [filename: string, text: string][];
files: Files;
root?: string;
settings?: [name: string, vale: any][];
}) {
this.root = root;
const mockFiles = { ...defaultMocks };
files.map(([filename, text]) => {
mockFiles[this.filePath(filename)] = text;
});
mockfs(mockFiles);
this.files = files;

this.mockFiles();
this.messageProcessor = new MessageProcessor({
connection: {
get workspace() {
Expand All @@ -68,16 +67,22 @@ export class MockProject {
loadConfigOptions: { rootDir: root },
});
}
private mockFiles() {
const mockFiles = { ...defaultMocks };
this.files.map(([filename, text]) => {
mockFiles[this.filePath(filename)] = text;
});
mockfs(mockFiles);
}
public filePath(filename: string) {
return `${this.root}/${filename}`;
}
public uri(filename: string) {
return URI.file(this.filePath(filename)).toString();
}
changeFile(filename: string, text: string) {
mockfs({
[this.filePath(filename)]: text,
});
this.files.push([filename, text]);
this.mockFiles();
}
get lsp() {
return this.messageProcessor;
Expand Down

0 comments on commit 04000ca

Please sign in to comment.