From 1ef84babe9257d4f0b1b5d0c9f0cc844a58d7e55 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sun, 28 Feb 2021 20:09:21 -0800 Subject: [PATCH] v2.7.1 (#57) - Fix indentation with parentheses ([#25](https://github.com/mark-wiemer/vscode-autohotkey-plus-plus/issues/25)) --- Changelog.md | 4 + demos/demo_for_ahk_v1.ahk | 8 +- package.json | 2 +- src/providers/formattingProvider.ts | 26 +++++- src/test/suite/format/demo.in.ahk | 1 - src/test/suite/format/demo.out.ahk | 1 - src/test/suite/format/format.test.ts | 36 +++++++-- src/test/suite/format/samples/demo.in.ahk | 81 +++++++++++++++++++ src/test/suite/format/samples/demo.out.ahk | 81 +++++++++++++++++++ .../insertSpacesFalse.in.ahk} | 0 .../insertSpacesFalse.out.ahk} | 0 .../format/samples/multilineString.in.ahk | 5 ++ .../format/samples/multilineString.out.ahk | 5 ++ src/test/suite/format/samples/tabSize2.in.ahk | 3 + .../suite/format/samples/tabSize2.out.ahk | 3 + src/test/suite/index.ts | 1 + 16 files changed, 240 insertions(+), 17 deletions(-) delete mode 100644 src/test/suite/format/demo.in.ahk delete mode 100644 src/test/suite/format/demo.out.ahk create mode 100644 src/test/suite/format/samples/demo.in.ahk create mode 100644 src/test/suite/format/samples/demo.out.ahk rename src/test/suite/format/{multiline.in.ahk => samples/insertSpacesFalse.in.ahk} (100%) rename src/test/suite/format/{multiline.out.ahk => samples/insertSpacesFalse.out.ahk} (100%) create mode 100644 src/test/suite/format/samples/multilineString.in.ahk create mode 100644 src/test/suite/format/samples/multilineString.out.ahk create mode 100644 src/test/suite/format/samples/tabSize2.in.ahk create mode 100644 src/test/suite/format/samples/tabSize2.out.ahk diff --git a/Changelog.md b/Changelog.md index 6f4b4f46..10385348 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,9 @@ # Changelog +## 2.7.1 - 2021-02-28 + +- Fix indentation with parentheses ([#25](https://github.com/mark-wiemer/vscode-autohotkey-plus-plus/issues/25)) + ## 2.7.0 - 2021-02-21 - Respect user choice to indent with either tabs or spaces ([#49](https://github.com/mark-wiemer/vscode-autohotkey-plus-plus/issues/49)) diff --git a/demos/demo_for_ahk_v1.ahk b/demos/demo_for_ahk_v1.ahk index f4c89cc8..4c02d737 100644 --- a/demos/demo_for_ahk_v1.ahk +++ b/demos/demo_for_ahk_v1.ahk @@ -11,13 +11,11 @@ function() if (str == "str") { MsgBox Overwrite primitive variable! } - ; Known bug: `line ` lines should be indented one level more - ; https://github.com/mark-wiemer/vscode-autohotkey-plus-plus/issues/25 str_multiline := " (LTrim - line 1 - line 2 - line 3 + line 1 + line 2 + line 3 )" int := 123 float := 123.456 diff --git a/package.json b/package.json index 9189fba6..4ed704dc 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-autohotkey-plus-plus", "displayName": "AutoHotkey Plus Plus", "description": "AutoHotkey IntelliSense, debug, and language support for VS Code, forked from AutoHotkey Plus by cweijan", - "version": "2.7.0", + "version": "2.7.1", "publisher": "mark-wiemer", "engines": { "vscode": "^1.30.0" diff --git a/src/providers/formattingProvider.ts b/src/providers/formattingProvider.ts index b1df3089..e735e445 100644 --- a/src/providers/formattingProvider.ts +++ b/src/providers/formattingProvider.ts @@ -36,7 +36,9 @@ export class FormatProvider implements vscode.DocumentFormattingEditProvider { token: vscode.CancellationToken, ): vscode.TextEdit[] { let formattedDocument = ''; + /** Current level of indentation. 0 = top-level, no indentation */ let depth = 0; + /** ??? */ let tagDepth = 0; let oneCommandCode = false; let blockComment = false; @@ -102,7 +104,7 @@ export class FormatProvider implements vscode.DocumentFormattingEditProvider { } } - // Check open and close braces + // Check close braces if (purifiedLine.match(/}/) != null) { let temp = purifiedLine.match(/}/).length; const t2 = purifiedLine.match(/{[^{}]*}/); @@ -114,6 +116,16 @@ export class FormatProvider implements vscode.DocumentFormattingEditProvider { atTopLevel = false; } } + + // Check close parens + if (purifiedLine.includes(')')) { + const openCount = purifiedLine.match(/\(/)?.length ?? 0; + const closeCount = purifiedLine.match(/\)/).length; + if (closeCount > openCount) { + depth--; + } + } + if (oneCommandCode && purifiedLine.match(/{/) != null) { let temp = purifiedLine.match(/{/).length; const t2 = purifiedLine.match(/{[^{}]*}/); @@ -130,10 +142,10 @@ export class FormatProvider implements vscode.DocumentFormattingEditProvider { depth = 0; } + // Add the indented line to the file const indentationChars = options.insertSpaces ? ' '.repeat(depth * options.tabSize) : '\t'.repeat(depth); - formattedDocument += !formattedLine || formattedLine.trim() == '' ? formattedLine @@ -157,6 +169,7 @@ export class FormatProvider implements vscode.DocumentFormattingEditProvider { atTopLevel = false; } + // Check open braces if (purifiedLine.match(/{/) != null) { let temp = purifiedLine.match(/{/).length; const t2 = purifiedLine.match(/{[^{}]*}/); @@ -169,6 +182,15 @@ export class FormatProvider implements vscode.DocumentFormattingEditProvider { } } + // Check open parens + if (purifiedLine.includes('(')) { + const openCount = purifiedLine.match(/\(/).length; + const closeCount = purifiedLine.match(/\)/)?.length ?? 0; + if (openCount > closeCount) { + depth++; + } + } + if (purifiedLine.match(/:\s*$/)) { depth++; tagDepth = depth; diff --git a/src/test/suite/format/demo.in.ahk b/src/test/suite/format/demo.in.ahk deleted file mode 100644 index 33cf2d91..00000000 --- a/src/test/suite/format/demo.in.ahk +++ /dev/null @@ -1 +0,0 @@ -foo() { } \ No newline at end of file diff --git a/src/test/suite/format/demo.out.ahk b/src/test/suite/format/demo.out.ahk deleted file mode 100644 index d7c744f4..00000000 --- a/src/test/suite/format/demo.out.ahk +++ /dev/null @@ -1 +0,0 @@ -foo() { } \ No newline at end of file diff --git a/src/test/suite/format/format.test.ts b/src/test/suite/format/format.test.ts index 9de28dfc..7a9baa3d 100644 --- a/src/test/suite/format/format.test.ts +++ b/src/test/suite/format/format.test.ts @@ -4,17 +4,35 @@ import * as path from 'path'; import * as vscode from 'vscode'; import { FormatProvider } from '../../../providers/formattingProvider'; +// Make sure const values match provided suffixes below +const inFilenameSuffix = '.in.ahk'; +const outFilenameSuffix = '.out.ahk'; interface FormatTest { + // Make sure provided suffixes match const values above + /** Name of the file, excluding the suffix (suffixes include .in.ahk, .out.ahk) */ filenameRoot: string; - options: vscode.FormattingOptions; + /** If not provided, file will be formatted with 4 spaces. */ + options?: Partial; } - +/** Default formatting options */ +const defaultOptions: vscode.FormattingOptions = { + tabSize: 4, + insertSpaces: true, +}; const formatTests: FormatTest[] = [ - { filenameRoot: 'demo', options: { tabSize: 4, insertSpaces: true } }, - { filenameRoot: 'multiline', options: { tabSize: 4, insertSpaces: false } }, + { filenameRoot: 'demo' }, + { + filenameRoot: 'insertSpacesFalse', + options: { insertSpaces: false }, + }, + { + filenameRoot: 'multilineString', + }, + { + filenameRoot: 'tabSize2', + options: { tabSize: 2 }, + }, ]; -const inFilenameSuffix = '.in.ahk'; -const outFilenameSuffix = '.out.ahk'; const filesParentPath = path.join( __dirname, @@ -26,6 +44,7 @@ const filesParentPath = path.join( 'test', 'suite', 'format', + 'samples', ); suite('Formatter', () => { @@ -45,7 +64,10 @@ suite('Formatter', () => { const formatter = new FormatProvider(); const edits = formatter.provideDocumentFormattingEdits( unformattedSampleFile, - formatTest.options, + { + ...defaultOptions, + ...formatTest.options, + }, null, ); await textEditor.edit((editBuilder) => { diff --git a/src/test/suite/format/samples/demo.in.ahk b/src/test/suite/format/samples/demo.in.ahk new file mode 100644 index 00000000..cbbba514 --- /dev/null +++ b/src/test/suite/format/samples/demo.in.ahk @@ -0,0 +1,81 @@ +globalVar := "Global" +global SuperGlobalVar := "SuperGlobal" +function() +return +function() +{ +globalVar := "Local" +SuperGlobalVar := "Local" +bool := true +str := "string" +if (str == "str") { +MsgBox Overwrite primitive variable! +} +str_multiline := " +(LTrim +line 1 +line 2 +line 3 +)" +int := 123 +float := 123.456 + +emptyArray := [] +smallArray := [1, 2, { str: "string" }] +sparseArray := { 1: 1, 3: 3 } +arrayLike := { 1: 1, 2: 2, 3: 3, length: 3 } +bigArray := [] +Loop 150 { +bigArray.push(A_Index) +} +if (bigArray == "str") { +MsgBox Overwrite object variable! +} + +obj := { str: str, int: int, float: float } +objobj := { str: str, obj: obj } +objobjobj := { str: str, int: int, obj: { str: str, obj: obj } } + +circular := {} +circular.circular := circular +instance := new Cls() + +enum := obj._NewEnum() +} +class Cls +{ +instanceVar := "instance" +static str := "string" +static num := 123 +static obj := { str: "string", int: 123, float: 123.456 } +property[] { +get { +} +} +method() { +} +} + +; Block comments and nested regions +/* ;region +Collapse me! +{ + Collapse me too! +} +*/ ;endregion + +; Function calls (with a space before parens) +foo() +bar () +baz () ; multiple spaces + +; SUBROUTINES + +; ExitApp indentation for subroutines +MySub: +foo() + ExitApp ; should not be indented at all + +; Formatting line below ternary with third operand a string value +true ? 1 : "string" + foo() ; should not be indented at all \ No newline at end of file diff --git a/src/test/suite/format/samples/demo.out.ahk b/src/test/suite/format/samples/demo.out.ahk new file mode 100644 index 00000000..28c9360e --- /dev/null +++ b/src/test/suite/format/samples/demo.out.ahk @@ -0,0 +1,81 @@ +globalVar := "Global" +global SuperGlobalVar := "SuperGlobal" +function() +return +function() +{ + globalVar := "Local" + SuperGlobalVar := "Local" + bool := true + str := "string" + if (str == "str") { + MsgBox Overwrite primitive variable! + } + str_multiline := " + (LTrim + line 1 + line 2 + line 3 + )" + int := 123 + float := 123.456 + + emptyArray := [] + smallArray := [1, 2, { str: "string" }] + sparseArray := { 1: 1, 3: 3 } + arrayLike := { 1: 1, 2: 2, 3: 3, length: 3 } + bigArray := [] + Loop 150 { + bigArray.push(A_Index) + } + if (bigArray == "str") { + MsgBox Overwrite object variable! + } + + obj := { str: str, int: int, float: float } + objobj := { str: str, obj: obj } + objobjobj := { str: str, int: int, obj: { str: str, obj: obj } } + + circular := {} + circular.circular := circular + instance := new Cls() + + enum := obj._NewEnum() +} +class Cls +{ + instanceVar := "instance" + static str := "string" + static num := 123 + static obj := { str: "string", int: 123, float: 123.456 } + property[] { + get { + } + } + method() { + } +} + +; Block comments and nested regions +/* ;region +Collapse me! +{ + Collapse me too! +} +*/ ;endregion + +; Function calls (with a space before parens) +foo() +bar () +baz () ; multiple spaces + +; SUBROUTINES + +; ExitApp indentation for subroutines +MySub: + foo() +ExitApp ; should not be indented at all + +; Formatting line below ternary with third operand a string value +true ? 1 : "string" +foo() ; should not be indented at all \ No newline at end of file diff --git a/src/test/suite/format/multiline.in.ahk b/src/test/suite/format/samples/insertSpacesFalse.in.ahk similarity index 100% rename from src/test/suite/format/multiline.in.ahk rename to src/test/suite/format/samples/insertSpacesFalse.in.ahk diff --git a/src/test/suite/format/multiline.out.ahk b/src/test/suite/format/samples/insertSpacesFalse.out.ahk similarity index 100% rename from src/test/suite/format/multiline.out.ahk rename to src/test/suite/format/samples/insertSpacesFalse.out.ahk diff --git a/src/test/suite/format/samples/multilineString.in.ahk b/src/test/suite/format/samples/multilineString.in.ahk new file mode 100644 index 00000000..aeacceca --- /dev/null +++ b/src/test/suite/format/samples/multilineString.in.ahk @@ -0,0 +1,5 @@ +x := " +(LTrim +hello world +) +" \ No newline at end of file diff --git a/src/test/suite/format/samples/multilineString.out.ahk b/src/test/suite/format/samples/multilineString.out.ahk new file mode 100644 index 00000000..a05c8e92 --- /dev/null +++ b/src/test/suite/format/samples/multilineString.out.ahk @@ -0,0 +1,5 @@ +x := " +(LTrim + hello world +) +" \ No newline at end of file diff --git a/src/test/suite/format/samples/tabSize2.in.ahk b/src/test/suite/format/samples/tabSize2.in.ahk new file mode 100644 index 00000000..73413563 --- /dev/null +++ b/src/test/suite/format/samples/tabSize2.in.ahk @@ -0,0 +1,3 @@ +foo() { +x := 1 +} \ No newline at end of file diff --git a/src/test/suite/format/samples/tabSize2.out.ahk b/src/test/suite/format/samples/tabSize2.out.ahk new file mode 100644 index 00000000..00875809 --- /dev/null +++ b/src/test/suite/format/samples/tabSize2.out.ahk @@ -0,0 +1,3 @@ +foo() { + x := 1 +} \ No newline at end of file diff --git a/src/test/suite/index.ts b/src/test/suite/index.ts index 56405395..1fe13110 100644 --- a/src/test/suite/index.ts +++ b/src/test/suite/index.ts @@ -8,6 +8,7 @@ export function run(): Promise { ui: 'tdd', }); (mocha as any).color(); + mocha.timeout(0); const testsRoot = path.resolve(__dirname, '..');