Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(language-server): unused resolveLanguageServiceHost hook #953

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions packages/language-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
"@astrojs/compiler": "^2.10.3",
"@astrojs/yaml2ts": "^0.2.1",
"@jridgewell/sourcemap-codec": "^1.4.15",
"@volar/kit": "~2.4.0",
"@volar/language-core": "~2.4.0",
"@volar/language-server": "~2.4.0",
"@volar/language-service": "~2.4.0",
"@volar/typescript": "~2.4.0",
"@volar/kit": "~2.4.5",
"@volar/language-core": "~2.4.5",
"@volar/language-server": "~2.4.5",
"@volar/language-service": "~2.4.5",
"@volar/typescript": "~2.4.5",
"fast-glob": "^3.2.12",
"muggle-string": "^0.4.1",
"volar-service-css": "0.0.61",
Expand All @@ -53,7 +53,7 @@
"@types/chai": "^4.3.5",
"@types/mocha": "^10.0.1",
"@types/node": "^18.17.8",
"@volar/test-utils": "~2.4.0",
"@volar/test-utils": "~2.4.5",
"astro": "^4.14.0",
"chai": "^4.3.7",
"mocha": "^10.2.0",
Expand Down
16 changes: 13 additions & 3 deletions packages/language-server/src/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as kit from '@volar/kit';
import { Diagnostic, DiagnosticSeverity } from '@volar/language-server';
import fg from 'fast-glob';
import { URI } from 'vscode-uri';
import { getAstroLanguagePlugin } from './core/index.js';
import { addAstroTypes, getAstroLanguagePlugin } from './core/index.js';
import { getSvelteLanguagePlugin } from './core/svelte.js';
import { getVueLanguagePlugin } from './core/vue.js';
import { getAstroInstall } from './utils.js';
Expand Down Expand Up @@ -137,9 +137,8 @@ export class AstroCheck {
this.ts = this.typescriptPath ? require(this.typescriptPath) : require('typescript');
const tsconfigPath = this.getTsconfig();

const astroInstall = getAstroInstall([this.workspacePath]);
const languagePlugins = [
getAstroLanguagePlugin(typeof astroInstall === 'string' ? undefined : astroInstall, this.ts),
getAstroLanguagePlugin(),
getSvelteLanguagePlugin(),
getVueLanguagePlugin(),
];
Expand All @@ -152,6 +151,12 @@ export class AstroCheck {
services,
tsconfigPath,
includeProjectReference,
({ project }) => {
const { languageServiceHost } = project.typescript!;
const astroInstall = getAstroInstall([this.workspacePath]);

addAstroTypes(typeof astroInstall === 'string' ? undefined : astroInstall, this.ts, languageServiceHost);
},
);
} else {
this.linter = kit.createTypeScriptInferredChecker(languagePlugins, services, () => {
Expand All @@ -160,6 +165,11 @@ export class AstroCheck {
ignore: ['node_modules'],
absolute: true,
});
}, undefined, ({ project }) => {
const { languageServiceHost } = project.typescript!;
const astroInstall = getAstroInstall([this.workspacePath]);

addAstroTypes(typeof astroInstall === 'string' ? undefined : astroInstall, this.ts, languageServiceHost);
});
}
}
Expand Down
133 changes: 71 additions & 62 deletions packages/language-server/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,79 @@ import { extractStylesheets } from './parseCSS';
import { parseHTML } from './parseHTML';
import { extractScriptTags } from './parseJS.js';

