diff --git a/.changeset/thin-dragons-yell.md b/.changeset/thin-dragons-yell.md new file mode 100644 index 00000000..0e7a34d3 --- /dev/null +++ b/.changeset/thin-dragons-yell.md @@ -0,0 +1,7 @@ +--- +"astro-vscode": patch +"@astrojs/check": patch +"@astrojs/language-server": patch +--- + +chore: Update `volar-service-prettier`. This is only an internal refactor and there should be no visible changes. diff --git a/packages/language-server/package.json b/packages/language-server/package.json index be9be28b..033789ad 100644 --- a/packages/language-server/package.json +++ b/packages/language-server/package.json @@ -29,12 +29,12 @@ "@volar/language-service": "~2.1.2", "@volar/typescript": "~2.1.2", "fast-glob": "^3.2.12", - "volar-service-css": "0.0.31", - "volar-service-emmet": "0.0.31", - "volar-service-html": "0.0.31", - "volar-service-prettier": "0.0.31-patch.1", - "volar-service-typescript": "0.0.31", - "volar-service-typescript-twoslash-queries": "0.0.31", + "volar-service-css": "0.0.32", + "volar-service-emmet": "0.0.32", + "volar-service-html": "0.0.32", + "volar-service-prettier": "0.0.32", + "volar-service-typescript": "0.0.32", + "volar-service-typescript-twoslash-queries": "0.0.32", "vscode-html-languageservice": "^5.1.2", "vscode-uri": "^3.0.8" }, diff --git a/packages/language-server/src/check.ts b/packages/language-server/src/check.ts index 2fc7b409..83662c10 100644 --- a/packages/language-server/src/check.ts +++ b/packages/language-server/src/check.ts @@ -11,7 +11,7 @@ import { getVueLanguageModule } from './core/vue.js'; import { getAstroInstall } from './utils.js'; import { create as createAstroService } from './plugins/astro.js'; -import { create as createTypeScriptService } from './plugins/typescript/index.js'; +import { create as createTypeScriptServices } from './plugins/typescript/index.js'; // Export those for downstream consumers export { Diagnostic, DiagnosticSeverity }; @@ -142,7 +142,7 @@ export class AstroCheck { getSvelteLanguageModule(), getVueLanguageModule(), ]; - const services = [createTypeScriptService(this.ts), createAstroService(this.ts)]; + const services = [...createTypeScriptServices(this.ts), createAstroService(this.ts)]; if (tsconfigPath) { this.linter = kit.createTypeScriptChecker(languages, services, tsconfigPath); diff --git a/packages/language-server/src/languageServerPlugin.ts b/packages/language-server/src/languageServerPlugin.ts index c69e719a..f808de29 100644 --- a/packages/language-server/src/languageServerPlugin.ts +++ b/packages/language-server/src/languageServerPlugin.ts @@ -5,6 +5,7 @@ import { ShowMessageNotification, VirtualCode, } from '@volar/language-server/node'; +import { URI } from 'vscode-uri'; import { getLanguageModule } from './core'; import { getSvelteLanguageModule } from './core/svelte.js'; import { getVueLanguageModule } from './core/vue.js'; @@ -21,7 +22,7 @@ import type { ServerOptions } from '@volar/language-server/lib/server.js'; import { create as createAstroService } from './plugins/astro.js'; import { create as createHtmlService } from './plugins/html.js'; import { create as createTypescriptAddonsService } from './plugins/typescript-addons/index.js'; -import { create as createTypeScriptService } from './plugins/typescript/index.js'; +import { create as createTypeScriptServices } from './plugins/typescript/index.js'; export function createServerOptions( connection: Connection, @@ -47,8 +48,8 @@ export function createServerOptions( createHtmlService(), createCssService(), createEmmetService(), - createTypeScriptService(ts), - createTypeScriptTwoSlashService(), + ...createTypeScriptServices(ts), + createTypeScriptTwoSlashService(ts), createTypescriptAddonsService(), createAstroService(ts), getPrettierService(), @@ -90,49 +91,65 @@ export function createServerOptions( function getPrettierService() { let prettier: ReturnType; let prettierPluginPath: ReturnType; - return createPrettierService({ - getPrettier(env) { - const workspacePath = env.typescript!.uriToFileName(env.workspaceFolder); - prettier = importPrettier(workspacePath); - prettierPluginPath = getPrettierPluginPath(workspacePath); - if (!prettier || !prettierPluginPath) { - connection.sendNotification(ShowMessageNotification.type, { - message: - "Couldn't load `prettier` or `prettier-plugin-astro`. Formatting will not work. Please make sure those two packages are installed into your project.", - type: MessageType.Warning, - }); - } - return prettier; - }, - languages: ['astro'], - ignoreIdeOptions: true, - useIdeOptionsFallback: true, - resolveConfigOptions: { - // This seems to be broken since Prettier 3, and it'll always use its cumbersome cache. Hopefully it works one day. - useCache: false, - }, - additionalOptions: async (resolvedConfig) => { - async function getAstroPrettierPlugin() { + return createPrettierService( + context => { + const workspaceUri = URI.parse(context.env.workspaceFolder); + if (workspaceUri.scheme === 'file') { + prettier = importPrettier(workspaceUri.fsPath); + prettierPluginPath = getPrettierPluginPath(workspaceUri.fsPath); if (!prettier || !prettierPluginPath) { - return []; + connection.sendNotification(ShowMessageNotification.type, { + message: + "Couldn't load `prettier` or `prettier-plugin-astro`. Formatting will not work. Please make sure those two packages are installed into your project.", + type: MessageType.Warning, + }); } + return prettier; + } + }, + { + documentSelector: ['astro'], + getFormattingOptions: async (prettier, document, formatOptions, context) => { + const filePath = URI.parse(document.uri).fsPath; + const configOptions = await prettier.resolveConfig(filePath, { + // This seems to be broken since Prettier 3, and it'll always use its cumbersome cache. Hopefully it works one day. + useCache: false, + }); + const editorOptions = await context.env.getConfiguration<{}>?.('prettier', document.uri); - const hasPluginLoadedAlready = - (await prettier.getSupportInfo()).languages.some((l: any) => l.name === 'astro') || - resolvedConfig.plugins?.includes('prettier-plugin-astro'); // getSupportInfo doesn't seems to work very well in Prettier 3 for plugins + // Return a config with the following cascade: + // - Prettier config file should always win if it exists, if it doesn't: + // - Prettier config from the VS Code extension is used, if it doesn't exist: + // - Use the editor's basic configuration settings + const resolvedConfig = { + filepath: filePath, + tabWidth: formatOptions.tabSize, + useTabs: !formatOptions.insertSpaces, + ...editorOptions, + ...configOptions, + }; - return hasPluginLoadedAlready ? [] : [prettierPluginPath]; - } + return { + ...resolvedConfig, + plugins: [ + ...await getAstroPrettierPlugin(), + ...resolvedConfig.plugins ?? [], + ], + parser: 'astro', + }; - const plugins = [...(await getAstroPrettierPlugin()), ...(resolvedConfig.plugins ?? [])]; + async function getAstroPrettierPlugin() { + if (!prettier || !prettierPluginPath) { + return []; + } - return { - ...resolvedConfig, - plugins: plugins, - parser: 'astro', - }; - }, - allowImportError: true, - }); + const hasPluginLoadedAlready = + (await prettier.getSupportInfo()).languages.some((l: any) => l.name === 'astro') || + resolvedConfig.plugins?.includes('prettier-plugin-astro'); // getSupportInfo doesn't seems to work very well in Prettier 3 for plugins + + return hasPluginLoadedAlready ? [] : [prettierPluginPath]; + } + }, + }); } } diff --git a/packages/language-server/src/plugins/typescript/index.ts b/packages/language-server/src/plugins/typescript/index.ts index 3acfd3a8..3656bd1b 100644 --- a/packages/language-server/src/plugins/typescript/index.ts +++ b/packages/language-server/src/plugins/typescript/index.ts @@ -1,71 +1,76 @@ import type { ServicePlugin, ServicePluginInstance } from '@volar/language-server'; -import { create as createTypeScriptService } from 'volar-service-typescript'; +import { create as createTypeScriptServices } from 'volar-service-typescript'; import { AstroVirtualCode } from '../../core/index.js'; import { enhancedProvideCodeActions, enhancedResolveCodeAction } from './codeActions.js'; import { enhancedProvideCompletionItems, enhancedResolveCompletionItem } from './completions.js'; import { enhancedProvideSemanticDiagnostics } from './diagnostics.js'; -export const create = (ts: typeof import('typescript')): ServicePlugin => { - const tsServicePlugin = createTypeScriptService(ts as typeof import('typescript')); - return { - ...tsServicePlugin, - create(context): ServicePluginInstance { - const typeScriptPlugin = tsServicePlugin.create(context); +export const create = (ts: typeof import('typescript')): ServicePlugin[] => { + const tsServicePlugins = createTypeScriptServices(ts as typeof import('typescript'), {}); + return tsServicePlugins.map(plugin => { + if (plugin.name === 'typescript-semantic') { return { - ...typeScriptPlugin, - async provideCompletionItems(document, position, completionContext, token) { - const originalCompletions = await typeScriptPlugin.provideCompletionItems!( - document, - position, - completionContext, - token - ); - if (!originalCompletions) return null; + ...plugin, + create(context): ServicePluginInstance { + const typeScriptPlugin = plugin.create(context); + return { + ...typeScriptPlugin, + async provideCompletionItems(document, position, completionContext, token) { + const originalCompletions = await typeScriptPlugin.provideCompletionItems!( + document, + position, + completionContext, + token + ); + if (!originalCompletions) return null; - return enhancedProvideCompletionItems(originalCompletions); - }, - async resolveCompletionItem(item, token) { - const resolvedCompletionItem = await typeScriptPlugin.resolveCompletionItem!(item, token); - if (!resolvedCompletionItem) return item; + return enhancedProvideCompletionItems(originalCompletions); + }, + async resolveCompletionItem(item, token) { + const resolvedCompletionItem = await typeScriptPlugin.resolveCompletionItem!(item, token); + if (!resolvedCompletionItem) return item; - return enhancedResolveCompletionItem(resolvedCompletionItem, context); - }, - async provideCodeActions(document, range, codeActionContext, token) { - const originalCodeActions = await typeScriptPlugin.provideCodeActions!( - document, - range, - codeActionContext, - token - ); - if (!originalCodeActions) return null; + return enhancedResolveCompletionItem(resolvedCompletionItem, context); + }, + async provideCodeActions(document, range, codeActionContext, token) { + const originalCodeActions = await typeScriptPlugin.provideCodeActions!( + document, + range, + codeActionContext, + token + ); + if (!originalCodeActions) return null; - return enhancedProvideCodeActions(originalCodeActions, context); - }, - async resolveCodeAction(codeAction, token) { - const resolvedCodeAction = await typeScriptPlugin.resolveCodeAction!(codeAction, token); - if (!resolvedCodeAction) return codeAction; + return enhancedProvideCodeActions(originalCodeActions, context); + }, + async resolveCodeAction(codeAction, token) { + const resolvedCodeAction = await typeScriptPlugin.resolveCodeAction!(codeAction, token); + if (!resolvedCodeAction) return codeAction; - return enhancedResolveCodeAction(resolvedCodeAction, context); - }, - async provideSemanticDiagnostics(document, token) { - const [_, source] = context.documents.getVirtualCodeByUri(document.uri); - const code = source?.generated?.code; - let tsxLineCount = undefined; + return enhancedResolveCodeAction(resolvedCodeAction, context); + }, + async provideSemanticDiagnostics(document, token) { + const [_, source] = context.documents.getVirtualCodeByUri(document.uri); + const code = source?.generated?.code; + let tsxLineCount = undefined; - if (code instanceof AstroVirtualCode) { - // If we have compiler errors, our TSX isn't valid so don't bother showing TS errors - if (code.hasCompilationErrors) return null; + if (code instanceof AstroVirtualCode) { + // If we have compiler errors, our TSX isn't valid so don't bother showing TS errors + if (code.hasCompilationErrors) return null; - // We'll use this to filter out diagnostics that are outside the mapped range of the TSX - tsxLineCount = code.astroMeta.tsxRanges.body.end.line; - } + // We'll use this to filter out diagnostics that are outside the mapped range of the TSX + tsxLineCount = code.astroMeta.tsxRanges.body.end.line; + } - const diagnostics = await typeScriptPlugin.provideSemanticDiagnostics!(document, token); - if (!diagnostics) return null; + const diagnostics = await typeScriptPlugin.provideSemanticDiagnostics!(document, token); + if (!diagnostics) return null; - return enhancedProvideSemanticDiagnostics(diagnostics, tsxLineCount); + return enhancedProvideSemanticDiagnostics(diagnostics, tsxLineCount); + }, + }; }, }; - }, - }; + } + return plugin; + }); }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 08ebc49d..1e2d2cd8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,23 +100,23 @@ importers: specifier: ^3.2.12 version: 3.2.12 volar-service-css: - specifier: 0.0.31 - version: 0.0.31(@volar/language-service@2.1.2) + specifier: 0.0.32 + version: 0.0.32(@volar/language-service@2.1.2) volar-service-emmet: - specifier: 0.0.31 - version: 0.0.31(@volar/language-service@2.1.2) + specifier: 0.0.32 + version: 0.0.32(@volar/language-service@2.1.2) volar-service-html: - specifier: 0.0.31 - version: 0.0.31(@volar/language-service@2.1.2) + specifier: 0.0.32 + version: 0.0.32(@volar/language-service@2.1.2) volar-service-prettier: - specifier: 0.0.31-patch.1 - version: 0.0.31-patch.1(@volar/language-service@2.1.2)(prettier@3.2.5) + specifier: 0.0.32 + version: 0.0.32(@volar/language-service@2.1.2)(prettier@3.2.5) volar-service-typescript: - specifier: 0.0.31 - version: 0.0.31(@volar/language-service@2.1.2)(@volar/typescript@2.1.2) + specifier: 0.0.32 + version: 0.0.32(@volar/language-service@2.1.2) volar-service-typescript-twoslash-queries: - specifier: 0.0.31 - version: 0.0.31(@volar/language-service@2.1.2) + specifier: 0.0.32 + version: 0.0.32(@volar/language-service@2.1.2) vscode-html-languageservice: specifier: ^5.1.2 version: 5.1.2 @@ -6531,6 +6531,7 @@ packages: /strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} + requiresBuild: true dev: true optional: true @@ -7138,8 +7139,8 @@ packages: vite: 5.0.12(@types/node@18.17.8) dev: true - /volar-service-css@0.0.31(@volar/language-service@2.1.2): - resolution: {integrity: sha512-YDY+qwqYipkXVwh63f9Lk7x/48j9lsxVeXj9lsj5Fp1VAwpPoVpWQhAq3oNp3my9gyS8lEbdIPl0rJzBcJCuUA==} + /volar-service-css@0.0.32(@volar/language-service@2.1.2): + resolution: {integrity: sha512-ZqA2CuC9w008jiJ3nzx9bgAhdJXElcYTADlOQgJ0gPMRmXrO8P09gW63XZfJvsPVKizC5t7Pf6Jph9c78BpI/Q==} peerDependencies: '@volar/language-service': ~2.1.0 peerDependenciesMeta: @@ -7152,8 +7153,8 @@ packages: vscode-uri: 3.0.8 dev: false - /volar-service-emmet@0.0.31(@volar/language-service@2.1.2): - resolution: {integrity: sha512-d+KfC0axTB6Ku4v70So3GEqsEzrE9zifDvwnqHUrg+Bts05kCFlRgDCLziXmddKhtaaJJ6oSizHr7WcFUyesww==} + /volar-service-emmet@0.0.32(@volar/language-service@2.1.2): + resolution: {integrity: sha512-B62l1PD6Wfcvun7cXFtNez1DnUYGX+soV8Uu5eO275v8zGc2vueR17rEgpPqxcaMQhxpk/WLKt3OPAMERu7yYg==} peerDependencies: '@volar/language-service': ~2.1.0 peerDependenciesMeta: @@ -7165,8 +7166,8 @@ packages: vscode-html-languageservice: 5.1.2 dev: false - /volar-service-html@0.0.31(@volar/language-service@2.1.2): - resolution: {integrity: sha512-duMjl/VLvPWtmYsIAUtwYw/esFY3FWnVmH7537UpnfY9ncYTX/G43xmoVd+oQJPWh7xi8zwFeUQgZAA6T45Bhg==} + /volar-service-html@0.0.32(@volar/language-service@2.1.2): + resolution: {integrity: sha512-pFifUlywYUPx+Oz5MaGYVOiiUMkc80MI0Kyz+s+uuR26qB1pSuoqpcCr/02qMP19QdWDOD5Ak/c5B0oaBrbKMQ==} peerDependencies: '@volar/language-service': ~2.1.0 peerDependenciesMeta: @@ -7179,8 +7180,8 @@ packages: vscode-uri: 3.0.8 dev: false - /volar-service-prettier@0.0.31-patch.1(@volar/language-service@2.1.2)(prettier@3.2.5): - resolution: {integrity: sha512-jj6cKOFhOEgMUUKwdx0QUX5f7gsS0SXNqF/9LWcWslnf4C1i8GkOH+lba2yVhPMwHzltJLQOhOL5QKKB1PvKUg==} + /volar-service-prettier@0.0.32(@volar/language-service@2.1.2)(prettier@3.2.5): + resolution: {integrity: sha512-4skqVzj29u7GtM1VQJ4R0Ai0gzZshsZIzWKw2+IjzobvWn094ND77xX/qCaEHhusayqN2SyyAiauwDO5mNTj5w==} peerDependencies: '@volar/language-service': ~2.1.0 prettier: ^2.2 || ^3.0 @@ -7195,8 +7196,8 @@ packages: vscode-uri: 3.0.8 dev: false - /volar-service-typescript-twoslash-queries@0.0.31(@volar/language-service@2.1.2): - resolution: {integrity: sha512-NsI1izFST7H6GN7WQow/GEPykPLGt0zlIJl+05bX9W6pXY8kD6PUSz7U+v5TSbUMMmjFFn8IkAAHopbH11OWrA==} + /volar-service-typescript-twoslash-queries@0.0.32(@volar/language-service@2.1.2): + resolution: {integrity: sha512-eaMjxu1c1qlc3n1Ug7pwQ9tIaRkPUfNYIKxvutUSSomNlwU8eQvJQOg+4qV4c3239dYcaU6FdhT3Bb+U1NY52A==} peerDependencies: '@volar/language-service': ~2.1.0 peerDependenciesMeta: @@ -7206,17 +7207,15 @@ packages: '@volar/language-service': 2.1.2 dev: false - /volar-service-typescript@0.0.31(@volar/language-service@2.1.2)(@volar/typescript@2.1.2): - resolution: {integrity: sha512-gaSsX0NmWgENPx6KrHcj+Xru4iQWDpt1kLJcWYNJZ5XaMawYFlVXjWGX/lCO6P7AoLoc2NQnTYUpgTfTjbqdaQ==} + /volar-service-typescript@0.0.32(@volar/language-service@2.1.2): + resolution: {integrity: sha512-pgVYD/Q+J0h5gN4zgioVyUEH3b8Hpc5RkuXI5x8KeEGyD3vH5YRpJUt4SrV/mzW/whlOEK/atCwnrEOdr0+zCg==} peerDependencies: '@volar/language-service': ~2.1.0 - '@volar/typescript': ~2.1.0 peerDependenciesMeta: '@volar/language-service': optional: true dependencies: '@volar/language-service': 2.1.2 - '@volar/typescript': 2.1.2 path-browserify: 1.0.1 semver: 7.5.4 typescript-auto-import-cache: 0.3.2