Skip to content

Commit

Permalink
fix(typescript-plugin): improve named pipes reliability (#4603)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk authored Jul 22, 2024
1 parent 5b53aea commit 1d1d8d3
Show file tree
Hide file tree
Showing 5 changed files with 346 additions and 264 deletions.
72 changes: 24 additions & 48 deletions packages/language-server/lib/hybridModeProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Language, LanguagePlugin, LanguageServer, LanguageServerProject, P
import { createLanguageServiceEnvironment } from '@volar/language-server/lib/project/simpleProject';
import { createLanguage } from '@vue/language-core';
import { createLanguageService, createUriMap, LanguageService } from '@vue/language-service';
import { searchNamedPipeServerForFile, readPipeTable } from '@vue/typescript-plugin/lib/utils';
import { getReadyNamedPipePaths, onSomePipeReadyCallbacks, searchNamedPipeServerForFile } from '@vue/typescript-plugin/lib/utils';
import { URI } from 'vscode-uri';

export function createHybridModeProject(
Expand All @@ -17,26 +17,39 @@ export function createHybridModeProject(
}): void;
}>
): LanguageServerProject {
let initialized = false;
let simpleLs: Promise<LanguageService> | undefined;
let server: LanguageServer;
let pipeTableWatcher: NodeJS.Timeout | undefined;

const tsconfigProjects = createUriMap<Promise<LanguageService>>();
const project: LanguageServerProject = {
setup(_server) {
server = _server;
onSomePipeReadyCallbacks.push(() => {
server.refresh(project);
});
server.onDidChangeWatchedFiles(({ changes }) => {
for (const change of changes) {
const changeUri = URI.parse(change.uri);
if (tsconfigProjects.has(changeUri)) {
tsconfigProjects.get(changeUri)?.then(project => project.dispose());
tsconfigProjects.delete(changeUri);
server.clearPushDiagnostics();
}
}
});
const end = Date.now() + 60000;
const pipeWatcher = setInterval(() => {
getReadyNamedPipePaths();
if (Date.now() > end) {
clearInterval(pipeWatcher!);
}
}, 1000);
},
async getLanguageService(uri) {
if (!initialized) {
initialized = true;
initialize();
trackPipeTableChanges();
}
const fileName = asFileName(uri);
const projectInfo = (await searchNamedPipeServerForFile(fileName))?.projectInfo;
if (projectInfo?.kind === 1) {
const tsconfig = projectInfo.name;
const namedPipeServer = (await searchNamedPipeServerForFile(fileName));
if (namedPipeServer?.projectInfo?.kind === 1) {
const tsconfig = namedPipeServer.projectInfo.name;
const tsconfigUri = URI.file(tsconfig);
if (!tsconfigProjects.has(tsconfigUri)) {
tsconfigProjects.set(tsconfigUri, createLs(server, tsconfig));
Expand All @@ -63,10 +76,6 @@ export function createHybridModeProject(
}
tsconfigProjects.clear();
simpleLs = undefined;
if (pipeTableWatcher) {
clearInterval(pipeTableWatcher);
pipeTableWatcher = undefined;
}
},
};

Expand All @@ -76,39 +85,6 @@ export function createHybridModeProject(
return uri.fsPath.replace(/\\/g, '/');
}

function initialize() {
server.onDidChangeWatchedFiles(({ changes }) => {
for (const change of changes) {
const changeUri = URI.parse(change.uri);
if (tsconfigProjects.has(changeUri)) {
tsconfigProjects.get(changeUri)?.then(project => project.dispose());
tsconfigProjects.delete(changeUri);
server.clearPushDiagnostics();
}
}
});
}

function trackPipeTableChanges() {
if (pipeTableWatcher) {
clearInterval(pipeTableWatcher);
pipeTableWatcher = undefined;
}
let table = readPipeTable();
let remaining = 20;
pipeTableWatcher = setInterval(() => {
const newTable = readPipeTable();
if (JSON.stringify(table) !== JSON.stringify(newTable)) {
table = newTable;
server.refresh(project);
}
if (remaining-- <= 0) {
clearInterval(pipeTableWatcher);
pipeTableWatcher = undefined;
}
}, 1000);
}

async function createLs(server: LanguageServer, tsconfig: string | undefined) {
const { languagePlugins, setup } = await create({
configFileName: tsconfig,
Expand Down
11 changes: 7 additions & 4 deletions packages/typescript-plugin/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createLanguageServicePlugin, externalFiles } from '@volar/typescript/lib/quickstart/createLanguageServicePlugin';
import * as vue from '@vue/language-core';
import { proxyLanguageServiceForVue } from './lib/common';
import { projects, startNamedPipeServer } from './lib/server';
import { startNamedPipeServer } from './lib/server';

const windowsPathReg = /\\/g;

Expand All @@ -25,10 +25,13 @@ const plugin = createLanguageServicePlugin(
return {
languagePlugins: [languagePlugin],
setup: language => {
projects.set(info.project, { info, language, vueOptions });

info.languageService = proxyLanguageServiceForVue(ts, language, info.languageService, vueOptions, fileName => fileName);
startNamedPipeServer(ts, info.project.projectKind, info.project.getCurrentDirectory());
if (
info.project.projectKind === ts.server.ProjectKind.Configured
|| info.project.projectKind === ts.server.ProjectKind.Inferred
) {
startNamedPipeServer(ts, info, language, info.project.projectKind);
}

// #3963
const timer = setInterval(() => {
Expand Down
13 changes: 5 additions & 8 deletions packages/typescript-plugin/lib/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Request } from './server';
import { connect, searchNamedPipeServerForFile, sendRequestWorker } from './utils';
import { searchNamedPipeServerForFile, sendRequestWorker } from './utils';

export function collectExtractProps(
...args: Parameters<typeof import('./requests/collectExtractProps.js')['collectExtractProps']>
Expand Down Expand Up @@ -85,15 +85,12 @@ export function getElementAttrs(
}

async function sendRequest<T>(request: Request) {
const server = (await searchNamedPipeServerForFile(request.args[0]))?.server;
const server = (await searchNamedPipeServerForFile(request.args[0]));
if (!server) {
console.warn('[Vue Named Pipe Client] No server found for', request.args[0]);
return;
}
const client = await connect(server.path);
if (!client) {
console.warn('[Vue Named Pipe Client] Failed to connect to', server.path);
return;
}
return await sendRequestWorker<T>(request, client);
const res = await sendRequestWorker<T>(request, server.socket);
server.socket.end();
return res;
}
Loading

0 comments on commit 1d1d8d3

Please sign in to comment.