diff --git a/.changeset/slimy-fireants-dream.md b/.changeset/slimy-fireants-dream.md new file mode 100644 index 00000000000..72c9ae3da83 --- /dev/null +++ b/.changeset/slimy-fireants-dream.md @@ -0,0 +1,7 @@ +--- +'graphql-language-service-cli': patch +'graphql-language-service-server': patch +'vscode-graphql': patch +--- + +Fixes to svelte parsing, tag parsing refactor diff --git a/.github/workflows/main-test.yml b/.github/workflows/main-test.yml index e4477ce642e..7a93be632ca 100644 --- a/.github/workflows/main-test.yml +++ b/.github/workflows/main-test.yml @@ -51,5 +51,3 @@ jobs: files: coverage/lcov.info fail_ci_if_error: true verbose: true - - diff --git a/jest.config.base.js b/jest.config.base.js index 8765a91bad9..15e87eda8f8 100644 --- a/jest.config.base.js +++ b/jest.config.base.js @@ -30,6 +30,8 @@ module.exports = (dir, env = 'jsdom') => { '^cm6-graphql\\/src\\/([^]+)': `${__dirname}/packages/cm6-graphql/dist/$1`, '^example-([^/]+)': `${__dirname}/examples/$1/src`, '^-!svg-react-loader.*$': '/resources/jest/svgImportMock.js', + // because of the svelte compiler's export patterns i guess? + 'svelte/compiler': `${__dirname}/node_modules/svelte/compiler.cjs`, }, testMatch: ['**/*[-.](spec|test).[jt]s?(x)', '!**/cypress/**'], testEnvironment: env, diff --git a/packages/graphql-language-service-server/package.json b/packages/graphql-language-service-server/package.json index ea1272d427b..99348f2ca53 100644 --- a/packages/graphql-language-service-server/package.json +++ b/packages/graphql-language-service-server/package.json @@ -50,12 +50,13 @@ "mkdirp": "^1.0.4", "node-abort-controller": "^3.0.1", "nullthrows": "^1.0.0", - "svelte": "^4.0.0", - "svelte2tsx": "^0.6.16", "vscode-jsonrpc": "^8.0.1", "vscode-languageserver": "^8.0.1", - "vscode-languageserver-types": "^3.17.1", - "vscode-uri": "^3.0.2" + "vscode-languageserver-types": "^3.17.2", + "vscode-uri": "^3.0.2", + "svelte2tsx": "^0.6.19", + "svelte": "^4.1.1", + "source-map-js": "1.0.2" }, "devDependencies": { "@types/glob": "^8.1.0", diff --git a/packages/graphql-language-service-server/src/GraphQLCache.ts b/packages/graphql-language-service-server/src/GraphQLCache.ts index 7a3e0da2bdb..f7b043e5676 100644 --- a/packages/graphql-language-service-server/src/GraphQLCache.ts +++ b/packages/graphql-language-service-server/src/GraphQLCache.ts @@ -27,7 +27,6 @@ import type { ObjectTypeInfo, Uri, } from 'graphql-language-service'; -import type { Logger } from 'vscode-languageserver'; import * as fs from 'node:fs'; import { readFile } from 'node:fs/promises'; @@ -48,6 +47,11 @@ import glob from 'glob'; import { LoadConfigOptions } from './types'; import { URI } from 'vscode-uri'; import { CodeFileLoader } from '@graphql-tools/code-file-loader'; +import { + DEFAULT_SUPPORTED_EXTENSIONS, + DEFAULT_SUPPORTED_GRAPHQL_EXTENSIONS, +} from './constants'; +import { NoopLogger, Logger } from './Logger'; const LanguageServiceExtension: GraphQLExtensionDeclaration = api => { // For schema @@ -68,7 +72,7 @@ export async function getGraphQLCache({ config, }: { parser: typeof parseDocument; - logger: Logger; + logger: Logger | NoopLogger; loadConfigOptions: LoadConfigOptions; config?: GraphQLConfig; }): Promise { @@ -98,7 +102,7 @@ export class GraphQLCache implements GraphQLCacheInterface { _fragmentDefinitionsCache: Map>; _typeDefinitionsCache: Map>; _parser: typeof parseDocument; - _logger: Logger; + _logger: Logger | NoopLogger; constructor({ configDir, @@ -109,7 +113,7 @@ export class GraphQLCache implements GraphQLCacheInterface { configDir: Uri; config: GraphQLConfig; parser: typeof parseDocument; - logger: Logger; + logger: Logger | NoopLogger; }) { this._configDir = configDir; this._graphQLConfig = config; @@ -827,7 +831,13 @@ export class GraphQLCache implements GraphQLCacheInterface { let queries: CachedContent[] = []; if (content.trim().length !== 0) { try { - queries = this._parser(content, filePath); + queries = this._parser( + content, + filePath, + DEFAULT_SUPPORTED_EXTENSIONS, + DEFAULT_SUPPORTED_GRAPHQL_EXTENSIONS, + this._logger, + ); if (queries.length === 0) { // still resolve with an empty ast return { diff --git a/packages/graphql-language-service-server/src/MessageProcessor.ts b/packages/graphql-language-service-server/src/MessageProcessor.ts index 49f332f29ea..14dc2e2518e 100644 --- a/packages/graphql-language-service-server/src/MessageProcessor.ts +++ b/packages/graphql-language-service-server/src/MessageProcessor.ts @@ -53,13 +53,12 @@ import type { WorkspaceSymbolParams, Connection, DidChangeConfigurationRegistrationOptions, - Logger, } from 'vscode-languageserver/node'; import type { UnnormalizedTypeDefPointer } from '@graphql-tools/load'; import { getGraphQLCache, GraphQLCache } from './GraphQLCache'; -import { parseDocument, DEFAULT_SUPPORTED_EXTENSIONS } from './parseDocument'; +import { parseDocument } from './parseDocument'; import { printSchema, visit, parse, FragmentDefinitionNode } from 'graphql'; import { tmpdir } from 'node:os'; @@ -72,6 +71,11 @@ import { ProjectNotFoundError, } from 'graphql-config'; import type { LoadConfigOptions } from './types'; +import { + DEFAULT_SUPPORTED_EXTENSIONS, + SupportedExtensionsEnum, +} from './constants'; +import { NoopLogger, Logger } from './Logger'; const configDocLink = 'https://www.npmjs.com/package/graphql-language-service-server#user-content-graphql-configuration-file'; @@ -93,7 +97,7 @@ export class MessageProcessor { _isInitialized = false; _isGraphQLConfigMissing: boolean | null = null; _willShutdown = false; - _logger: Logger; + _logger: Logger | NoopLogger; _extensions?: GraphQLExtensionDeclaration[]; _parser: (text: string, uri: string) => CachedContent[]; _tmpDir: string; @@ -114,8 +118,8 @@ export class MessageProcessor { tmpDir, connection, }: { - logger: Logger; - fileExtensions: string[]; + logger: Logger | NoopLogger; + fileExtensions: ReadonlyArray; graphqlFileExtensions: string[]; loadConfigOptions: LoadConfigOptions; config?: GraphQLConfig; @@ -788,7 +792,7 @@ export class MessageProcessor { if (parentRange && res.name) { const isInline = inlineFragments.includes(res.name); const isEmbedded = DEFAULT_SUPPORTED_EXTENSIONS.includes( - path.extname(textDocument.uri), + path.extname(textDocument.uri) as SupportedExtensionsEnum, ); if (isInline && isEmbedded) { const vOffset = parentRange.start.line; 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 16b639bb4f6..440711cdb50 100644 --- a/packages/graphql-language-service-server/src/__tests__/MessageProcessor-test.ts +++ b/packages/graphql-language-service-server/src/__tests__/MessageProcessor-test.ts @@ -35,7 +35,6 @@ describe('MessageProcessor', () => { // @ts-ignore connection: {}, logger, - fileExtensions: ['js'], graphqlFileExtensions: ['graphql'], loadConfigOptions: { rootDir: __dirname }, }); @@ -56,6 +55,7 @@ describe('MessageProcessor', () => { configDir: __dirname, config: gqlConfig, parser: parseDocument, + logger: new NoopLogger(), }); messageProcessor._languageService = { // @ts-ignore @@ -484,6 +484,7 @@ export function Example(arg: string) { }`; const contents = parseDocument(text, 'test.tsx'); + expect(contents[0].query).toEqual(` query Test { test { diff --git a/packages/graphql-language-service-server/src/__tests__/findGraphQLTags-test.ts b/packages/graphql-language-service-server/src/__tests__/findGraphQLTags-test.ts index 8596991dc01..d2f9c6d2837 100644 --- a/packages/graphql-language-service-server/src/__tests__/findGraphQLTags-test.ts +++ b/packages/graphql-language-service-server/src/__tests__/findGraphQLTags-test.ts @@ -7,15 +7,17 @@ * */ +import { Position, Range } from 'graphql-language-service'; import { findGraphQLTags as baseFindGraphQLTags } from '../findGraphQLTags'; jest.mock('../Logger'); import { NoopLogger } from '../Logger'; +import { SupportedExtensionsEnum } from '../constants'; describe('findGraphQLTags', () => { const logger = new NoopLogger(); - const findGraphQLTags = (text: string, ext: string) => + const findGraphQLTags = (text: string, ext: SupportedExtensionsEnum) => baseFindGraphQLTags(text, ext, '', logger); it('finds queries in tagged templates', async () => { @@ -315,15 +317,46 @@ query {id}`); it('finds queries in tagged templates in Svelte using normal `; const contents = findGraphQLTags(text, '.svelte'); expect(contents[0].template).toEqual(` -query {id}`); + query AllCharacters { + characters { + results { + name + id + image + } + } + } +`); + + expect(JSON.stringify(contents[0].range)).toEqual( + JSON.stringify(new Range(new Position(2, 29), new Position(12, 0))), + ); }); it('no crash in Svelte files without