From 72bff0e7db46fb53293efc990dc64d2c06401459 Mon Sep 17 00:00:00 2001 From: Gord P Date: Mon, 11 Oct 2021 07:10:54 -0400 Subject: [PATCH] fix: skip config updates when no custom filename is defined (#1951) Skip config reload when no custom filename is defined. Previously, any project without a load.fileName configuration would reload configuration on every change event. This is because match(undefined) always returns true. --- .changeset/itchy-peaches-return.md | 5 ++ .../package.json | 3 +- .../src/MessageProcessor.ts | 11 ++-- .../src/__tests__/MessageProcessor-test.ts | 58 ++++++++++++++++++- 4 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 .changeset/itchy-peaches-return.md diff --git a/.changeset/itchy-peaches-return.md b/.changeset/itchy-peaches-return.md new file mode 100644 index 00000000000..357ae66f266 --- /dev/null +++ b/.changeset/itchy-peaches-return.md @@ -0,0 +1,5 @@ +--- +'graphql-language-service-server': patch +--- + +fix: skip config updates when no custom filename is defined diff --git a/packages/graphql-language-service-server/package.json b/packages/graphql-language-service-server/package.json index 9e7e81cf57a..788c7e2cfe2 100644 --- a/packages/graphql-language-service-server/package.json +++ b/packages/graphql-language-service-server/package.json @@ -44,6 +44,7 @@ "devDependencies": { "@types/mkdirp": "^1.0.1", "cross-env": "^7.0.2", - "graphql": "experimental-stream-defer" + "graphql": "experimental-stream-defer", + "vscode-languageserver-protocol": "^3.15.3" } } diff --git a/packages/graphql-language-service-server/src/MessageProcessor.ts b/packages/graphql-language-service-server/src/MessageProcessor.ts index 0e5e5cb9f55..50e35afe435 100644 --- a/packages/graphql-language-service-server/src/MessageProcessor.ts +++ b/packages/graphql-language-service-server/src/MessageProcessor.ts @@ -564,11 +564,12 @@ export class MessageProcessor { throw Error('No cache available for handleWatchedFilesChanged'); } // update when graphql config changes! - if ( - ['graphql.config', 'graphqlrc', this._settings.load.fileName].some( - v => change.uri.match(v)?.length, - ) - ) { + const configMatchers = [ + 'graphql.config', + 'graphqlrc', + this._settings.load.fileName, + ].filter(Boolean); + if (configMatchers.some(v => change.uri.match(v)?.length)) { this._logger.info('updating graphql config'); this._updateGraphQLConfig(); } diff --git a/packages/graphql-language-service-server/src/__tests__/MessageProcessor-test.ts b/packages/graphql-language-service-server/src/__tests__/MessageProcessor-test.ts index b060ea67e9f..2a6fbb767df 100644 --- a/packages/graphql-language-service-server/src/__tests__/MessageProcessor-test.ts +++ b/packages/graphql-language-service-server/src/__tests__/MessageProcessor-test.ts @@ -8,6 +8,7 @@ */ import { tmpdir } from 'os'; import { SymbolKind } from 'vscode-languageserver'; +import { FileChangeType } from 'vscode-languageserver-protocol'; import { Position, Range } from 'graphql-language-service-utils'; import { MessageProcessor } from '../MessageProcessor'; @@ -24,7 +25,10 @@ import type { DefinitionQueryResult, Outline } from 'graphql-language-service'; import { Logger } from '../Logger'; import { pathToFileURL } from 'url'; -const baseConfig = { dirpath: __dirname }; +jest.mock('fs', () => ({ + ...jest.requireActual('fs'), + readFileSync: jest.fn(jest.requireActual('fs').readFileSync), +})); describe('MessageProcessor', () => { const logger = new Logger(tmpdir()); @@ -48,6 +52,7 @@ describe('MessageProcessor', () => { beforeEach(async () => { const gqlConfig = await loadConfig({ rootDir: __dirname, extensions: [] }); // loadConfig.mockRestore(); + messageProcessor._settings = { load: {} }; messageProcessor._graphQLCache = new GraphQLCache({ configDir: __dirname, config: gqlConfig, @@ -480,4 +485,55 @@ export function Example(arg: string) {}`; const contents = parseDocument(text, 'test.js'); expect(contents.length).toEqual(0); }); + + describe('handleWatchedFilesChangedNotification', () => { + const mockReadFileSync: jest.Mock = jest.requireMock('fs').readFileSync; + + beforeEach(() => { + mockReadFileSync.mockReturnValue(''); + messageProcessor._updateGraphQLConfig = jest.fn(); + }); + + it('skips config updates for normal file changes', async () => { + await messageProcessor.handleWatchedFilesChangedNotification({ + changes: [ + { + uri: `${pathToFileURL('.')}/foo.graphql`, + type: FileChangeType.Changed, + }, + ], + }); + + expect(messageProcessor._updateGraphQLConfig).not.toHaveBeenCalled(); + }); + + it('updates config for standard config filename changes', async () => { + await messageProcessor.handleWatchedFilesChangedNotification({ + changes: [ + { + uri: `${pathToFileURL('.')}/.graphql.config`, + type: FileChangeType.Changed, + }, + ], + }); + + expect(messageProcessor._updateGraphQLConfig).toHaveBeenCalled(); + }); + + it('updates config for custom config filename changes', async () => { + const customConfigName = 'custom-config-name.yml'; + messageProcessor._settings = { load: { fileName: customConfigName } }; + + await messageProcessor.handleWatchedFilesChangedNotification({ + changes: [ + { + uri: `${pathToFileURL('.')}/${customConfigName}`, + type: FileChangeType.Changed, + }, + ], + }); + + expect(messageProcessor._updateGraphQLConfig).toHaveBeenCalled(); + }); + }); });