Skip to content

Commit

Permalink
fix: onDidChangeConfiguration not working on document features server
Browse files Browse the repository at this point in the history
close #1210
  • Loading branch information
johnsoncodehk committed Apr 18, 2022
1 parent ce17114 commit 11b288a
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 96 deletions.
Expand Up @@ -15,6 +15,7 @@ export function activate(context: vscode.ExtensionContext) {
const clientOptions: lsp.LanguageClientOptions = {
documentSelector,
initializationOptions: initOptions,
progressOnInitialization: true,
synchronize: {
fileEvents: vscode.workspace.createFileSystemWatcher('{**/*.vue,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.json}')
}
Expand Down
7 changes: 3 additions & 4 deletions extensions/vscode-vue-language-features/src/common.ts
Expand Up @@ -99,21 +99,21 @@ async function doActivate(context: vscode.ExtensionContext, createLc: CreateLang
'volar-language-features',
'Volar - Language Features Server',
languageFeaturesDocumentSelector,
getInitializationOptions(context, 'main-language-features', undefined, _useSecondServer),
getInitializationOptions(context, 'main-language-features', _useSecondServer),
6009,
);
docClient = _useSecondServer ? createLc(
'volar-language-features-2',
'Volar - Second Language Features Server',
languageFeaturesDocumentSelector,
getInitializationOptions(context, 'second-language-features', undefined, _useSecondServer),
getInitializationOptions(context, 'second-language-features', _useSecondServer),
6010,
) : undefined;
htmlClient = createLc(
'volar-document-features',
'Volar - Document Features Server',
documentFeaturesDocumentSelector,
getInitializationOptions(context, 'document-features', undefined, _useSecondServer),
getInitializationOptions(context, 'document-features', _useSecondServer),
6011,
);

Expand Down Expand Up @@ -197,7 +197,6 @@ function useSecondServer() {
function getInitializationOptions(
context: vscode.ExtensionContext,
mode: 'main-language-features' | 'second-language-features' | 'document-features',
initMessage: string | undefined,
useSecondServer: boolean,
) {
const initializationOptions: shared.ServerInitializationOptions = {
Expand Down
Expand Up @@ -6,7 +6,6 @@ import * as shared from '@volar/shared';
export async function activate(context: vscode.ExtensionContext, languageClient: CommonLanguageClient) {

await languageClient.onReady();
await languageClient.sendRequest(shared.InitDoneRequest.type);

const attrCases = shared.createPathMap<'kebabCase' | 'camelCase'>();
const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
Expand Down
Expand Up @@ -6,7 +6,6 @@ import * as shared from '@volar/shared';
export async function activate(context: vscode.ExtensionContext, languageClient: CommonLanguageClient) {

await languageClient.onReady();
await languageClient.sendRequest(shared.InitDoneRequest.type);

const tagCases = shared.createPathMap<'both' | 'kebabCase' | 'pascalCase' | 'unsure'>();
const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
Expand Down
Expand Up @@ -6,7 +6,6 @@ import * as path from 'path';
export async function activate(context: vscode.ExtensionContext, languageClient: CommonLanguageClient) {

await languageClient.onReady();
await languageClient.sendRequest(shared.InitDoneRequest.type);

const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
let currentTsconfig = '';
Expand Down
Expand Up @@ -24,6 +24,7 @@ export function activate(context: vscode.ExtensionContext) {
const clientOptions: lsp.LanguageClientOptions = {
documentSelector,
initializationOptions: initOptions,
progressOnInitialization: true,
synchronize: {
fileEvents: vscode.workspace.createFileSystemWatcher('{**/*.vue,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.json}')
}
Expand Down
85 changes: 32 additions & 53 deletions packages/vue-language-server/src/common.ts
Expand Up @@ -11,30 +11,19 @@ import type { FileSystemProvider } from 'vscode-html-languageservice';
export interface RuntimeEnvironment {
loadTypescript: (initOptions: shared.ServerInitializationOptions) => typeof import('typescript/lib/tsserverlibrary'),
loadTypescriptLocalized: (initOptions: shared.ServerInitializationOptions) => any,
schemaRequestHandlers: { [schema: string]: (uri: string, encoding?: BufferEncoding) => Promise<string> },
schemaRequestHandlers: { [schema: string]: (uri: string, encoding?: BufferEncoding) => Promise<string>; },
onDidChangeConfiguration?: (settings: any) => void,
fileSystemProvide: FileSystemProvider | undefined,
}

export function createLanguageServer(connection: vscode.Connection, runtimeEnv: RuntimeEnvironment) {

connection.onInitialize(onInitialize);
connection.listen();

const documents = new vscode.TextDocuments(TextDocument);
documents.listen(connection);

let inited = false;
connection.onRequest(shared.InitDoneRequest.type, async () => {
while (!inited) {
await shared.sleep(100);
}
return undefined;
});
let clientCapabilities: vscode.ClientCapabilities;

async function onInitialize(params: vscode.InitializeParams) {
connection.onInitialize(async params => {

const options: shared.ServerInitializationOptions = params.initializationOptions as any;
clientCapabilities = params.capabilities;
let folders: string[] = [];
let rootUri: URI;

Expand All @@ -57,11 +46,11 @@ export function createLanguageServer(connection: vscode.Connection, runtimeEnv:
},
};
const configuration = params.capabilities.workspace?.configuration ? connection.workspace : undefined;
const ts = runtimeEnv.loadTypescript(options);
const configHost = params.capabilities.workspace?.configuration ? createLsConfigs(folders, connection) : undefined;

if (options.documentFeatures) {

const configHost = params.capabilities.workspace?.configuration ? createLsConfigs(folders, connection) : undefined;
const ts = runtimeEnv.loadTypescript(options);
const documentService = vue.getDocumentService(
{ typescript: ts },
configHost,
Expand All @@ -75,53 +64,43 @@ export function createLanguageServer(connection: vscode.Connection, runtimeEnv:

if (options.languageFeatures) {

let projects: ReturnType<typeof createProjects> | undefined;
const lsConfigs = params.capabilities.workspace?.configuration ? createLsConfigs(folders, connection) : undefined;

const ts = runtimeEnv.loadTypescript(options);
const tsLocalized = runtimeEnv.loadTypescriptLocalized(options);
const projects = createProjects(
runtimeEnv,
folders,
ts,
tsLocalized,
options,
documents,
connection,
configHost,
() => getInferredCompilerOptions(ts, configuration),
);

(await import('./features/customFeatures')).register(connection, documents, () => projects);
(await import('./features/languageFeatures')).register(ts, connection, documents, () => projects, options.languageFeatures, params);
(await import('./features/customFeatures')).register(connection, documents, projects);
(await import('./features/languageFeatures')).register(ts, connection, documents, projects, options.languageFeatures, params);
(await import('./registers/registerlanguageFeatures')).register(options.languageFeatures!, vue.getSemanticTokenLegend(), result.capabilities);

connection.onInitialized(async () => {

const inferredCompilerOptions = await getInferredCompilerOptions(ts, configuration);
const tsLocalized = runtimeEnv.loadTypescriptLocalized(options);

if (params.capabilities.workspace?.didChangeConfiguration?.dynamicRegistration) { // TODO
connection.client.register(vscode.DidChangeConfigurationNotification.type);
}

projects = createProjects(
runtimeEnv,
folders,
ts,
tsLocalized,
options,
documents,
connection,
lsConfigs,
inferredCompilerOptions,
);

inited = true;
});
}
else {
inited = true;
}

return result;
}
});
connection.onInitialized(() => {
if (clientCapabilities.workspace?.didChangeConfiguration?.dynamicRegistration) { // TODO
connection.client.register(vscode.DidChangeConfigurationNotification.type);
}
});
connection.listen();

const documents = new vscode.TextDocuments(TextDocument);
documents.listen(connection);
}

export function loadCustomPlugins(dir: string) {
try {
const configPath = require.resolve('./volar.config.js', { paths: [dir] });
const config: { plugins?: vue.EmbeddedLanguageServicePlugin[] } = require(configPath);
const config: { plugins?: vue.EmbeddedLanguageServicePlugin[]; } = require(configPath);
// console.warn('Found', configPath, 'and loaded', config.plugins?.length, 'plugins.');
return config.plugins ?? []
return config.plugins ?? [];
}
catch (err) {
// console.warn('No volar.config.js found in', dir);
Expand Down
14 changes: 3 additions & 11 deletions packages/vue-language-server/src/features/customFeatures.ts
Expand Up @@ -7,7 +7,7 @@ import type { Projects } from '../projects';
export function register(
connection: vscode.Connection,
documents: vscode.TextDocuments<TextDocument>,
getProjects: () => Projects | undefined,
projects: Projects,
) {
connection.onRequest(shared.D3Request.type, async handler => {
// const document = documents.get(handler.uri);
Expand All @@ -17,14 +17,10 @@ export function register(
return undefined; // disable for now
});
connection.onRequest(shared.GetMatchTsConfigRequest.type, async handler => {
const projects = getProjects();
return (await projects?.getProject(handler.uri))?.tsconfig;
return (await projects.getProject(handler.uri))?.tsconfig;
});
connection.onNotification(shared.WriteVirtualFilesNotification.type, async () => {

const projects = getProjects();
if (!projects) return;

const fs = await import('fs');

for (const workspace of projects.workspaces.values()) {
Expand All @@ -50,9 +46,6 @@ export function register(
});
connection.onNotification(shared.VerifyAllScriptsNotification.type, async () => {

const projects = getProjects();
if (!projects) return;

let errors = 0;
let warnings = 0;

Expand Down Expand Up @@ -89,8 +82,7 @@ export function register(
});

async function getLanguageService(uri: string) {
const projects = await getProjects();
const project = (await projects?.getProject(uri))?.project;
const project = (await projects.getProject(uri))?.project;
return project?.getLanguageService();
}
}
36 changes: 16 additions & 20 deletions packages/vue-language-server/src/features/languageFeatures.ts
Expand Up @@ -10,7 +10,7 @@ export function register(
ts: typeof import('typescript/lib/tsserverlibrary'),
connection: vscode.Connection,
documents: vscode.TextDocuments<TextDocument>,
getProjects: () => Projects | undefined,
projects: Projects,
features: NonNullable<shared.ServerInitializationOptions['languageFeatures']>,
params: vscode.InitializeParams,
) {
Expand All @@ -32,7 +32,7 @@ export function register(
return list;
});
connection.onCompletionResolve(async item => {
const uri = (item.data as { uri?: string } | undefined)?.uri;
const uri = (item.data as { uri?: string; } | undefined)?.uri;
if (!uri) return item;
const activeSel = features.completion?.getDocumentSelectionRequest
? await connection.sendRequest(shared.GetEditorSelectionRequest.type)
Expand Down Expand Up @@ -164,27 +164,24 @@ export function register(
return languageService?.findDocumentLinks(handler.textDocument.uri);
});
connection.onWorkspaceSymbol(async (handler, token) => {
const projects = getProjects();
if (projects) {

let results: vscode.SymbolInformation[] = [];
let results: vscode.SymbolInformation[] = [];

for (const workspace of projects.workspaces.values()) {
let projects = [...workspace.projects.values()];
projects = projects.length ? projects : [workspace.getInferredProject()];
for (const project of projects) {
for (const workspace of projects.workspaces.values()) {
let projects = [...workspace.projects.values()];
projects = projects.length ? projects : [workspace.getInferredProject()];
for (const project of projects) {

if (token.isCancellationRequested)
return;
if (token.isCancellationRequested)
return;

const languageService = await (await project).getLanguageService();
const languageService = await (await project).getLanguageService();

results = results.concat(await languageService.findWorkspaceSymbols(handler.query));
}
results = results.concat(await languageService.findWorkspaceSymbols(handler.query));
}

return results;
}

return results;
});
connection.languages.callHierarchy.onPrepare(async handler => {
const languageService = await getLanguageService(handler.textDocument.uri);
Expand All @@ -198,13 +195,13 @@ export function register(
return items?.length ? items : null;
});
connection.languages.callHierarchy.onIncomingCalls(async handler => {
const data = handler.item.data as { __uri?: string } | undefined;
const data = handler.item.data as { __uri?: string; } | undefined;
const uri = data?.__uri ?? handler.item.uri;
const languageService = await getLanguageService(uri);
return languageService?.callHierarchy.getIncomingCalls(handler.item) ?? [];
});
connection.languages.callHierarchy.onOutgoingCalls(async handler => {
const data = handler.item.data as { __uri?: string } | undefined;
const data = handler.item.data as { __uri?: string; } | undefined;
const uri = data?.__uri ?? handler.item.uri;
const languageService = await getLanguageService(uri);
return languageService?.callHierarchy.getOutgoingCalls(handler.item) ?? [];
Expand Down Expand Up @@ -309,8 +306,7 @@ export function register(
}
}
async function getLanguageService(uri: string) {
const projects = await getProjects();
const project = (await projects?.getProject(uri))?.project;
const project = (await projects.getProject(uri))?.project;
return project?.getLanguageService();
}
}
10 changes: 5 additions & 5 deletions packages/vue-language-server/src/projects.ts
Expand Up @@ -21,7 +21,7 @@ export function createProjects(
documents: vscode.TextDocuments<TextDocument>,
connection: vscode.Connection,
lsConfigs: ReturnType<typeof createLsConfigs> | undefined,
inferredCompilerOptions: ts.CompilerOptions,
getInferredCompilerOptions: () => Promise<ts.CompilerOptions>,
) {

let semanticTokensReq = 0;
Expand All @@ -44,7 +44,7 @@ export function createProjects(
documents,
connection,
lsConfigs,
inferredCompilerOptions,
getInferredCompilerOptions,
));
}

Expand Down Expand Up @@ -276,7 +276,7 @@ function createWorkspace(
documents: vscode.TextDocuments<TextDocument>,
connection: vscode.Connection,
lsConfigs: ReturnType<typeof createLsConfigs> | undefined,
inferredCompilerOptions: ts.CompilerOptions,
getInferredCompilerOptions: () => Promise<ts.CompilerOptions>,
) {

const rootTsConfigs = ts.sys.readDirectory(rootPath, rootTsConfigNames, undefined, ['**/*']);
Expand Down Expand Up @@ -305,14 +305,14 @@ function createWorkspace(
};
}
}
function getInferredProject() {
async function getInferredProject() {
if (!inferredProject) {
inferredProject = createProject(
runtimeEnv,
ts,
options,
rootPath,
inferredCompilerOptions,
await getInferredCompilerOptions(),
tsLocalized,
documents,
connection,
Expand Down

0 comments on commit 11b288a

Please sign in to comment.