From 78ee5fb090ee5af421f90d5dc7ed27f0544bc2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Tue, 7 Sep 2021 12:01:53 +0100 Subject: [PATCH 1/3] Implement Document Formatting --- language-server/javascript/src/server.ts | 8 +++++ language-service/javascript/README.md | 1 + .../src/getGherkinFormattingEdits.ts | 26 ++++++++++++++++ language-service/javascript/src/index.ts | 1 + .../test/getGherkinFormattingEdits.test.ts | 30 +++++++++++++++++++ monaco/javascript/example/index.html | 11 +++++++ monaco/javascript/example/index.js | 2 ++ monaco/javascript/src/index.ts | 18 +++++++++++ 8 files changed, 97 insertions(+) create mode 100644 language-service/javascript/src/getGherkinFormattingEdits.ts create mode 100644 language-service/javascript/test/getGherkinFormattingEdits.test.ts diff --git a/language-server/javascript/src/server.ts b/language-server/javascript/src/server.ts index 7e77975fe6c..b31a18b7898 100644 --- a/language-server/javascript/src/server.ts +++ b/language-server/javascript/src/server.ts @@ -9,6 +9,7 @@ import { TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind, + TextEdit, } from 'vscode-languageserver/node' import { TextDocument } from 'vscode-languageserver-textdocument' @@ -17,6 +18,7 @@ import { getGherkinCompletionItems, getGherkinDiagnostics, getGherkinSemanticTokens, + getGherkinFormattingEdits, semanticTokenModifiers, semanticTokenTypes, } from '@cucumber/language-service' @@ -77,6 +79,7 @@ connection.onInitialize(async (params: InitializeParams) => { }, } : undefined, + documentFormattingProvider: true, }, } if (hasWorkspaceFolderCapability) { @@ -164,6 +167,11 @@ connection.languages.semanticTokens.on((semanticTokenParams: SemanticTokensParam return getGherkinSemanticTokens(gherkinSource, indexAndExpressions.expressions) }) +connection.onDocumentFormatting(async (params): Promise => { + const gherkinSource = documents.get(params.textDocument.uri).getText() + return getGherkinFormattingEdits(gherkinSource) +}) + documents.listen(connection) connection.listen() diff --git a/language-service/javascript/README.md b/language-service/javascript/README.md index d60b7c88292..f572dd6e30c 100644 --- a/language-service/javascript/README.md +++ b/language-service/javascript/README.md @@ -5,6 +5,7 @@ and [Cucumber Monaco](../../monaco/javascript). ## Supported features +- [x] Formatting / pretty printing - [x] Handle parse errors - [x] Code completion - [x] Steps diff --git a/language-service/javascript/src/getGherkinFormattingEdits.ts b/language-service/javascript/src/getGherkinFormattingEdits.ts new file mode 100644 index 00000000000..5f6a14a398f --- /dev/null +++ b/language-service/javascript/src/getGherkinFormattingEdits.ts @@ -0,0 +1,26 @@ +import { TextEdit } from "vscode-languageserver-types"; +import { parseGherkinDocument } from './parseGherkinDocument' +import { pretty } from '@cucumber/gherkin-utils' + +// https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#textDocument_formatting +export function getGherkinFormattingEdits(gherkinSource: string): TextEdit[] { + const { gherkinDocument } = parseGherkinDocument(gherkinSource) + const newText = pretty(gherkinDocument) + const lines = gherkinSource.split(/\r?\n/) + const line = lines.length - 1 + const character = lines[line].length + const textEdit: TextEdit = { + newText, + range: { + start: { + line: 0, + character: 0 + }, + end: { + line, + character + } + } + } + return [textEdit] +} diff --git a/language-service/javascript/src/index.ts b/language-service/javascript/src/index.ts index 7eef49c3941..318460677bf 100644 --- a/language-service/javascript/src/index.ts +++ b/language-service/javascript/src/index.ts @@ -1,3 +1,4 @@ export * from './getGherkinSemanticTokens' export * from './getGherkinDiagnostics' export * from './getGherkinCompletionItems' +export * from './getGherkinFormattingEdits' diff --git a/language-service/javascript/test/getGherkinFormattingEdits.test.ts b/language-service/javascript/test/getGherkinFormattingEdits.test.ts new file mode 100644 index 00000000000..aad2e093790 --- /dev/null +++ b/language-service/javascript/test/getGherkinFormattingEdits.test.ts @@ -0,0 +1,30 @@ +import assert from 'assert' +import { TextEdit } from 'vscode-languageserver-types' +import { getGherkinFormattingEdits } from '../src' + +describe('getGherkinFormattingEdits', () => { + it('returns text edits that prettifies a Gherkin document', () => { + const gherkinSource = `Feature: Hello +Scenario: World +Given something` + const textEdits = getGherkinFormattingEdits(gherkinSource) + const expectedTextEdit: TextEdit = { + newText: `Feature: Hello + + Scenario: World + Given something +`, + range: { + start: { + line: 0, + character: 0, + }, + end: { + line: 2, + character: 15 + } + } + } + assert.deepStrictEqual([expectedTextEdit], textEdits) + }) +}) diff --git a/monaco/javascript/example/index.html b/monaco/javascript/example/index.html index 31284e12ba6..fdf39dcebf1 100644 --- a/monaco/javascript/example/index.html +++ b/monaco/javascript/example/index.html @@ -5,6 +5,17 @@ Cucumber Monaco +

+ Monaco Editor with Cucumber Plugin +

+

+ Things you can try: +

+ diff --git a/monaco/javascript/example/index.js b/monaco/javascript/example/index.js index 131f9394961..5764b809734 100644 --- a/monaco/javascript/example/index.js +++ b/monaco/javascript/example/index.js @@ -38,6 +38,8 @@ Feature: Hello Scenario: Hi Given I have 58 cukes in my belly And this is an undefined step + | some | poorly | + | formatted | table | `, language: 'gherkin', theme: 'vs-dark', diff --git a/monaco/javascript/src/index.ts b/monaco/javascript/src/index.ts index 90104f12454..709d4f10561 100644 --- a/monaco/javascript/src/index.ts +++ b/monaco/javascript/src/index.ts @@ -3,6 +3,7 @@ import { getGherkinCompletionItems, getGherkinDiagnostics, getGherkinSemanticTokens, + getGherkinFormattingEdits, semanticTokenModifiers, semanticTokenTypes } from '@cucumber/language-service' @@ -85,4 +86,21 @@ export function configure(monaco: Monaco, index: Index | undefined, expressions: } } }) + + // Document Formatting + monaco.languages.registerDocumentFormattingEditProvider('gherkin', { + provideDocumentFormattingEdits: function (model, options, token) { + const gherkinSource = model.getValue() + const textEdits = getGherkinFormattingEdits(gherkinSource) + return textEdits.map(textEdit => ({ + range: { + startLineNumber: textEdit.range.start.line + 1, + startColumn: textEdit.range.start.character + 1, + endLineNumber: textEdit.range.end.line + 1, + endColumn: textEdit.range.end.character + 1, + }, + text: textEdit.newText + })) + } + }) } From f29f2c0aaf5f8cdb3657b32f82ba05811afbee7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Tue, 7 Sep 2021 12:15:14 +0100 Subject: [PATCH 2/3] Update changelog --- language-server/CHANGELOG.md | 4 ++++ language-service/CHANGELOG.md | 4 ++++ monaco/CHANGELOG.md | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/language-server/CHANGELOG.md b/language-server/CHANGELOG.md index c150c283f13..1ea9f61e65e 100644 --- a/language-server/CHANGELOG.md +++ b/language-server/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added +* Document Formatting + ([#1732](https://github.com/cucumber/common/pull/1732) + [aslakhellesoy]) + ### Changed ### Deprecated diff --git a/language-service/CHANGELOG.md b/language-service/CHANGELOG.md index 31edb49821d..8d2f8a319f7 100644 --- a/language-service/CHANGELOG.md +++ b/language-service/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added +* Document Formatting + ([#1732](https://github.com/cucumber/common/pull/1732) + [aslakhellesoy]) + ### Changed ### Deprecated diff --git a/monaco/CHANGELOG.md b/monaco/CHANGELOG.md index d79df4407e5..ca01e775d85 100644 --- a/monaco/CHANGELOG.md +++ b/monaco/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added +* Document Formatting + ([#1732](https://github.com/cucumber/common/pull/1732) + [aslakhellesoy]) + ### Changed ### Deprecated From 60014b5f90f65c74fd85e239d9275a0dbd8295b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Tue, 7 Sep 2021 12:16:25 +0100 Subject: [PATCH 3/3] Remove unused parameters --- monaco/javascript/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monaco/javascript/src/index.ts b/monaco/javascript/src/index.ts index 709d4f10561..5401d986d37 100644 --- a/monaco/javascript/src/index.ts +++ b/monaco/javascript/src/index.ts @@ -89,7 +89,7 @@ export function configure(monaco: Monaco, index: Index | undefined, expressions: // Document Formatting monaco.languages.registerDocumentFormattingEditProvider('gherkin', { - provideDocumentFormattingEdits: function (model, options, token) { + provideDocumentFormattingEdits: function (model) { const gherkinSource = model.getValue() const textEdits = getGherkinFormattingEdits(gherkinSource) return textEdits.map(textEdit => ({