export function getAstroLanguagePlugin(
const decoratedHosts = new WeakSet<ts.LanguageServiceHost>();

export function addAstroTypes(
astroInstall: AstroInstall | undefined,
ts: typeof import('typescript'),
): LanguagePlugin<URI, AstroVirtualCode> {
host: ts.LanguageServiceHost
) {
if (decoratedHosts.has(host)) {
return;
}
decoratedHosts.add(host);

const getScriptFileNames = host.getScriptFileNames.bind(host);
const getCompilationSettings = host.getCompilationSettings.bind(host);

host.getScriptFileNames = () => {
const languageServerTypesDirectory = getLanguageServerTypesDir(ts);
const fileNames = getScriptFileNames();
const addedFileNames = [];

if (astroInstall) {
addedFileNames.push(
...['./env.d.ts', './astro-jsx.d.ts'].map((filePath) =>
ts.sys.resolvePath(path.resolve(astroInstall.path, filePath)),
),
);

// If Astro version is < 4.0.8, add jsx-runtime-augment.d.ts to the files to fake `JSX` being available from "astro/jsx-runtime".
// TODO: Remove this once a majority of users are on Astro 4.0.8+, erika - 2023-12-28
if (
astroInstall.version.major < 4 ||
(astroInstall.version.major === 4 &&
astroInstall.version.minor === 0 &&
astroInstall.version.patch < 8)
) {
addedFileNames.push(
...['./jsx-runtime-augment.d.ts'].map((filePath) =>
ts.sys.resolvePath(path.resolve(languageServerTypesDirectory, filePath)),
),
);
}
} else {
// If we don't have an Astro installation, add the fallback types from the language server.
// See the README in packages/language-server/types for more information.
addedFileNames.push(
...['./env.d.ts', './astro-jsx.d.ts', './jsx-runtime-fallback.d.ts'].map((f) =>
ts.sys.resolvePath(path.resolve(languageServerTypesDirectory, f)),
),
);
}

return [...fileNames, ...addedFileNames];
}
host.getCompilationSettings = () => {
const baseCompilationSettings = getCompilationSettings();
return {
...baseCompilationSettings,
module: ts.ModuleKind.ESNext ?? 99,
target: ts.ScriptTarget.ESNext ?? 99,
jsx: ts.JsxEmit.Preserve ?? 1,
resolveJsonModule: true,
allowJs: true, // Needed for inline scripts, which are virtual .js files
isolatedModules: true,
moduleResolution:
baseCompilationSettings.moduleResolution === ts.ModuleResolutionKind.Classic ||
!baseCompilationSettings.moduleResolution
? ts.ModuleResolutionKind.Node10
: baseCompilationSettings.moduleResolution,
};
};
}

export function getAstroLanguagePlugin(): LanguagePlugin<URI, AstroVirtualCode> {
return {
getLanguageId(uri) {
if (uri.path.endsWith('.astro')) {
Expand Down Expand Up @@ -66,66 +135,6 @@ export function getAstroLanguagePlugin(
}
return result;
},
resolveLanguageServiceHost(host) {
return {
...host,
getScriptFileNames() {
const languageServerTypesDirectory = getLanguageServerTypesDir(ts);
const fileNames = host.getScriptFileNames();
const addedFileNames = [];

if (astroInstall) {
addedFileNames.push(
...['./env.d.ts', './astro-jsx.d.ts'].map((filePath) =>
ts.sys.resolvePath(path.resolve(astroInstall.path, filePath)),
),
);

// If Astro version is < 4.0.8, add jsx-runtime-augment.d.ts to the files to fake `JSX` being available from "astro/jsx-runtime".
// TODO: Remove this once a majority of users are on Astro 4.0.8+, erika - 2023-12-28
if (
astroInstall.version.major < 4 ||
(astroInstall.version.major === 4 &&
astroInstall.version.minor === 0 &&
astroInstall.version.patch < 8)
) {
addedFileNames.push(
...['./jsx-runtime-augment.d.ts'].map((filePath) =>
ts.sys.resolvePath(path.resolve(languageServerTypesDirectory, filePath)),
),
);
}
} else {
// If we don't have an Astro installation, add the fallback types from the language server.
// See the README in packages/language-server/types for more information.
addedFileNames.push(
...['./env.d.ts', './astro-jsx.d.ts', './jsx-runtime-fallback.d.ts'].map((f) =>
ts.sys.resolvePath(path.resolve(languageServerTypesDirectory, f)),
),
);
}

return [...fileNames, ...addedFileNames];
},
getCompilationSettings() {
const baseCompilationSettings = host.getCompilationSettings();
return {
...baseCompilationSettings,
module: ts.ModuleKind.ESNext ?? 99,
target: ts.ScriptTarget.ESNext ?? 99,
jsx: ts.JsxEmit.Preserve ?? 1,
resolveJsonModule: true,
allowJs: true, // Needed for inline scripts, which are virtual .js files
isolatedModules: true,
moduleResolution:
baseCompilationSettings.moduleResolution === ts.ModuleResolutionKind.Classic ||
!baseCompilationSettings.moduleResolution
? ts.ModuleResolutionKind.Node10
: baseCompilationSettings.moduleResolution,
};
},
};
},
},
};
}
Expand Down
32 changes: 2 additions & 30 deletions packages/language-server/src/languageServerPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
type Connection,
type LanguagePlugin,
type LanguageServiceEnvironment,
MessageType,
ShowMessageNotification,
} from '@volar/language-server/node';
Expand All @@ -10,7 +9,6 @@ import { getAstroLanguagePlugin } from './core';
import { getSvelteLanguagePlugin } from './core/svelte.js';
import { getVueLanguagePlugin } from './core/vue.js';
import { getPrettierPluginPath, importPrettier } from './importPackage.js';
import { getAstroInstall } from './utils.js';

// Services
import { create as createCssService } from 'volar-service-css';
Expand All @@ -25,43 +23,17 @@ import { create as createTypescriptAddonsService } from './plugins/typescript-ad
import { create as createTypeScriptServices } from './plugins/typescript/index.js';
import { create as createYAMLService } from './plugins/yaml.js';

