Skip to content

Commit a847c15

Browse files
authored
(feat) make prettier/emmet config updateable (#709)
Move prettier/emmet config into LSConfigManager to make it updateable and to have config in one place
1 parent b5e0785 commit a847c15

File tree

10 files changed

+109
-99
lines changed

10 files changed

+109
-99
lines changed

packages/language-server/src/ls-config.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { merge, get } from 'lodash';
22
import { UserPreferences } from 'typescript';
3+
import { EmmetConfiguration } from 'vscode-emmet-helper';
34

45
/**
56
* Default config for the language server.
@@ -91,7 +92,7 @@ export interface LSTypescriptConfig {
9192
};
9293
signatureHelp: {
9394
enable: boolean;
94-
}
95+
};
9596
}
9697

9798
export interface LSCSSConfig {
@@ -188,7 +189,9 @@ export class LSConfigManager {
188189
private tsUserPreferences: Record<TsUserConfigLang, UserPreferences> = {
189190
typescript: {},
190191
javascript: {}
191-
}
192+
};
193+
private prettierConfig: any = {};
194+
private emmetConfig: EmmetConfiguration = {};
192195

193196
/**
194197
* Updates config.
@@ -237,13 +240,43 @@ export class LSConfigManager {
237240
this.listeners.push(callback);
238241
}
239242

240-
updateTsUserPreferences(lang: TsUserConfigLang, config: TsUserPreferencesConfig) {
243+
updateEmmetConfig(config: EmmetConfiguration): void {
244+
this.emmetConfig = config || {};
245+
}
246+
247+
getEmmetConfig(): EmmetConfiguration {
248+
return this.emmetConfig;
249+
}
250+
251+
updatePrettierConfig(config: any): void {
252+
this.prettierConfig = config || {};
253+
}
254+
255+
getPrettierConfig(): any {
256+
return this.prettierConfig;
257+
}
258+
259+
updateTsJsUserPreferences(
260+
config: Record<
261+
TsUserConfigLang,
262+
{
263+
preferences: TsUserPreferencesConfig;
264+
}
265+
>
266+
): void {
267+
(['typescript', 'javascript'] as const).forEach((lang) => {
268+
if (config[lang]?.preferences) {
269+
this._updateTsUserPreferences(lang, config[lang].preferences);
270+
}
271+
});
272+
}
273+
274+
private _updateTsUserPreferences(lang: TsUserConfigLang, config: TsUserPreferencesConfig) {
241275
this.tsUserPreferences[lang] = Object.assign(this.tsUserPreferences[lang], {
242276
importModuleSpecifierPreference: config.importModuleSpecifier,
243277
importModuleSpecifierEnding: config.importModuleSpecifierEnding,
244278
includePackageJsonAutoImports: config.includePackageJsonAutoImports,
245279
quotePreference: config.quoteStyle
246-
247280
} as UserPreferences);
248281
}
249282

packages/language-server/src/plugins/PluginHost.ts

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,37 @@ import {
55
Color,
66
ColorInformation,
77
ColorPresentation,
8+
CompletionContext,
9+
CompletionItem,
810
CompletionList,
911
DefinitionLink,
1012
Diagnostic,
13+
FormattingOptions,
1114
Hover,
15+
Location,
1216
Position,
1317
Range,
14-
SymbolInformation,
15-
TextDocumentIdentifier,
16-
TextEdit,
17-
CompletionItem,
18-
CompletionContext,
19-
WorkspaceEdit,
20-
FormattingOptions,
2118
ReferenceContext,
22-
Location,
2319
SelectionRange,
2420
SignatureHelp,
25-
SignatureHelpContext
21+
SignatureHelpContext,
22+
SymbolInformation,
23+
TextDocumentIdentifier,
24+
TextEdit,
25+
WorkspaceEdit
2626
} from 'vscode-languageserver';
27-
import { LSConfig, LSConfigManager, TsUserConfigLang, TsUserPreferencesConfig } from '../ls-config';
2827
import { DocumentManager } from '../lib/documents';
28+
import { Logger } from '../logger';
29+
import { regexLastIndexOf } from '../utils';
2930
import {
30-
LSProvider,
31-
Plugin,
32-
OnWatchFileChanges,
3331
AppCompletionItem,
3432
FileRename,
3533
LSPProviderConfig,
36-
OnWatchFileChangesPara
34+
LSProvider,
35+
OnWatchFileChanges,
36+
OnWatchFileChangesPara,
37+
Plugin
3738
} from './interfaces';
38-
import { Logger } from '../logger';
39-
import { regexLastIndexOf } from '../utils';
4039

4140
enum ExecuteMode {
4241
None,
@@ -51,7 +50,7 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
5150
definitionLinkSupport: false
5251
};
5352

54-
constructor(private documentsManager: DocumentManager, private config: LSConfigManager) { }
53+
constructor(private documentsManager: DocumentManager) {}
5554

5655
initialize(pluginHostConfig: LSPProviderConfig) {
5756
this.pluginHostConfig = pluginHostConfig;
@@ -61,20 +60,6 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
6160
this.plugins.push(plugin);
6261
}
6362

64-
updateConfig(config: LSConfig) {
65-
this.config.update(config);
66-
}
67-
68-
updateTsUserPreferences(config: Record<TsUserConfigLang, {
69-
preferences: TsUserPreferencesConfig
70-
}>) {
71-
(['typescript', 'javascript'] as const).forEach((lang) => {
72-
if (config[lang]?.preferences) {
73-
this.config.updateTsUserPreferences(lang, config[lang].preferences);
74-
}
75-
});
76-
}
77-
7863
async getDiagnostics(textDocument: TextDocumentIdentifier): Promise<Diagnostic[]> {
7964
const document = this.getDocument(textDocument.uri);
8065
if (!document) {
@@ -397,16 +382,18 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
397382
}
398383

399384
try {
400-
return Promise.all(positions.map(async (position) => {
401-
for (const plugin of this.plugins) {
402-
const range = await plugin.getSelectionRange?.(document, position);
403-
404-
if (range) {
405-
return range;
385+
return Promise.all(
386+
positions.map(async (position) => {
387+
for (const plugin of this.plugins) {
388+
const range = await plugin.getSelectionRange?.(document, position);
389+
390+
if (range) {
391+
return range;
392+
}
406393
}
407-
}
408-
return SelectionRange.create(Range.create(position, position));
409-
}));
394+
return SelectionRange.create(Range.create(position, position));
395+
})
396+
);
410397
} catch (error) {
411398
Logger.error(error);
412399
return null;

packages/language-server/src/plugins/css/CSSPlugin.ts

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
getEmmetCompletionParticipants,
3-
doComplete as doEmmetComplete,
4-
EmmetConfiguration
5-
} from 'vscode-emmet-helper';
1+
import { getEmmetCompletionParticipants, doComplete as doEmmetComplete } from 'vscode-emmet-helper';
62
import {
73
Color,
84
ColorInformation,
@@ -28,7 +24,8 @@ import {
2824
mapSymbolInformationToOriginal,
2925
mapObjWithRangeToOriginal,
3026
mapHoverToParent,
31-
mapSelectionRangeToParent, isInTag
27+
mapSelectionRangeToParent,
28+
isInTag
3229
} from '../../lib/documents';
3330
import { LSConfigManager, LSCSSConfig } from '../../ls-config';
3431
import {
@@ -58,11 +55,7 @@ export class CSSPlugin
5855
private triggerCharacters = ['.', ':', '-', '/'];
5956
private globalVars = new GlobalVars();
6057

61-
constructor(
62-
docManager: DocumentManager,
63-
configManager: LSConfigManager,
64-
private emmetConfig?: EmmetConfiguration
65-
) {
58+
constructor(docManager: DocumentManager, configManager: LSConfigManager) {
6659
this.configManager = configManager;
6760

6861
this.globalVars.watchFiles(this.configManager.get('css.globals'));
@@ -81,12 +74,11 @@ export class CSSPlugin
8174
}
8275

8376
const cssDocument = this.getCSSDoc(document);
84-
const [range] = getLanguageService(extractLanguage(cssDocument))
85-
.getSelectionRanges(
86-
cssDocument,
87-
[cssDocument.getGeneratedPosition(position)],
88-
cssDocument.stylesheet
89-
);
77+
const [range] = getLanguageService(extractLanguage(cssDocument)).getSelectionRanges(
78+
cssDocument,
79+
[cssDocument.getGeneratedPosition(position)],
80+
cssDocument.stylesheet
81+
);
9082

9183
if (!range) {
9284
return null;
@@ -160,7 +152,7 @@ export class CSSPlugin
160152
if (isSASS(cssDocument)) {
161153
// the css language service does not support sass, still we can use
162154
// the emmet helper directly to at least get emmet completions
163-
return doEmmetComplete(document, position, 'sass', this.emmetConfig || {});
155+
return doEmmetComplete(document, position, 'sass', this.configManager.getEmmetConfig());
164156
}
165157

166158
const type = extractLanguage(cssDocument);
@@ -178,7 +170,7 @@ export class CSSPlugin
178170
cssDocument,
179171
cssDocument.getGeneratedPosition(position),
180172
getLanguage(type),
181-
this.emmetConfig || {},
173+
this.configManager.getEmmetConfig(),
182174
emmetResults
183175
)
184176
]);

packages/language-server/src/plugins/html/HTMLPlugin.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { EmmetConfiguration, getEmmetCompletionParticipants } from 'vscode-emmet-helper';
1+
import { getEmmetCompletionParticipants } from 'vscode-emmet-helper';
22
import {
33
getLanguageService,
44
HTMLDocument,
@@ -33,11 +33,7 @@ export class HTMLPlugin implements HoverProvider, CompletionsProvider {
3333
private documents = new WeakMap<Document, HTMLDocument>();
3434
private styleScriptTemplate = new Set(['template', 'style', 'script']);
3535

36-
constructor(
37-
docManager: DocumentManager,
38-
configManager: LSConfigManager,
39-
private emmetConfig?: EmmetConfiguration
40-
) {
36+
constructor(docManager: DocumentManager, configManager: LSConfigManager) {
4137
this.configManager = configManager;
4238
docManager.on('documentChange', (document) => {
4339
this.documents.set(document, document.html);
@@ -84,7 +80,7 @@ export class HTMLPlugin implements HoverProvider, CompletionsProvider {
8480
document,
8581
position,
8682
'html',
87-
this.emmetConfig || {},
83+
this.configManager.getEmmetConfig(),
8884
emmetResults
8985
)
9086
]);

packages/language-server/src/plugins/svelte/SveltePlugin.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class SveltePlugin
4040
SelectionRangeProvider {
4141
private docManager = new Map<Document, SvelteDocument>();
4242

43-
constructor(private configManager: LSConfigManager, private prettierConfig?: any) {}
43+
constructor(private configManager: LSConfigManager) {}
4444

4545
async getDiagnostics(document: Document): Promise<Diagnostic[]> {
4646
if (!this.featureEnabled('diagnostics')) {
@@ -73,15 +73,15 @@ export class SveltePlugin
7373
// Try resolving the config through prettier and fall back to possible editor config
7474
const config =
7575
returnObjectIfHasKeys(await prettier.resolveConfig(filePath, { editorconfig: true })) ||
76-
returnObjectIfHasKeys(this.prettierConfig) ||
76+
returnObjectIfHasKeys(this.configManager.getPrettierConfig()) ||
7777
// Be defensive here because IDEs other than VSCode might not have these settings
7878
(options && {
7979
tabWidth: options.tabSize,
8080
useTabs: !options.insertSpaces
8181
});
8282
// Take .prettierignore into account
8383
const fileInfo = await prettier.getFileInfo(filePath, {
84-
ignorePath: this.prettierConfig?.ignorePath ?? '.prettierignore',
84+
ignorePath: this.configManager.getPrettierConfig()?.ignorePath ?? '.prettierignore',
8585
// Sapper places stuff within src/node_modules, we want to format that, too
8686
withNodeModules: true
8787
});

packages/language-server/src/server.ts

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export function startServer(options?: LSOptions) {
8383
(textDocument) => new Document(textDocument.uri, textDocument.text)
8484
);
8585
const configManager = new LSConfigManager();
86-
const pluginHost = new PluginHost(docManager, configManager);
86+
const pluginHost = new PluginHost(docManager);
8787
let sveltePlugin: SveltePlugin = undefined as any;
8888

8989
connection.onInitialize((evt) => {
@@ -95,25 +95,19 @@ export function startServer(options?: LSOptions) {
9595
Logger.error('No workspace path set');
9696
}
9797

98+
configManager.update(evt.initializationOptions?.config || {});
99+
configManager.updateTsJsUserPreferences(evt.initializationOptions?.typescriptConfig || {});
100+
configManager.updateEmmetConfig(evt.initializationOptions?.emmetConfig || {});
101+
configManager.updatePrettierConfig(evt.initializationOptions?.prettierConfig || {});
102+
98103
pluginHost.initialize({
99104
filterIncompleteCompletions: !evt.initializationOptions
100105
?.dontFilterIncompleteCompletions,
101106
definitionLinkSupport: !!evt.capabilities.textDocument?.definition?.linkSupport
102107
});
103-
pluginHost.updateConfig(evt.initializationOptions?.config || {});
104-
pluginHost.updateTsUserPreferences(evt.initializationOptions?.typescriptConfig || {});
105-
pluginHost.register(
106-
(sveltePlugin = new SveltePlugin(
107-
configManager,
108-
evt.initializationOptions?.prettierConfig
109-
))
110-
);
111-
pluginHost.register(
112-
new HTMLPlugin(docManager, configManager, evt.initializationOptions?.emmetConfig)
113-
);
114-
pluginHost.register(
115-
new CSSPlugin(docManager, configManager, evt.initializationOptions?.emmetConfig)
116-
);
108+
pluginHost.register((sveltePlugin = new SveltePlugin(configManager)));
109+
pluginHost.register(new HTMLPlugin(docManager, configManager));
110+
pluginHost.register(new CSSPlugin(docManager, configManager));
117111
pluginHost.register(new TypeScriptPlugin(docManager, configManager, workspaceUris));
118112

119113
const clientSupportApplyEditCommand = !!evt.capabilities.workspace?.applyEdit;
@@ -206,8 +200,10 @@ export function startServer(options?: LSOptions) {
206200
connection.onPrepareRename((req) => pluginHost.prepareRename(req.textDocument, req.position));
207201

208202
connection.onDidChangeConfiguration(({ settings }) => {
209-
pluginHost.updateConfig(settings.svelte?.plugin);
210-
pluginHost.updateTsUserPreferences(settings);
203+
configManager.update(settings.svelte?.plugin);
204+
configManager.updateTsJsUserPreferences(settings);
205+
configManager.updateEmmetConfig(settings.emmet);
206+
configManager.updatePrettierConfig(settings.prettier);
211207
});
212208

213209
connection.onDidOpenTextDocument((evt) => {
@@ -284,10 +280,12 @@ export function startServer(options?: LSOptions) {
284280
);
285281

286282
connection.onDidChangeWatchedFiles((para) => {
287-
const onWatchFileChangesParas = para.changes.map((change) => ({
288-
fileName: urlToPath(change.uri),
289-
changeType: change.type
290-
})).filter((change): change is OnWatchFileChangesPara => !!change.fileName);
283+
const onWatchFileChangesParas = para.changes
284+
.map((change) => ({
285+
fileName: urlToPath(change.uri),
286+
changeType: change.type
287+
}))
288+
.filter((change): change is OnWatchFileChangesPara => !!change.fileName);
291289

292290
pluginHost.onWatchFileChanges(onWatchFileChangesParas);
293291

packages/language-server/src/svelte-check.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class SvelteCheck {
2121
(textDocument) => new Document(textDocument.uri, textDocument.text)
2222
);
2323
private configManager = new LSConfigManager();
24-
private pluginHost = new PluginHost(this.docManager, this.configManager);
24+
private pluginHost = new PluginHost(this.docManager);
2525

2626
constructor(workspacePath: string, options: SvelteCheckOptions = {}) {
2727
Logger.setLogErrorsOnly(true);
@@ -36,7 +36,7 @@ export class SvelteCheck {
3636
});
3737
// No HTMLPlugin, it does not provide diagnostics
3838
if (shouldRegister('svelte')) {
39-
this.pluginHost.register(new SveltePlugin(this.configManager, {}));
39+
this.pluginHost.register(new SveltePlugin(this.configManager));
4040
}
4141
if (shouldRegister('css')) {
4242
this.pluginHost.register(new CSSPlugin(this.docManager, this.configManager));

0 commit comments

Comments
 (0)