diff --git a/package-lock.json b/package-lock.json index a13224fa..64b1f1e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "@vscode/l10n": "^0.0.18", "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", - "prettier": "^3.8.1", "request-light": "^0.5.7", "vscode-json-languageservice": "4.1.8", "vscode-languageserver": "^9.0.0", @@ -41,6 +40,7 @@ "mocha": "11.7.1", "mocha-lcov-reporter": "^1.3.0", "nyc": "^15.1.0", + "prettier": "3.8.1", "rimraf": "^3.0.2", "sinon": "^9.0.3", "sinon-chai": "^3.5.0", @@ -5094,6 +5094,7 @@ "version": "3.8.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" diff --git a/package.json b/package.json index a50b03d7..2ac78b38 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "@vscode/l10n": "^0.0.18", "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", - "prettier": "^3.8.1", "request-light": "^0.5.7", "vscode-json-languageservice": "4.1.8", "vscode-languageserver": "^9.0.0", @@ -56,6 +55,7 @@ "mocha": "11.7.1", "mocha-lcov-reporter": "^1.3.0", "nyc": "^15.1.0", + "prettier": "3.8.1", "rimraf": "^3.0.2", "sinon": "^9.0.3", "sinon-chai": "^3.5.0", diff --git a/src/languageserver/handlers/settingsHandlers.ts b/src/languageserver/handlers/settingsHandlers.ts index 581b3f0d..b1adc891 100644 --- a/src/languageserver/handlers/settingsHandlers.ts +++ b/src/languageserver/handlers/settingsHandlers.ts @@ -106,7 +106,6 @@ export class SettingsHandler { if (settings.yaml.format) { this.yamlSettings.yamlFormatterSettings = { - proseWrap: settings.yaml.format.proseWrap || 'preserve', printWidth: settings.yaml.format.printWidth || 80, }; diff --git a/src/languageservice/services/yamlFormatter.ts b/src/languageservice/services/yamlFormatter.ts index d2eb5753..8380a8cb 100644 --- a/src/languageservice/services/yamlFormatter.ts +++ b/src/languageservice/services/yamlFormatter.ts @@ -4,20 +4,23 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Range, Position, TextEdit, FormattingOptions } from 'vscode-languageserver-types'; -import { CustomFormatterOptions, LanguageSettings } from '../yamlLanguageService'; -import { Options } from 'prettier'; -import * as yamlPlugin from 'prettier/plugins/yaml'; -import * as estreePlugin from 'prettier/plugins/estree'; -import { format } from 'prettier/standalone'; import { TextDocument } from 'vscode-languageserver-textdocument'; +import { FormattingOptions, Position, Range, TextEdit } from 'vscode-languageserver-types'; +import { parseDocument, ToStringOptions } from 'yaml'; +import { YamlVersion } from '../parser/yamlParser07'; +import { CustomFormatterOptions, LanguageSettings } from '../yamlLanguageService'; +import { getCustomTags } from '../parser/custom-tag-provider'; export class YAMLFormatter { private formatterEnabled = true; + private yamlVersion: YamlVersion = '1.2'; + private customTags: string[] = []; public configure(shouldFormat: LanguageSettings): void { if (shouldFormat) { this.formatterEnabled = shouldFormat.format; + this.yamlVersion = shouldFormat.yamlVersion; + this.customTags = shouldFormat.customTags; } } @@ -31,24 +34,28 @@ export class YAMLFormatter { try { const text = document.getText(); + const doc = parseDocument(text, { + version: this.yamlVersion, + customTags: getCustomTags(this.customTags), + }); - const prettierOptions: Options = { - parser: 'yaml', - plugins: [yamlPlugin, estreePlugin], - + const toStringOptions: ToStringOptions = { // --- FormattingOptions --- - tabWidth: (options.tabWidth as number) || options.tabSize, + indent: (options.tabWidth as number) || options.tabSize || 2, // --- CustomFormatterOptions --- singleQuote: options.singleQuote, - bracketSpacing: options.bracketSpacing, - // 'preserve' is the default for Options.proseWrap. See also server.ts - proseWrap: 'always' === options.proseWrap ? 'always' : 'never' === options.proseWrap ? 'never' : 'preserve', - printWidth: options.printWidth, - trailingComma: options.trailingComma === false ? 'none' : 'all', + flowCollectionPadding: options.bracketSpacing, + blockQuote: options.proseWrap === 'always' ? 'folded' : true, + lineWidth: Math.max(options.printWidth || 0, 22), + trailingComma: options.trailingComma === undefined ? true : options.trailingComma, }; - const formatted = await format(text, prettierOptions); + const formatted = doc.toString(toStringOptions); + + if (formatted === text) { + return []; + } return [TextEdit.replace(Range.create(Position.create(0, 0), document.positionAt(text.length)), formatted)]; } catch (error) { diff --git a/test/formatter.test.ts b/test/formatter.test.ts index ceb537c9..5f460652 100644 --- a/test/formatter.test.ts +++ b/test/formatter.test.ts @@ -86,7 +86,19 @@ describe('Formatter Tests', () => { printWidth: 20, proseWrap: 'always', }); - assert.equal(edits[0].newText, 'comments: >\n test test test\n test test test\n test test test\n test test test\n'); + assert.equal(edits[0].newText, 'comments: >\n test test test test\n test test test test\n test test test test\n'); + }); + + it('Formatting handles trailing commas (default)', async () => { + const content = `{ + key: 'value', + food: 'raisins', + airport: 'YYZ', + lightened_bulb: 'illuminating', +} +`; + const edits = await parseSetup(content, { singleQuote: true, trailingComma: true }); + assert.equal(edits.length, 0); }); it('Formatting handles trailing commas (enabled)', async () => { @@ -98,7 +110,7 @@ describe('Formatter Tests', () => { } `; const edits = await parseSetup(content, { singleQuote: true }); - assert.equal(edits[0].newText, content); + assert.equal(edits.length, 0); }); it('Formatting handles trailing commas (disabled)', async () => {