From c8547e570823f0238785d44fff6cf75382ec2335 Mon Sep 17 00:00:00 2001 From: Alex Ross <38270282+alexr00@users.noreply.github.com> Date: Thu, 20 Nov 2025 10:49:33 +0100 Subject: [PATCH] Update tree-sitter-wasm (#278399) * Update tree-sitter-wasm * Update test results * Update pwsh && tests, fix prompt Fixes #274548 --------- Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com> --- .../test_css.json | 84 +++++++++++++++++++ package-lock.json | 8 +- package.json | 2 +- remote/package-lock.json | 8 +- remote/package.json | 2 +- remote/web/package-lock.json | 8 +- remote/web/package.json | 2 +- .../browser/tools/runInTerminalTool.ts | 7 +- .../browser/treeSitterCommandParser.ts | 6 +- .../treeSitterCommandParser.test.ts | 29 +++---- 10 files changed, 116 insertions(+), 40 deletions(-) diff --git a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_css.json b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_css.json index 73b86795d8a..98adba8bf54 100644 --- a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_css.json +++ b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_css.json @@ -125,6 +125,20 @@ "light_modern": "string: #A31515" } }, + { + "c": "mystyle.css", + "t": "string.quoted.double.css", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178", + "dark_modern": "string: #CE9178", + "hc_light": "string: #0F4A85", + "light_modern": "string: #A31515" + } + }, { "c": "\"", "t": "string.quoted.double.css", @@ -209,6 +223,20 @@ "light_modern": "string: #A31515" } }, + { + "c": "mystyle.css", + "t": "string.quoted.double.css", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178", + "dark_modern": "string: #CE9178", + "hc_light": "string: #0F4A85", + "light_modern": "string: #A31515" + } + }, { "c": "\"", "t": "string.quoted.double.css", @@ -307,6 +335,20 @@ "light_modern": "string: #A31515" } }, + { + "c": "bluish.css", + "t": "string.quoted.double.css", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178", + "dark_modern": "string: #CE9178", + "hc_light": "string: #0F4A85", + "light_modern": "string: #A31515" + } + }, { "c": "\"", "t": "string.quoted.double.css", @@ -3387,6 +3429,20 @@ "light_modern": "string: #A31515" } }, + { + "c": "", + "t": "string.quoted.single.css", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178", + "dark_modern": "string: #CE9178", + "hc_light": "string: #0F4A85", + "light_modern": "string: #A31515" + } + }, { "c": "'", "t": "string.quoted.single.css", @@ -7307,6 +7363,20 @@ "light_modern": "string: #A31515" } }, + { + "c": "#B3AE94", + "t": "string.quoted.single.css", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178", + "dark_modern": "string: #CE9178", + "hc_light": "string: #0F4A85", + "light_modern": "string: #A31515" + } + }, { "c": "'", "t": "string.quoted.single.css", @@ -8413,6 +8483,20 @@ "light_modern": "string: #A31515" } }, + { + "c": "codicon-", + "t": "meta.selector.css string.quoted.single.css", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178", + "dark_modern": "string: #CE9178", + "hc_light": "string: #0F4A85", + "light_modern": "string: #A31515" + } + }, { "c": "'", "t": "meta.selector.css string.quoted.single.css", diff --git a/package-lock.json b/package-lock.json index 72e6541080c..5351efd3098 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@vscode/spdlog": "^0.15.2", "@vscode/sqlite3": "5.1.8-vscode", "@vscode/sudo-prompt": "9.3.1", - "@vscode/tree-sitter-wasm": "^0.2.0", + "@vscode/tree-sitter-wasm": "^0.3.0", "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-mutex": "^0.5.0", "@vscode/windows-process-tree": "^0.6.0", @@ -3325,9 +3325,9 @@ } }, "node_modules/@vscode/tree-sitter-wasm": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.2.0.tgz", - "integrity": "sha512-abvLfKwmriqgdS4WrIzFK7mzdPUVqIIW1UWarp2lA8lpOZ1EDPL1snRBKe7g+5R5ri173mNJEuPLnG/NlpMp4w==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.3.0.tgz", + "integrity": "sha512-4kjB1jgLyG9VimGfyJb1F8/GFdrx55atsBCH/9r2D/iZHAUDCvZ5zhWXB7sRQ2z2WkkuNYm/0pgQtUm1jhdf7A==", "license": "MIT" }, "node_modules/@vscode/v8-heap-parser": { diff --git a/package.json b/package.json index 67d280d2d87..ccc9212544e 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "@vscode/spdlog": "^0.15.2", "@vscode/sqlite3": "5.1.8-vscode", "@vscode/sudo-prompt": "9.3.1", - "@vscode/tree-sitter-wasm": "^0.2.0", + "@vscode/tree-sitter-wasm": "^0.3.0", "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-mutex": "^0.5.0", "@vscode/windows-process-tree": "^0.6.0", diff --git a/remote/package-lock.json b/remote/package-lock.json index 7d123d102d5..524826e045f 100644 --- a/remote/package-lock.json +++ b/remote/package-lock.json @@ -16,7 +16,7 @@ "@vscode/proxy-agent": "^0.36.0", "@vscode/ripgrep": "^1.15.13", "@vscode/spdlog": "^0.15.2", - "@vscode/tree-sitter-wasm": "^0.2.0", + "@vscode/tree-sitter-wasm": "^0.3.0", "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-process-tree": "^0.6.0", "@vscode/windows-registry": "^1.1.0", @@ -188,9 +188,9 @@ } }, "node_modules/@vscode/tree-sitter-wasm": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.2.0.tgz", - "integrity": "sha512-abvLfKwmriqgdS4WrIzFK7mzdPUVqIIW1UWarp2lA8lpOZ1EDPL1snRBKe7g+5R5ri173mNJEuPLnG/NlpMp4w==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.3.0.tgz", + "integrity": "sha512-4kjB1jgLyG9VimGfyJb1F8/GFdrx55atsBCH/9r2D/iZHAUDCvZ5zhWXB7sRQ2z2WkkuNYm/0pgQtUm1jhdf7A==", "license": "MIT" }, "node_modules/@vscode/vscode-languagedetection": { diff --git a/remote/package.json b/remote/package.json index 905eae3d92e..119d62c9c67 100644 --- a/remote/package.json +++ b/remote/package.json @@ -11,7 +11,7 @@ "@vscode/proxy-agent": "^0.36.0", "@vscode/ripgrep": "^1.15.13", "@vscode/spdlog": "^0.15.2", - "@vscode/tree-sitter-wasm": "^0.2.0", + "@vscode/tree-sitter-wasm": "^0.3.0", "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-process-tree": "^0.6.0", "@vscode/windows-registry": "^1.1.0", diff --git a/remote/web/package-lock.json b/remote/web/package-lock.json index ac1a0d4234d..192ad264db4 100644 --- a/remote/web/package-lock.json +++ b/remote/web/package-lock.json @@ -11,7 +11,7 @@ "@microsoft/1ds-core-js": "^3.2.13", "@microsoft/1ds-post-js": "^3.2.13", "@vscode/iconv-lite-umd": "0.7.1", - "@vscode/tree-sitter-wasm": "^0.2.0", + "@vscode/tree-sitter-wasm": "^0.3.0", "@vscode/vscode-languagedetection": "1.0.21", "@xterm/addon-clipboard": "^0.2.0-beta.119", "@xterm/addon-image": "^0.9.0-beta.136", @@ -78,9 +78,9 @@ "license": "MIT" }, "node_modules/@vscode/tree-sitter-wasm": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.2.0.tgz", - "integrity": "sha512-abvLfKwmriqgdS4WrIzFK7mzdPUVqIIW1UWarp2lA8lpOZ1EDPL1snRBKe7g+5R5ri173mNJEuPLnG/NlpMp4w==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.3.0.tgz", + "integrity": "sha512-4kjB1jgLyG9VimGfyJb1F8/GFdrx55atsBCH/9r2D/iZHAUDCvZ5zhWXB7sRQ2z2WkkuNYm/0pgQtUm1jhdf7A==", "license": "MIT" }, "node_modules/@vscode/vscode-languagedetection": { diff --git a/remote/web/package.json b/remote/web/package.json index 26584bf22a5..fbe537240c6 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -6,7 +6,7 @@ "@microsoft/1ds-core-js": "^3.2.13", "@microsoft/1ds-post-js": "^3.2.13", "@vscode/iconv-lite-umd": "0.7.1", - "@vscode/tree-sitter-wasm": "^0.2.0", + "@vscode/tree-sitter-wasm": "^0.3.0", "@vscode/vscode-languagedetection": "1.0.21", "@xterm/addon-clipboard": "^0.2.0-beta.119", "@xterm/addon-image": "^0.9.0-beta.136", diff --git a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/runInTerminalTool.ts b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/runInTerminalTool.ts index cd65e8a054a..84b9f089c42 100644 --- a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/runInTerminalTool.ts +++ b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/runInTerminalTool.ts @@ -65,10 +65,9 @@ function createPowerShellModelDescription(shell: string): string { `This tool allows you to execute ${isWinPwsh ? 'Windows PowerShell 5.1' : 'PowerShell'} commands in a persistent terminal session, preserving environment variables, working directory, and other context across multiple commands.`, '', 'Command Execution:', - // TODO: Even for pwsh 7+ we want to use `;` to chain commands since the tree sitter grammar - // doesn't parse `&&`. We want to change this to avoid `&&` only in Windows PowerShell when - // the grammar supports it https://github.com/airbus-cert/tree-sitter-powershell/issues/27 - '- Use semicolons ; to chain commands on one line, NEVER use && even when asked explicitly', + // IMPORTANT: PowerShell 5 does not support `&&` so always re-write them to `;`. Note that + // the behavior of `&&` differs a little from `;` but in general it's fine + isWinPwsh ? '- Use semicolons ; to chain commands on one line, NEVER use && even when asked explicitly' : '- Prefer ; when chaining commands on one line', '- Prefer pipelines | for object-based data flow', '- Never create a sub-shell (eg. powershell -c "command") unless explicitly asked', '', diff --git a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/treeSitterCommandParser.ts b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/treeSitterCommandParser.ts index 973eab5dbf1..464d8695ce5 100644 --- a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/treeSitterCommandParser.ts +++ b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/treeSitterCommandParser.ts @@ -34,10 +34,8 @@ export class TreeSitterCommandParser extends Disposable { async extractPwshDoubleAmpersandChainOperators(commandLine: string): Promise { const captures = await this._queryTree(TreeSitterCommandParserLanguage.PowerShell, commandLine, [ '(', - ' (command', - ' (command_elements', - ' (generic_token) @double.ampersand', - ' (#eq? @double.ampersand "&&")))', + ' (pipeline', + ' (pipeline_chain_tail) @double.ampersand)', ')', ].join('\n')); return captures; diff --git a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/electron-browser/treeSitterCommandParser.test.ts b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/electron-browser/treeSitterCommandParser.test.ts index bad3a681152..4b3c50bc072 100644 --- a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/electron-browser/treeSitterCommandParser.test.ts +++ b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/electron-browser/treeSitterCommandParser.test.ts @@ -212,15 +212,14 @@ suite('TreeSitterCommandParser', () => { test('&& with complex commands', () => t('Get-ChildItem -Path C:\\ && Set-Location C:\\Users', ['&&'])); test('&& with parameters', () => t('Get-Process -Name notepad && Stop-Process -Name notepad', ['&&'])); test('&& with pipeline inside', () => t('Get-Process | Where-Object {$_.Name -eq "notepad"} && Write-Host "Found"', ['&&'])); - // TODO: A lot of these tests are skipped until proper parsing of && is supported in https://github.com/airbus-cert/tree-sitter-powershell/issues/27 - test.skip('nested && in script blocks', () => t('if ($true) { echo hello && echo world } && echo done', ['&&', '&&'])); - test.skip('&& with method calls', () => t('"hello".ToUpper() && "world".ToLower()', ['&&'])); - test.skip('&& with array operations', () => t('@(1,2,3) | ForEach-Object { $_ } && Write-Host "done"', ['&&'])); - test.skip('&& with hashtable', () => t('@{key="value"} && Write-Host "created"', ['&&'])); - test.skip('&& with type casting', () => t('[int]"123" && [string]456', ['&&'])); - test.skip('&& with comparison operators', () => t('5 -gt 3 && "hello" -like "h*"', ['&&'])); - test.skip('&& with variable assignment', () => t('$var = "test" && Write-Host $var', ['&&'])); - test.skip('&& with expandable strings', () => t('$name="World" && "Hello $name"', ['&&'])); + test('nested && in script blocks', () => t('if ($true) { echo hello && echo world }', ['&&'])); + test('&& with method calls', () => t('"hello".ToUpper() && "world".ToLower()', ['&&'])); + test('&& with array operations', () => t('@(1,2,3) | ForEach-Object { $_ } && Write-Host "done"', ['&&'])); + test('&& with hashtable', () => t('@{key="value"} && Write-Host "created"', ['&&'])); + test('&& with type casting', () => t('[int]"123" && [string]456', ['&&'])); + test('&& with comparison operators', () => t('5 -gt 3 && "hello" -like "h*"', ['&&'])); + test('&& with variable assignment', () => t('$var = "test" && Write-Host $var', ['&&'])); + test('&& with expandable strings', () => t('$name="World" && "Hello $name"', ['&&'])); test('&& with subexpressions', () => t('Write-Host $(Get-Date) && Get-Location', ['&&'])); test('&& with here-strings', () => t('Write-Host @"\nhello\nworld\n"@ && Get-Date', ['&&'])); test('&& with splatting', () => t('$params = @{Path="C:\\"}; Get-ChildItem @params && Write-Host "done"', ['&&'])); @@ -230,7 +229,7 @@ suite('TreeSitterCommandParser', () => { test('&& with error handling', () => t('try { Get-Content "file.txt" && Write-Host "success" } catch { Write-Error "failed" }', ['&&'])); test('&& inside foreach', () => t('ForEach-Object { Write-Host $_.Name && Write-Host $_.Length }', ['&&'])); test('&& with conditional logic', () => t('if (Test-Path "file.txt") { Get-Content "file.txt" && Write-Host "read" }', ['&&'])); - test.skip('&& with switch statement', () => t('switch ($var) { 1 { "one" && "first" } 2 { "two" && "second" } }', ['&&', '&&'])); + test('&& with switch statement', () => t('switch ($var) { 1 { "one" && "first" } 2 { "two" && "second" } }', ['&&', '&&'])); test('&& in do-while', () => t('do { Write-Host $i && $i++ } while ($i -lt 5)', ['&&'])); test('&& in for loop', () => t('for ($i=0; $i -lt 5; $i++) { Write-Host $i && Start-Sleep 1 }', ['&&'])); test('&& with parallel processing', () => t('1..10 | ForEach-Object -Parallel { Write-Host $_ && Start-Sleep 1 }', ['&&'])); @@ -239,22 +238,18 @@ suite('TreeSitterCommandParser', () => { suite('edge cases', () => { test('empty string', () => t('', [])); test('whitespace only', () => t(' \n\t ', [])); - test('single &', () => t('Get-Date & Get-Location', [])); - test.skip('triple &&&', () => t('echo hello &&& echo world', ['&&'])); - test.skip('&& at beginning', () => t('&& echo hello', ['&&'])); - test('&& at end', () => t('echo hello &&', ['&&'])); + test('triple &&&', () => t('echo hello &&& echo world', ['&&'])); test('spaced && operators', () => t('echo hello & & echo world', [])); test('&& with unicode', () => t('Write-Host "测试" && Write-Host "🚀"', ['&&'])); test('very long command with &&', () => t('Write-Host "' + 'a'.repeat(1000) + '" && Get-Date', ['&&'])); test('deeply nested with &&', () => t('if ($true) { if ($true) { if ($true) { echo nested && echo deep } } }', ['&&'])); test('&& with escaped characters', () => t('Write-Host "hello`"world" && Get-Date', ['&&'])); - test.skip('&& with backticks', () => t('Write-Host `hello && Get-Date', ['&&'])); - test.skip('malformed syntax with &&', () => t('echo "unclosed && Get-Date', ['&&'])); + test('&& with backticks', () => t('Write-Host `hello && Get-Date', ['&&'])); }); suite('real-world scenarios', () => { test('git workflow', () => t('git add . && git commit -m "message" && git push', ['&&', '&&'])); - test.skip('build and test', () => t('dotnet build && dotnet test && dotnet publish', ['&&', '&&'])); + test('build and test', () => t('dotnet build && dotnet test && dotnet publish', ['&&', '&&'])); test('file operations', () => t('New-Item -Type File "test.txt" && Add-Content "test.txt" "hello" && Get-Content "test.txt"', ['&&', '&&'])); test('service management', () => t('Stop-Service spooler && Set-Service spooler -StartupType Manual && Start-Service spooler', ['&&', '&&'])); test('registry operations', () => t('New-Item -Path "HKCU:\\Software\\Test" && Set-ItemProperty -Path "HKCU:\\Software\\Test" -Name "Value" -Value "Data"', ['&&']));