Skip to content

Commit

Permalink
feat: migrate to TS Plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Dec 15, 2023
1 parent 7de75d3 commit 376e0d9
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 144 deletions.
4 changes: 2 additions & 2 deletions packages/language-server/src/languageServerPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ export function createPlugin(connection: Connection): ServerPlugin {
],
resolveConfig(config, env, projectContext) {
config.languages ??= {};
if (env && projectContext?.typescript) {
const rootPath = projectContext.typescript.configFileName
if (env) {
const rootPath = projectContext?.typescript?.configFileName
? projectContext.typescript.configFileName.split('/').slice(0, -1).join('/')
: env.uriToFileName(env.workspaceFolder.uri.toString());
const nearestPackageJson = modules.typescript?.findConfigFile(
Expand Down
4 changes: 2 additions & 2 deletions packages/language-server/src/nodeServer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createConnection, startTypeScriptServer } from '@volar/language-server/node';
import { createConnection, startSimpleServer } from '@volar/language-server/node';
import { createPlugin } from './languageServerPlugin.js';

const connection = createConnection();
const plugin = createPlugin(connection);

startTypeScriptServer(connection, plugin);
startSimpleServer(connection, plugin);
2 changes: 0 additions & 2 deletions packages/ts-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,12 @@
"@volar/typescript": "2.0.0-alpha.6",
"@astrojs/compiler": "^2.2.2",
"@jridgewell/sourcemap-codec": "^1.4.15",
"semver": "^7.3.8",
"vscode-languageserver-textdocument": "^1.0.11"
},
"devDependencies": {
"@types/chai": "^4.3.5",
"@types/mocha": "^10.0.1",
"@types/node": "^18.17.8",
"@types/semver": "^7.3.13",
"chai": "^4.3.7",
"glob": "^8.0.3",
"mocha": "^10.2.0"
Expand Down
80 changes: 6 additions & 74 deletions packages/ts-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,9 @@
import { createFileProvider } from '@volar/language-core';
import {
decorateLanguageService,
decorateLanguageServiceHost,
searchExternalFiles,
} from '@volar/typescript';
import * as semver from 'semver';
import type ts from 'typescript/lib/tsserverlibrary';
import { createTSServerPlugin } from '@volar/typescript/lib/starters/createTSServerPlugin.js';
import { getLanguageModule } from './language.js';

const externalFiles = new WeakMap<ts.server.Project, string[]>();

const init: ts.server.PluginModuleFactory = (modules) => {
const { typescript: ts } = modules;
const pluginModule: ts.server.PluginModule = {
create(info) {
const virtualFiles = createFileProvider(
[getLanguageModule(ts)],
ts.sys.useCaseSensitiveFileNames,
() => {}
);

decorateLanguageService(virtualFiles, info.languageService);
decorateLanguageServiceHost(virtualFiles, info.languageServiceHost, ts, ['.astro']);

if (semver.lt(ts.version, '5.3.0')) {
// HACK: AutoImportProviderProject's script kind does not match the one of the language service host here
// this causes TypeScript to throw and crash. So, we'll fake being a TS file here for now until they fix it
// Fixed by https://github.com/microsoft/TypeScript/pull/55716
const getScriptKind = info.languageServiceHost.getScriptKind?.bind(
info.languageServiceHost.getScriptKind
);
if (getScriptKind) {
info.languageServiceHost.getScriptKind = (fileName) => {
if (fileName.endsWith('.astro')) {
return ts.ScriptKind.TS;
}
return getScriptKind(fileName);
};
}
}

return info.languageService;
},
getExternalFiles(project, updateLevel = 0) {
if (
// @ts-expect-error wait for TS 5.3
updateLevel >= (1 satisfies ts.ProgramUpdateLevel.RootNamesAndUpdate) ||
!externalFiles.has(project)
) {
const oldFiles = externalFiles.get(project);
const newFiles = searchExternalFiles(ts, project, ['.astro']);
externalFiles.set(project, newFiles);
if (oldFiles && !arrayItemsEqual(oldFiles, newFiles)) {
project.refreshDiagnostics();
}
}
return externalFiles.get(project)!;
},
export = createTSServerPlugin((ts) => {
return {
extensions: ['.astro'],
languagePlugins: [getLanguageModule(ts)],
};
return pluginModule;
};

function arrayItemsEqual(a: string[], b: string[]) {
if (a.length !== b.length) {
return false;
}
const set = new Set(a);
for (const file of b) {
if (!set.has(file)) {
return false;
}
}
return true;
}

export = init;
});
66 changes: 22 additions & 44 deletions packages/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,64 +57,42 @@
"typescriptServerPlugins": [
{
"name": "astro-ts-plugin-bundle",
"enableForWorkspaceTypeScriptVersions": true
}
],
"commands": [
{
"command": "astro.reloadProjects",
"title": "Astro: Reload Projects"
},
{
"command": "astro.findFileReferences",
"title": "Astro: Find File References"
},
{
"command": "astro.selectTypescriptVersion",
"title": "Astro: Select Typescript Version..."
},
{
"command": "astro.openTsConfig",
"title": "Astro: Open TypeScript config"
"enableForWorkspaceTypeScriptVersions": true,
"configNamespace": "typescript",
"languages": [
"astro"
]
}
],
"menus": {
"commandPalette": [
{
"command": "astro.reloadProjects",
"when": "editorLangId == astro"
},
{
"command": "astro.findFileReferences",
"when": "editorLangId == astro"
},
{
"command": "astro.selectTypescriptVersion",
"when": "editorLangId == astro"
},
"editor/context": [
{
"command": "astro.openTsConfig",
"when": "editorLangId == astro"
"command": "typescript.goToSourceDefinition",
"when": "tsSupportsSourceDefinition && resourceLangId == mdx",
"group": "navigation@9"
}
],
"editor/context": [
"explorer/context": [
{
"command": "astro.findFileReferences",
"when": "editorLangId == astro",
"command": "typescript.findAllFileReferences",
"when": "tsSupportsFileReferences && resourceLangId == mdx",
"group": "4_search"
}
],
"editor/title/context": [
{
"command": "astro.findFileReferences",
"when": "resourceLangId == astro && resourceScheme == file"
"command": "typescript.findAllFileReferences",
"when": "tsSupportsFileReferences && resourceLangId == mdx"
}
],
"explorer/context": [
"commandPalette": [
{
"command": "astro.findFileReferences",
"when": "resourceLangId == astro",
"group": "4_search"
"command": "typescript.reloadProjects",
"when": "editorLangId == mdx && typescript.isManagedFile"
},
{
"command": "typescript.goToProjectConfig",
"when": "editorLangId == mdx"
}
]
},
Expand Down Expand Up @@ -241,4 +219,4 @@
"prettier": "^3.0.0",
"prettier-plugin-astro": "^0.12.0"
}
}
}
45 changes: 31 additions & 14 deletions packages/vscode/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import { DiagnosticModel, InitializationOptions } from '@volar/language-server';
import * as protocol from '@volar/language-server/protocol';
import {
activateAutoInsertion,
activateFindFileReferences,
activateReloadProjects,
activateTsConfigStatusItem,
activateTsVersionStatusItem,
getTsdk,
supportLabsVersion,
type ExportsInfoForLabs,
Expand All @@ -17,6 +13,8 @@ import * as lsp from 'vscode-languageclient/node';
let client: lsp.BaseLanguageClient;

export async function activate(context: vscode.ExtensionContext): Promise<ExportsInfoForLabs> {
vscode.extensions.getExtension('vscode.typescript-language-features')?.activate();

const runtimeConfig = vscode.workspace.getConfiguration('astro.language-server');

const { workspaceFolders } = vscode.workspace;
Expand Down Expand Up @@ -65,22 +63,16 @@ export async function activate(context: vscode.ExtensionContext): Promise<Export
const clientOptions: lsp.LanguageClientOptions = {
documentSelector: [{ language: 'astro' }],
initializationOptions,
markdown: {
isTrusted: true,
supportHtml: true,
},
};
client = new lsp.LanguageClient('astro', 'Astro Language Server', serverOptions, clientOptions);
await client.start();

// support for auto close tag
activateAutoInsertion('astro', client);
activateFindFileReferences('astro.findFileReferences', client);
activateReloadProjects('astro.reloadProjects', client);
activateTsConfigStatusItem('astro', 'astro.openTsConfig', client);
activateTsVersionStatusItem(
'astro',
'astro.selectTypescriptVersion',
context,
client,
(text) => text
);

return {
volarLabs: {
Expand Down Expand Up @@ -142,3 +134,28 @@ async function getConfiguredServerPath(workspaceState: vscode.Memento) {
return lsPath;
}
}

// Track https://github.com/microsoft/vscode/issues/200511
try {
const tsExtension = vscode.extensions.getExtension('vscode.typescript-language-features');
if (tsExtension) {
const readFileSync = require('fs').readFileSync;
const extensionJsPath = require.resolve('./dist/extension.js', { paths: [tsExtension.extensionPath] });

// @ts-expect-error
require('fs').readFileSync = (...args) => {
if (args[0] === extensionJsPath) {
let text = readFileSync(...args) as string;

// patch jsTsLanguageModes
text = text.replace('t.$u=[t.$r,t.$s,t.$p,t.$q]', s => s + '.concat("astro")');

// patch isSupportedLanguageMode
text = text.replace('s.languages.match([t.$p,t.$q,t.$r,t.$s]', s => s + '.concat("astro")');

return text;
}
return readFileSync(...args);
};
}
} catch { }
7 changes: 1 addition & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 376e0d9

Please sign in to comment.