From 290a62d7276c851a85b9083c3c59e1a53d2ccec0 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 31 Mar 2022 15:12:17 +0200 Subject: [PATCH] adopt css formatter --- package-lock.json | 58 +++++++-------- package.json | 6 +- src/language/css/cssMode.ts | 16 ++++ src/language/css/cssWorker.ts | 95 ++++++++++++++---------- src/language/css/monaco.contribution.ts | 35 ++++++++- src/language/html/monaco.contribution.ts | 4 +- website/playground/monaco.d.ts.txt | 24 +++++- website/typedoc/monaco.d.ts | 24 +++++- 8 files changed, 181 insertions(+), 81 deletions(-) diff --git a/package-lock.json b/package-lock.json index 858edd2f..3e50533e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,9 +30,9 @@ "ts-node": "^10.6.0", "typedoc": "^0.22.11", "typescript": "4.5.5", - "vscode-css-languageservice": "^5.1.12", - "vscode-html-languageservice": "^4.2.1", - "vscode-json-languageservice": "4.2.0", + "vscode-css-languageservice": "5.3.0", + "vscode-html-languageservice": "4.2.4", + "vscode-json-languageservice": "4.2.1", "vscode-languageserver-textdocument": "^1.0.4", "vscode-languageserver-types": "3.16.0", "vscode-uri": "3.0.3", @@ -2488,33 +2488,33 @@ "dev": true }, "node_modules/vscode-css-languageservice": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-5.1.12.tgz", - "integrity": "sha512-293C5C2732Rbhh3opTs+nQBpC5Dd+oYrEA8lc0OWdyt40oYmJ331FV7NMF1SLFSIcOFB5XveLiWUZak2oyc49Q==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-5.3.0.tgz", + "integrity": "sha512-ujWW855AoJlE4ETU17Gff7unlZZTHDA0w26itk9EQFMfJqi9lE6S67zOsMvcPmJf55MrnGQbojDYZRiDVaFjdA==", "dev": true, "dependencies": { - "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-textdocument": "^1.0.4", "vscode-languageserver-types": "^3.16.0", "vscode-nls": "^5.0.0", - "vscode-uri": "^3.0.2" + "vscode-uri": "^3.0.3" } }, "node_modules/vscode-html-languageservice": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-4.2.1.tgz", - "integrity": "sha512-PgaToZVXJ44nFWEBuSINdDgVV6EnpC3MnXBsysR3O5TKcAfywbYeRGRy+Y4dVR7YeUgDvtb+JkJoSkaYC0mxXQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-4.2.4.tgz", + "integrity": "sha512-1HqvXKOq9WlZyW4HTD+0XzrjZoZ/YFrgQY2PZqktbRloHXVAUKm6+cAcvZi4YqKPVn05/CK7do+KBHfuSaEdbg==", "dev": true, "dependencies": { - "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-textdocument": "^1.0.4", "vscode-languageserver-types": "^3.16.0", "vscode-nls": "^5.0.0", - "vscode-uri": "^3.0.2" + "vscode-uri": "^3.0.3" } }, "node_modules/vscode-json-languageservice": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.2.0.tgz", - "integrity": "sha512-XNawv0Vdy/sUK0S+hGf7cq/qsVAbIniGJr89TvZOqMCNJmpgKTy1e8PL1aWW0uy6BfWMG7vxa5lZb3ypuFtuGQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.2.1.tgz", + "integrity": "sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==", "dev": true, "dependencies": { "jsonc-parser": "^3.0.0", @@ -4601,33 +4601,33 @@ "dev": true }, "vscode-css-languageservice": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-5.1.12.tgz", - "integrity": "sha512-293C5C2732Rbhh3opTs+nQBpC5Dd+oYrEA8lc0OWdyt40oYmJ331FV7NMF1SLFSIcOFB5XveLiWUZak2oyc49Q==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-5.3.0.tgz", + "integrity": "sha512-ujWW855AoJlE4ETU17Gff7unlZZTHDA0w26itk9EQFMfJqi9lE6S67zOsMvcPmJf55MrnGQbojDYZRiDVaFjdA==", "dev": true, "requires": { - "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-textdocument": "^1.0.4", "vscode-languageserver-types": "^3.16.0", "vscode-nls": "^5.0.0", - "vscode-uri": "^3.0.2" + "vscode-uri": "^3.0.3" } }, "vscode-html-languageservice": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-4.2.1.tgz", - "integrity": "sha512-PgaToZVXJ44nFWEBuSINdDgVV6EnpC3MnXBsysR3O5TKcAfywbYeRGRy+Y4dVR7YeUgDvtb+JkJoSkaYC0mxXQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-4.2.4.tgz", + "integrity": "sha512-1HqvXKOq9WlZyW4HTD+0XzrjZoZ/YFrgQY2PZqktbRloHXVAUKm6+cAcvZi4YqKPVn05/CK7do+KBHfuSaEdbg==", "dev": true, "requires": { - "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-textdocument": "^1.0.4", "vscode-languageserver-types": "^3.16.0", "vscode-nls": "^5.0.0", - "vscode-uri": "^3.0.2" + "vscode-uri": "^3.0.3" } }, "vscode-json-languageservice": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.2.0.tgz", - "integrity": "sha512-XNawv0Vdy/sUK0S+hGf7cq/qsVAbIniGJr89TvZOqMCNJmpgKTy1e8PL1aWW0uy6BfWMG7vxa5lZb3ypuFtuGQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.2.1.tgz", + "integrity": "sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==", "dev": true, "requires": { "jsonc-parser": "^3.0.0", diff --git a/package.json b/package.json index b4e76c87..901c0f39 100644 --- a/package.json +++ b/package.json @@ -53,9 +53,9 @@ "ts-node": "^10.6.0", "typedoc": "^0.22.11", "typescript": "4.5.5", - "vscode-css-languageservice": "^5.1.12", - "vscode-html-languageservice": "^4.2.1", - "vscode-json-languageservice": "4.2.0", + "vscode-css-languageservice": "5.3.0", + "vscode-html-languageservice": "4.2.4", + "vscode-json-languageservice": "4.2.1", "vscode-languageserver-textdocument": "^1.0.4", "vscode-languageserver-types": "3.16.0", "vscode-uri": "3.0.3", diff --git a/src/language/css/cssMode.ts b/src/language/css/cssMode.ts index d916cb02..57301691 100644 --- a/src/language/css/cssMode.ts +++ b/src/language/css/cssMode.ts @@ -106,6 +106,22 @@ export function setupMode(defaults: LanguageServiceDefaults): IDisposable { ) ); } + if (modeConfiguration.documentFormattingEdits) { + providers.push( + languages.registerDocumentFormattingEditProvider( + languageId, + new languageFeatures.DocumentFormattingEditProvider(worker) + ) + ); + } + if (modeConfiguration.documentRangeFormattingEdits) { + providers.push( + languages.registerDocumentRangeFormattingEditProvider( + languageId, + new languageFeatures.DocumentRangeFormattingEditProvider(worker) + ) + ); + } } registerProviders(); diff --git a/src/language/css/cssWorker.ts b/src/language/css/cssWorker.ts index 5650315e..b0529192 100644 --- a/src/language/css/cssWorker.ts +++ b/src/language/css/cssWorker.ts @@ -12,7 +12,7 @@ export class CSSWorker { private _ctx: worker.IWorkerContext; private _languageService: cssService.LanguageService; - private _languageSettings: cssService.LanguageSettings; + private _languageSettings: Options; private _languageId: string; constructor(ctx: worker.IWorkerContext, createData: ICreateData) { @@ -53,10 +53,10 @@ export class CSSWorker { // --- language service host --------------- async doValidation(uri: string): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (document) { - let stylesheet = this._languageService.parseStylesheet(document); - let diagnostics = this._languageService.doValidation(document, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const diagnostics = this._languageService.doValidation(document, stylesheet); return Promise.resolve(diagnostics); } return Promise.resolve([]); @@ -65,63 +65,63 @@ export class CSSWorker { uri: string, position: cssService.Position ): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return null; } - let stylesheet = this._languageService.parseStylesheet(document); - let completions = this._languageService.doComplete(document, position, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const completions = this._languageService.doComplete(document, position, stylesheet); return Promise.resolve(completions); } async doHover(uri: string, position: cssService.Position): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return null; } - let stylesheet = this._languageService.parseStylesheet(document); - let hover = this._languageService.doHover(document, position, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const hover = this._languageService.doHover(document, position, stylesheet); return Promise.resolve(hover); } async findDefinition( uri: string, position: cssService.Position ): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return null; } - let stylesheet = this._languageService.parseStylesheet(document); - let definition = this._languageService.findDefinition(document, position, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const definition = this._languageService.findDefinition(document, position, stylesheet); return Promise.resolve(definition); } async findReferences(uri: string, position: cssService.Position): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return []; } - let stylesheet = this._languageService.parseStylesheet(document); - let references = this._languageService.findReferences(document, position, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const references = this._languageService.findReferences(document, position, stylesheet); return Promise.resolve(references); } async findDocumentHighlights( uri: string, position: cssService.Position ): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return []; } - let stylesheet = this._languageService.parseStylesheet(document); - let highlights = this._languageService.findDocumentHighlights(document, position, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const highlights = this._languageService.findDocumentHighlights(document, position, stylesheet); return Promise.resolve(highlights); } async findDocumentSymbols(uri: string): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return []; } - let stylesheet = this._languageService.parseStylesheet(document); - let symbols = this._languageService.findDocumentSymbols(document, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const symbols = this._languageService.findDocumentSymbols(document, stylesheet); return Promise.resolve(symbols); } async doCodeActions( @@ -129,21 +129,21 @@ export class CSSWorker { range: cssService.Range, context: cssService.CodeActionContext ): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return []; } - let stylesheet = this._languageService.parseStylesheet(document); - let actions = this._languageService.doCodeActions(document, range, context, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const actions = this._languageService.doCodeActions(document, range, context, stylesheet); return Promise.resolve(actions); } async findDocumentColors(uri: string): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return []; } - let stylesheet = this._languageService.parseStylesheet(document); - let colorSymbols = this._languageService.findDocumentColors(document, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const colorSymbols = this._languageService.findDocumentColors(document, stylesheet); return Promise.resolve(colorSymbols); } async getColorPresentations( @@ -151,12 +151,12 @@ export class CSSWorker { color: cssService.Color, range: cssService.Range ): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return []; } - let stylesheet = this._languageService.parseStylesheet(document); - let colorPresentations = this._languageService.getColorPresentations( + const stylesheet = this._languageService.parseStylesheet(document); + const colorPresentations = this._languageService.getColorPresentations( document, stylesheet, color, @@ -168,23 +168,23 @@ export class CSSWorker { uri: string, context?: { rangeLimit?: number } ): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return []; } - let ranges = this._languageService.getFoldingRanges(document, context); + const ranges = this._languageService.getFoldingRanges(document, context); return Promise.resolve(ranges); } async getSelectionRanges( uri: string, positions: cssService.Position[] ): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return []; } - let stylesheet = this._languageService.parseStylesheet(document); - let ranges = this._languageService.getSelectionRanges(document, positions, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const ranges = this._languageService.getSelectionRanges(document, positions, stylesheet); return Promise.resolve(ranges); } async doRename( @@ -192,17 +192,30 @@ export class CSSWorker { position: cssService.Position, newName: string ): Promise { - let document = this._getTextDocument(uri); + const document = this._getTextDocument(uri); if (!document) { return null; } - let stylesheet = this._languageService.parseStylesheet(document); - let renames = this._languageService.doRename(document, position, newName, stylesheet); + const stylesheet = this._languageService.parseStylesheet(document); + const renames = this._languageService.doRename(document, position, newName, stylesheet); return Promise.resolve(renames); } + async format( + uri: string, + range: cssService.Range | null, + options: cssService.CSSFormatConfiguration + ): Promise { + const document = this._getTextDocument(uri); + if (!document) { + return []; + } + const settings = { ...this._languageSettings.format, ...options }; + const textEdits = this._languageService.format(document, range! /* TODO */, settings); + return Promise.resolve(textEdits); + } private _getTextDocument(uri: string): cssService.TextDocument | null { - let models = this._ctx.getMirrorModels(); - for (let model of models) { + const models = this._ctx.getMirrorModels(); + for (const model of models) { if (model.uri.toString() === uri) { return cssService.TextDocument.create( uri, diff --git a/src/language/css/monaco.contribution.ts b/src/language/css/monaco.contribution.ts index b3b5d114..746c2e52 100644 --- a/src/language/css/monaco.contribution.ts +++ b/src/language/css/monaco.contribution.ts @@ -6,6 +6,15 @@ import * as mode from './cssMode'; import { languages, Emitter, IEvent } from '../../fillers/monaco-editor-core'; +export interface CSSFormatConfiguration { + /** separate selectors with newline (e.g. "a,\nbr" or "a, br"): Default: true */ + newlineBetweenSelectors?: boolean; + /** add a new line after every css rule: Default: true */ + newlineBetweenRules?: boolean; + /** ensure space around selector separators: '>', '+', '~' (e.g. "a>b" -> "a > b"): Default: false */ + spaceAroundSelectorSeparator?: boolean; +} + export interface Options { readonly validate?: boolean; readonly lint?: { @@ -32,6 +41,11 @@ export interface Options { * Configures the CSS data types known by the langauge service. */ readonly data?: CSSDataConfiguration; + + /** + * Settings for the CSS formatter. + */ + readonly format?: CSSFormatConfiguration; } export interface ModeConfiguration { @@ -89,6 +103,16 @@ export interface ModeConfiguration { * Defines whether the built-in selection range provider is enabled. */ readonly selectionRanges?: boolean; + + /** + * Defines whether the built-in document formatting edit provider is enabled. + */ + readonly documentFormattingEdits?: boolean; + + /** + * Defines whether the built-in document formatting range edit provider is enabled. + */ + readonly documentRangeFormattingEdits?: boolean; } export interface LanguageServiceDefaults { @@ -180,7 +204,12 @@ const optionsDefault: Required = { float: 'ignore', idSelector: 'ignore' }, - data: { useDefaultDataProvider: true } + data: { useDefaultDataProvider: true }, + format: { + newlineBetweenSelectors: true, + newlineBetweenRules: true, + spaceAroundSelectorSeparator: false + } }; const modeConfigurationDefault: Required = { @@ -194,7 +223,9 @@ const modeConfigurationDefault: Required = { colors: true, foldingRanges: true, diagnostics: true, - selectionRanges: true + selectionRanges: true, + documentFormattingEdits: true, + documentRangeFormattingEdits: true }; export const cssDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl( diff --git a/src/language/html/monaco.contribution.ts b/src/language/html/monaco.contribution.ts index 817f8dfb..daed532c 100644 --- a/src/language/html/monaco.contribution.ts +++ b/src/language/html/monaco.contribution.ts @@ -27,11 +27,11 @@ export interface CompletionConfiguration { export interface Options { /** - * If set, comments are tolerated. If set to false, syntax errors will be emitted for comments. + * Settings for the HTML formatter. */ readonly format?: HTMLFormatConfiguration; /** - * A list of known schemas and/or associations of schemas to file names. + * Code completion settings. */ readonly suggest?: CompletionConfiguration; /** diff --git a/website/playground/monaco.d.ts.txt b/website/playground/monaco.d.ts.txt index 2b1da12f..9d395a03 100644 --- a/website/playground/monaco.d.ts.txt +++ b/website/playground/monaco.d.ts.txt @@ -7157,6 +7157,14 @@ declare namespace monaco.worker { *--------------------------------------------------------------------------------------------*/ declare namespace monaco.languages.css { + export interface CSSFormatConfiguration { + /** separate selectors with newline (e.g. "a,\nbr" or "a, br"): Default: true */ + newlineBetweenSelectors?: boolean; + /** add a new line after every css rule: Default: true */ + newlineBetweenRules?: boolean; + /** ensure space around selector separators: '>', '+', '~' (e.g. "a>b" -> "a > b"): Default: false */ + spaceAroundSelectorSeparator?: boolean; + } export interface Options { readonly validate?: boolean; readonly lint?: { @@ -7183,6 +7191,10 @@ declare namespace monaco.languages.css { * Configures the CSS data types known by the langauge service. */ readonly data?: CSSDataConfiguration; + /** + * Settings for the CSS formatter. + */ + readonly format?: CSSFormatConfiguration; } export interface ModeConfiguration { /** @@ -7229,6 +7241,14 @@ declare namespace monaco.languages.css { * Defines whether the built-in selection range provider is enabled. */ readonly selectionRanges?: boolean; + /** + * Defines whether the built-in document formatting edit provider is enabled. + */ + readonly documentFormattingEdits?: boolean; + /** + * Defines whether the built-in document formatting range edit provider is enabled. + */ + readonly documentRangeFormattingEdits?: boolean; } export interface LanguageServiceDefaults { readonly languageId: string; @@ -7346,11 +7366,11 @@ declare namespace monaco.languages.html { } export interface Options { /** - * If set, comments are tolerated. If set to false, syntax errors will be emitted for comments. + * Settings for the HTML formatter. */ readonly format?: HTMLFormatConfiguration; /** - * A list of known schemas and/or associations of schemas to file names. + * Conde completion settings. */ readonly suggest?: CompletionConfiguration; /** diff --git a/website/typedoc/monaco.d.ts b/website/typedoc/monaco.d.ts index 2b1da12f..9d395a03 100644 --- a/website/typedoc/monaco.d.ts +++ b/website/typedoc/monaco.d.ts @@ -7157,6 +7157,14 @@ declare namespace monaco.worker { *--------------------------------------------------------------------------------------------*/ declare namespace monaco.languages.css { + export interface CSSFormatConfiguration { + /** separate selectors with newline (e.g. "a,\nbr" or "a, br"): Default: true */ + newlineBetweenSelectors?: boolean; + /** add a new line after every css rule: Default: true */ + newlineBetweenRules?: boolean; + /** ensure space around selector separators: '>', '+', '~' (e.g. "a>b" -> "a > b"): Default: false */ + spaceAroundSelectorSeparator?: boolean; + } export interface Options { readonly validate?: boolean; readonly lint?: { @@ -7183,6 +7191,10 @@ declare namespace monaco.languages.css { * Configures the CSS data types known by the langauge service. */ readonly data?: CSSDataConfiguration; + /** + * Settings for the CSS formatter. + */ + readonly format?: CSSFormatConfiguration; } export interface ModeConfiguration { /** @@ -7229,6 +7241,14 @@ declare namespace monaco.languages.css { * Defines whether the built-in selection range provider is enabled. */ readonly selectionRanges?: boolean; + /** + * Defines whether the built-in document formatting edit provider is enabled. + */ + readonly documentFormattingEdits?: boolean; + /** + * Defines whether the built-in document formatting range edit provider is enabled. + */ + readonly documentRangeFormattingEdits?: boolean; } export interface LanguageServiceDefaults { readonly languageId: string; @@ -7346,11 +7366,11 @@ declare namespace monaco.languages.html { } export interface Options { /** - * If set, comments are tolerated. If set to false, syntax errors will be emitted for comments. + * Settings for the HTML formatter. */ readonly format?: HTMLFormatConfiguration; /** - * A list of known schemas and/or associations of schemas to file names. + * Conde completion settings. */ readonly suggest?: CompletionConfiguration; /**