diff --git a/extensions/vb/language-configuration.json b/extensions/vb/language-configuration.json index 53f537617c5..e5f718360f4 100644 --- a/extensions/vb/language-configuration.json +++ b/extensions/vb/language-configuration.json @@ -25,5 +25,40 @@ "start": "^\\s*#Region\\b", "end": "^\\s*#End Region\\b" } - } + }, + "indentationRules": { + "decreaseIndentPattern": { + "pattern": "^\\s*((End\\s+(If|Sub|Function|Class|Module|Enum|Structure|Interface|Namespace|With|Select|Try|While|For|Property|Get|Set|SyncLock|Using|AddHandler|RaiseEvent|RemoveHandler|Event|Operator))|Else|ElseIf|Case|Catch|Finally|Loop|Next|Wend|Until)\\b", + "flags": "i" + }, + "increaseIndentPattern": { + "pattern": "^\\s*((If|ElseIf).*Then(?!\\s+(End\\s+If))\\s*(('|REM).*)?$)|\\b(Else|While|For|Do|Select\\s+Case|Case|Sub|Function|Class|Module|Enum|Structure|Interface|Namespace|With|Try|Catch|Finally|SyncLock|Using|Property|Get|Set|AddHandler|RaiseEvent|RemoveHandler|Event|Operator)\\b(?!.*\\bEnd\\s+(If|Sub|Function|Class|Module|Enum|Structure|Interface|Namespace|With|Select|Try|While|For|Property|Get|Set|SyncLock|Using|AddHandler|RaiseEvent|RemoveHandler|Event|Operator)\\b).*(('|REM).*)?$", + "flags": "i" + } + }, + "onEnterRules": [ + // Prevent indent after End statements, block terminators (Else, ElseIf, Loop, Next, etc.) + { + "beforeText": { "pattern": "^\\s*((End\\s+(If|Sub|Function|Class|Module|Enum|Structure|Interface|Namespace|With|Select|Try|While|For|Property|Get|Set|SyncLock|Using|AddHandler|RaiseEvent|RemoveHandler|Event|Operator))|Else|ElseIf|Loop|Next|Wend|Until)\\b.*$", "flags": "i" }, + "action": { + "indent": "none" + } + }, + // Prevent indent when pressing Enter on a blank line after End statements or block terminators + { + "beforeText": "^\\s*$", + "previousLineText": { "pattern": "^\\s*((End\\s+(If|Sub|Function|Class|Module|Enum|Structure|Interface|Namespace|With|Select|Try|While|For|Property|Get|Set|SyncLock|Using|AddHandler|RaiseEvent|RemoveHandler|Event|Operator))|Else|ElseIf|Loop|Next|Wend|Until)\\b.*$", "flags": "i" }, + "action": { + "indent": "none" + } + }, + // Prevent indent after lines ending with closing parenthesis (e.g., function calls, method invocations) + { + "beforeText": { "pattern": "^[^'\"]*\\)\\s*('.*)?$", "flags": "i" }, + "afterText": "^(?!\\s*\\))", + "action": { + "indent": "none" + } + } + ] } diff --git a/src/vs/editor/contrib/indentation/test/browser/indentation.test.ts b/src/vs/editor/contrib/indentation/test/browser/indentation.test.ts index 16a300fa56f..98558263b73 100644 --- a/src/vs/editor/contrib/indentation/test/browser/indentation.test.ts +++ b/src/vs/editor/contrib/indentation/test/browser/indentation.test.ts @@ -18,7 +18,7 @@ import { NullState } from '../../../../common/languages/nullTokenize.js'; import { AutoIndentOnPaste, IndentationToSpacesCommand, IndentationToTabsCommand } from '../../browser/indentation.js'; import { withTestCodeEditor } from '../../../../test/browser/testCodeEditor.js'; import { testCommand } from '../../../../test/browser/testCommand.js'; -import { goIndentationRules, htmlIndentationRules, javascriptIndentationRules, latexIndentationRules, luaIndentationRules, phpIndentationRules, rubyIndentationRules } from '../../../../test/common/modes/supports/indentationRules.js'; +import { goIndentationRules, htmlIndentationRules, javascriptIndentationRules, latexIndentationRules, luaIndentationRules, phpIndentationRules, rubyIndentationRules, vbIndentationRules } from '../../../../test/common/modes/supports/indentationRules.js'; import { cppOnEnterRules, htmlOnEnterRules, javascriptOnEnterRules, phpOnEnterRules } from '../../../../test/common/modes/supports/onEnterRules.js'; import { TypeOperations } from '../../../../common/cursor/cursorTypeOperations.js'; import { cppBracketRules, goBracketRules, htmlBracketRules, latexBracketRules, luaBracketRules, phpBracketRules, rubyBracketRules, typescriptBracketRules, vbBracketRules } from '../../../../test/common/modes/supports/bracketRules.js'; @@ -94,6 +94,7 @@ export function registerLanguageConfiguration(languageConfigurationService: ILan case Language.VB: return languageConfigurationService.register(language, { brackets: vbBracketRules, + indentationRules: vbIndentationRules, }); case Language.Latex: return languageConfigurationService.register(language, { @@ -1737,14 +1738,14 @@ suite('Auto Indent On Type - Visual Basic', () => { assert.ok(true); }); - test.skip('issue #118932: no indentation in visual basic files', () => { + test('issue #118932: no indentation in visual basic files', () => { // https://github.com/microsoft/vscode/issues/118932 const model = createTextModel([ - 'if True then', + 'If True Then', ' Some code', - ' end i', + ' End I', ].join('\n'), languageId, {}); disposables.add(model); @@ -1752,9 +1753,9 @@ suite('Auto Indent On Type - Visual Basic', () => { editor.setSelection(new Selection(3, 10, 3, 10)); viewModel.type('f', 'keyboard'); assert.strictEqual(model.getValue(), [ - 'if True then', + 'If True Then', ' Some code', - 'end if', + 'End If', ].join('\n')); }); }); diff --git a/src/vs/editor/test/common/modes/supports/indentationRules.ts b/src/vs/editor/test/common/modes/supports/indentationRules.ts index 0967de48bff..22a9d82b6b7 100644 --- a/src/vs/editor/test/common/modes/supports/indentationRules.ts +++ b/src/vs/editor/test/common/modes/supports/indentationRules.ts @@ -40,3 +40,11 @@ export const luaIndentationRules = { decreaseIndentPattern: /^\s*((\b(elseif|else|end|until)\b)|(\})|(\)))/, increaseIndentPattern: /^((?!(\-\-)).)*((\b(else|function|then|do|repeat)\b((?!\b(end|until)\b).)*)|(\{\s*))$/, }; + +export const vbIndentationRules = { + // Decrease indent when line starts with End , Else, ElseIf, Case, Catch, Finally, Loop, Next, Wend, Until + decreaseIndentPattern: /^\s*((End\s+(If|Sub|Function|Class|Module|Enum|Structure|Interface|Namespace|With|Select|Try|While|For|Property|Get|Set|SyncLock|Using|AddHandler|RaiseEvent|RemoveHandler|Event|Operator))|Else|ElseIf|Case|Catch|Finally|Loop|Next|Wend|Until)\b/i, + // Increase indent after lines ending with Then, or lines starting with If/While/For/Do/Select/Sub/Function/Class/etc (block-starting keywords) + // The pattern matches lines that start block structures but excludes lines that also end them (like single-line If...Then...End If) + increaseIndentPattern: /^\s*((If|ElseIf).*Then(?!\s+(End\s+If))\s*(('|REM).*)?$)|\b(Else|While|For|Do|Select\s+Case|Case|Sub|Function|Class|Module|Enum|Structure|Interface|Namespace|With|Try|Catch|Finally|SyncLock|Using|Property|Get|Set|AddHandler|RaiseEvent|RemoveHandler|Event|Operator)\b(?!.*\bEnd\s+(If|Sub|Function|Class|Module|Enum|Structure|Interface|Namespace|With|Select|Try|While|For|Property|Get|Set|SyncLock|Using|AddHandler|RaiseEvent|RemoveHandler|Event|Operator)\b).*(('|REM).*)?$/i, +};