export function getLanguagePlugins(
connection: Connection,
ts: typeof import('typescript'),
serviceEnv: LanguageServiceEnvironment,
tsconfig: string | undefined,
collectionConfigs: CollectionConfig[],
) {
export function getLanguagePlugins(collectionConfigs: CollectionConfig[]) {
const languagePlugins: LanguagePlugin<URI>[] = [
getAstroLanguagePlugin(),
getVueLanguagePlugin(),
getSvelteLanguagePlugin(),
];

const rootPath = tsconfig
? tsconfig.split('/').slice(0, -1).join('/')
: serviceEnv.workspaceFolders[0]!.fsPath;
const nearestPackageJson = ts.findConfigFile(rootPath, ts.sys.fileExists, 'package.json');

const astroInstall = getAstroInstall([rootPath], {
nearestPackageJson: nearestPackageJson,
readDirectory: ts.sys.readDirectory,
});

if (astroInstall === 'not-found') {
connection.sendNotification(ShowMessageNotification.type, {
message: `Couldn't find Astro in workspace "${rootPath}". Experience might be degraded. For the best experience, please make sure Astro is installed into your project and restart the language server.`,
type: MessageType.Warning,
});
}

if (collectionConfigs.length) {
languagePlugins.push(getFrontmatterLanguagePlugin(collectionConfigs));
}

languagePlugins.unshift(
getAstroLanguagePlugin(typeof astroInstall === 'string' ? undefined : astroInstall, ts),
);

return languagePlugins;
}

Expand Down
37 changes: 28 additions & 9 deletions packages/language-server/src/nodeServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ import {
createServer,
createTypeScriptProject,
loadTsdkByPath,
MessageType,
ShowMessageNotification,
} from '@volar/language-server/node';
import { URI, Utils } from 'vscode-uri';
import {
type CollectionConfig,
SUPPORTED_FRONTMATTER_EXTENSIONS_KEYS,
} from './core/frontmatterHolders.js';
import { getLanguagePlugins, getLanguageServicePlugins } from './languageServerPlugin.js';
import { addAstroTypes } from './core/index.js';
import { getAstroInstall } from './utils.js';

const connection = createConnection();
const server = createServer(connection);
Expand Down Expand Up @@ -63,16 +67,31 @@ connection.onInitialize((params) => {

return server.initialize(
params,
createTypeScriptProject(typescript, diagnosticMessages, ({ env, configFileName }) => {
createTypeScriptProject(typescript, diagnosticMessages, ({ env }) => {
return {
languagePlugins: getLanguagePlugins(
connection,
typescript,
env,
configFileName,
collectionConfigs,
),
setup() {},
languagePlugins: getLanguagePlugins(collectionConfigs),
setup({ project }) {
const { languageServiceHost, configFileName } = project.typescript!;

const rootPath = configFileName
? configFileName.split('/').slice(0, -1).join('/')
: env.workspaceFolders[0]!.fsPath;
const nearestPackageJson = typescript.findConfigFile(rootPath, typescript.sys.fileExists, 'package.json');

const astroInstall = getAstroInstall([rootPath], {
nearestPackageJson: nearestPackageJson,
readDirectory: typescript.sys.readDirectory,
});

if (astroInstall === 'not-found') {
connection.sendNotification(ShowMessageNotification.type, {
message: `Couldn't find Astro in workspace "${rootPath}". Experience might be degraded. For the best experience, please make sure Astro is installed into your project and restart the language server.`,
type: MessageType.Warning,
});
}

addAstroTypes(typeof astroInstall === 'string' ? undefined : astroInstall, typescript, languageServiceHost, false);
},
};
}),
getLanguageServicePlugins(connection, typescript, collectionConfigs),
Expand Down
4 changes: 2 additions & 2 deletions packages/ts-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
"@astrojs/compiler": "^2.10.3",
"@astrojs/yaml2ts": "^0.2.1",
"@jridgewell/sourcemap-codec": "^1.4.15",
"@volar/language-core": "~2.4.0",
"@volar/typescript": "~2.4.0",
"@volar/language-core": "~2.4.5",
"@volar/typescript": "~2.4.5",
"semver": "^7.3.8",
"vscode-languageserver-textdocument": "^1.0.11"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@
"@types/mocha": "^10.0.1",
"@types/node": "^18.17.8",
"@types/vscode": "^1.82.0",
"@volar/language-server": "~2.4.0",
"@volar/vscode": "~2.4.0",
"@volar/language-server": "~2.4.5",
"@volar/vscode": "~2.4.5",
"@vscode/test-electron": "^2.3.2",
"@vscode/vsce": "2.30.0",
"esbuild": "^0.17.19",
Expand Down
2 changes: 1 addition & 1 deletion packages/yaml2ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"yaml": "^2.5.0"
},
"devDependencies": {
"@volar/language-core": "~2.4.0",
"@volar/language-core": "~2.4.5",
"typescript": "^5.5.4"
}
}
Loading
Loading