Skip to content

Commit

Permalink
chore: Update volar-service-prettier (#823)
Browse files Browse the repository at this point in the history
* chore: Upgrade `volar-service-prettier`

* bump

* fix types

* typo

* Create thin-dragons-yell.md

---------

Co-authored-by: Erika <[email protected]>
  • Loading branch information
johnsoncodehk and Princesseuh committed Mar 13, 2024
1 parent 390637f commit f1447ef
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 128 deletions.
7 changes: 7 additions & 0 deletions .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.
12 changes: 6 additions & 6 deletions packages/language-server/package.json
Expand Up @@ -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"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/language-server/src/check.ts
Expand Up @@ -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 };
Expand Down Expand Up @@ -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);
Expand Down
99 changes: 58 additions & 41 deletions packages/language-server/src/languageServerPlugin.ts
Expand Up @@ -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';
Expand All @@ -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,
Expand All @@ -47,8 +48,8 @@ export function createServerOptions(
createHtmlService(),
createCssService(),
createEmmetService(),
createTypeScriptService(ts),
createTypeScriptTwoSlashService(),
...createTypeScriptServices(ts),
createTypeScriptTwoSlashService(ts),
createTypescriptAddonsService(),
createAstroService(ts),
getPrettierService(),
Expand Down Expand Up @@ -90,49 +91,65 @@ export function createServerOptions(
function getPrettierService() {
let prettier: ReturnType<typeof importPrettier>;
let prettierPluginPath: ReturnType<typeof getPrettierPluginPath>;
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];
}
},
});
}
}
111 changes: 58 additions & 53 deletions 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<ServicePlugin>(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;
});
};

0 comments on commit f1447ef

Please sign in to comment.