Skip to content

feat: VSCode syntax highlighter#347

Merged
Seddryck merged 6 commits into
mainfrom
feat/vscode-syntax
May 14, 2026
Merged

feat: VSCode syntax highlighter#347
Seddryck merged 6 commits into
mainfrom
feat/vscode-syntax

Conversation

@Seddryck
Copy link
Copy Markdown
Owner

@Seddryck Seddryck commented May 14, 2026

Summary by CodeRabbit

  • New Features

    • VS Code extension added for Expressif syntax highlighting (.expr, .expressif)
    • Editor support: bracket matching, auto-closing pairs, and line comments
    • Extension packaged as downloadable VSIX and included in build artifacts
  • Documentation

    • README and docs updated with installation, VSIX download, and usage instructions
  • Chores

    • CI and release flow enhanced to build and publish VSIX assets and related release uploads

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

Adds a VSCode syntax highlighting extension for Expressif: TextMate grammar and generation scripts, package manifest and VSIX packaging scripts, AppVeyor CI changes to produce VSIX artifacts, GitHub release asset upload/download helpers, and documentation updates.

Changes

VSCode Syntax Highlighting Extension

Layer / File(s) Summary
Dotnet local tool foundation
.config/dotnet-tools.json, Expressif.Syntax/Ensure-DotnetLocalToolInstalled.ps1
didot-cli is declared in the .NET tools manifest; a PowerShell helper ensures local .NET tools are installed.
TextMate grammar definition and generation
Expressif.Syntax/Expressif.tmLanguage.json.sbn, Expressif.Syntax/New-tmLanguage.ps1
Adds the TextMate grammar template and a script that loads function.json/predicate.json, filters public entries, builds a model and invokes didot to render expressif.tmLanguage.json.
Extension manifest and editor config
Expressif.Syntax/package.json.sbn, Expressif.Syntax/language-configuration.json
Adds a templated package.json.sbn registering the expressif language and a language-configuration.json with comment/bracket/auto-closing configuration.
Package manifest generation
Expressif.Syntax/New-PackageJson.ps1
Script builds a version model, serializes it to JSON, and pipes it to didot to produce the final package.json.
Extension build and packaging orchestration
Expressif.Syntax/New-tmBundle.ps1
Build script that generates grammar/package manifest, downloads LICENSE, copies assets, validates npm tooling, and packages the staged folder into a .vsix.
CI/CD build automation
appveyor.yml
AppVeyor now installs @vscode/vsce, restores .NET tools, runs generation scripts and the bundle script during build, includes **\*.vsix in artifacts, adds a short sleep before release uploads, and uses git status to gate doc/index update.
GitHub release asset management
github.ps1
Adds functions to POST binary uploads (Send-GitHub-FileUpload-Request), fetch release info, upload matched local assets to a release (Upload-Release-Assets), and download/list release assets by pattern.
Documentation and project metadata
Expressif.sln, README.md, docs/_data/navigation_docs.yml, docs/_docs/vscode-extension-syntax.md, Expressif.Syntax/README, Expressif.Syntax/package.json.sbn
Solution metadata updated to target VS 18; README and docs updated with extension navigation and installation instructions; extension README and package template added.

🎯 3 (Moderate) | ⏱️ ~25 minutes

A rabbit hops through syntax trees so bright,
Each keyword gleams with TextMate light—
didot builds the grammar true,
VSIX packages, shiny new! 🎨
Now Expressif in VSCode shines through.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: VSCode syntax highlighter' accurately summarizes the main change: adding a VS Code extension for Expressif syntax highlighting.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/vscode-syntax

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

12-18: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add the missing top navigation link usage.

Line 18 defines [VSCode Syntax Highlighting Extension], but Line 12 never uses it, so the new section is not linked from the top nav and the reference stays unused.

Suggested fix
-[About][] | [Quickstart][] | [Installing][] | [Functions and predicates][]
+[About][] | [Quickstart][] | [Installing][] | [Functions and predicates][] | [VSCode Syntax Highlighting Extension][]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 12 - 18, The top navigation list on line 12 is
missing the newly defined link label [VSCode Syntax Highlighting Extension] from
line 18; update the nav list (the pipe-separated links line containing [About] |
[Quickstart] | [Installing] | [Functions and predicates]) to include [VSCode
Syntax Highlighting Extension] so the reference is used and the new section is
reachable from the top navigation.
🧹 Nitpick comments (6)
Expressif.Syntax/README (1)

36-42: ⚡ Quick win

Format installation steps as an ordered list for readability.

Lines 36-42 render as a compact text block in Markdown. Converting to a numbered list improves scannability for end users.

Suggested fix
-From VSIX
-Open Visual Studio Code
-Go to Extensions
-Click ... (top-right)
-Select Install from VSIX...
-Choose your .vsix file
-File Types
+### From VSIX
+1. Open Visual Studio Code.
+2. Go to **Extensions**.
+3. Click `...` (top-right).
+4. Select **Install from VSIX...**
+5. Choose your `.vsix` file.
+
+### File types
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Expressif.Syntax/README` around lines 36 - 42, The installation steps under
the "From VSIX" section are written as a compact text block; convert them into a
Markdown ordered list for readability by replacing the lines starting with "From
VSIX", "Open Visual Studio Code", "Go to Extensions", "Click ... (top-right)",
"Select Install from VSIX...", and "Choose your .vsix file" with a numbered list
(1., 2., 3., ...) so the steps render as an ordered list in the README; keep the
"File Types" heading after the list unchanged.
Expressif.Syntax/New-tmLanguage.ps1 (1)

8-9: ⚡ Quick win

Remove or wire LanguageName and ScopeName parameters.

These parameters are currently unused, which makes the script contract misleading. Either remove them or include them in the model/template rendering path.

Proposed minimal cleanup
-    [string] $LanguageName = "Expressif",
-    [string] $ScopeName = "source.expressif"
+    # Reserved for future template customization
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Expressif.Syntax/New-tmLanguage.ps1` around lines 8 - 9, The parameters
LanguageName and ScopeName are declared but unused; either remove their
declarations from New-tmLanguage.ps1 or wire them into the template rendering
logic so they affect output; to fix, search for the [string] $LanguageName and
[string] $ScopeName declarations and either delete them (and update any
docs/tests expecting them) or pass those variables into whatever template/model
rendering function you use (e.g., the function that builds the tmLanguage
content or calls a template engine) so the generated file uses $LanguageName and
$ScopeName in the appropriate fields.
github.ps1 (2)

261-292: ⚡ Quick win

Fragile filename extraction using substring.

Line 290 extracts the filename from the URL using Substring($url.LastIndexOf('/') + 1). This could fail if the URL structure is unexpected or doesn't contain a slash.

♻️ Proposed fix using Split for robust parsing
-	Invoke-WebRequest -Uri $url -OutFile $url.Substring($url.LastIndexOf('/') + 1)
+	$filename = $url.Split('/')[-1]
+	Invoke-WebRequest -Uri $url -OutFile $filename
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@github.ps1` around lines 261 - 292, The filename extraction in
Download-Release-Asset uses $url.Substring($url.LastIndexOf('/') + 1) which is
fragile; replace that logic with a robust extraction (e.g., create a
[System.Uri] from $url then call
[System.IO.Path]::GetFileName($uri.AbsolutePath) or split on '/' and take the
last non-empty segment) and ensure you strip any query string or trailing
slashes and fallback to a safe default filename if extraction yields empty;
update the variable used in Invoke-WebRequest -OutFile accordingly (refer to
Download-Release-Asset, $url and the Invoke-WebRequest -OutFile usage).

52-77: ⚡ Quick win

Content-Type hardcoded as "application/zip" for all uploads.

Line 67 sets the Content-Type to "application/zip" for all file uploads. While VSIX files are ZIP-based, using "application/octet-stream" would be more accurate and flexible for handling different file types.

♻️ Proposed fix for flexible Content-Type
-    $headers.Add("Content-Type", "application/zip")
+    $headers.Add("Content-Type", "application/octet-stream")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@github.ps1` around lines 52 - 77, The Send-GitHub-FileUpload-Request function
currently hardcodes the Content-Type to "application/zip"; change it to be
flexible by using "application/octet-stream" as a safe default and do not
overwrite an existing Content-Type header if one is supplied; update the header
handling around $headers.Keys / $headers.Remove / $headers.Add so it first
checks if $headers contains "Content-Type" and only adds
"application/octet-stream" when absent (or alternatively accept a new parameter
like [string] $ContentType and use that value if provided), and ensure $uri and
Invoke-WebRequest usage stays the same.
appveyor.yml (2)

110-115: ⚖️ Poor tradeoff

Hard-coded delay may mask an underlying timing issue.

The 5-second sleep before uploading release assets suggests a race condition or eventual consistency issue with GitHub's release API. While this may be necessary, consider whether a retry-with-backoff pattern would be more robust than a fixed delay.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@appveyor.yml` around lines 110 - 115, Replace the fixed Start-Sleep -Seconds
5 with a retry-with-backoff around the Upload-Release-Assets call: catch
transient failures when calling the Upload-Release-Assets command (the block
referencing Tag "v$($env:GitVersion_SemVer)" and Path "./.publish"), retry a
configurable number of times with exponential backoff (and short jitter), log
each attempt and failure, and fail only after exhausting retries so we don't
mask the underlying timing/race condition with a hard-coded delay.

58-68: ⚡ Quick win

Consider adding error handling for the info generation scripts.

The generate-info.ps1 scripts run without error checking. If either fails, the build continues to the tmBundle creation, which may produce incorrect results or fail unexpectedly.

🛡️ Proposed fix to add error handling
 - pwsh: |
-    & .\generate-info.ps1 function
-    & .\generate-info.ps1 predicate
+    & .\generate-info.ps1 function
+    if ($LASTEXITCODE -ne 0) { throw "Failed to generate function info" }
+    & .\generate-info.ps1 predicate
+    if ($LASTEXITCODE -ne 0) { throw "Failed to generate predicate info" }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@appveyor.yml` around lines 58 - 68, The generate-info.ps1 invocations run
without error checking so failures can be ignored and downstream steps like
New-tmBundle.ps1 will run against bad state; wrap each pwsh block that calls
.\generate-info.ps1 (and the block that calls .\New-tmBundle.ps1) in explicit
error handling: set ErrorActionPreference='Stop' or use -ErrorAction Stop when
invoking generate-info.ps1, catch exceptions in a try/catch around the call, log
the error and exit non‑zero (or rethrow) to halt the pipeline; do the same for
the New-tmBundle.ps1 block (the Push-Location / Pop-Location block) so any
failure there is propagated and the job stops.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Expressif.Syntax/New-PackageJson.ps1`:
- Line 14: The Write-Host call prints "$($model.version)" but $model is still
JSON text, so it won't reliably show the actual version; change the logging to
read the version from a parsed JSON object (e.g., parse $model with
ConvertFrom-Json into a variable like $modelObj and use $modelObj.version, or
directly use (ConvertFrom-Json $model).version) and use that parsed value in the
Write-Host message to ensure the real version is printed.

In `@Expressif.Syntax/New-tmBundle.ps1`:
- Line 31: The success log uses an undefined variable $OutputFolder; locate the
variable that actually holds the generated VSIX path in this script (e.g., the
assignment for the package output such as $OutputPath, $PackageOutput or
$OutDir) and replace $OutputFolder in the Write-Host call (the line with
Write-Host "-> VSIX package generated in $OutputFolder") with that correct
variable so the printed path is accurate.
- Around line 89-91: The build currently downloads LICENSE via Copy-RemoteText
which couples the build to a remote branch; replace that remote fetch by copying
the repository's checked-in LICENSE into the build obj folder (e.g., use
Copy-Item or Add-Content to copy .\LICENSE -> .\obj\LICENSE) and guard with
Test-Path to fail fast if the file is missing; remove or comment out the
Copy-RemoteText call and update any references to rely on the local LICENSE so
packaging is deterministic for the checked-out commit.

In `@Expressif.Syntax/package.json.sbn`:
- Line 9: Replace the placeholder repository URL value in the package metadata
by updating the "url" field (in package.json.sbn) from
"https://github.com/your-org/expressif.git" to the actual Git repository URL for
this project (a valid https or git URL for the expressif repo), ensuring the
string is reachable and correct; also verify any other package metadata fields
that reference the repo (e.g., "repository" or "homepage") are updated to the
same real URL so marketplace metadata links are not broken.

---

Outside diff comments:
In `@README.md`:
- Around line 12-18: The top navigation list on line 12 is missing the newly
defined link label [VSCode Syntax Highlighting Extension] from line 18; update
the nav list (the pipe-separated links line containing [About] | [Quickstart] |
[Installing] | [Functions and predicates]) to include [VSCode Syntax
Highlighting Extension] so the reference is used and the new section is
reachable from the top navigation.

---

Nitpick comments:
In `@appveyor.yml`:
- Around line 110-115: Replace the fixed Start-Sleep -Seconds 5 with a
retry-with-backoff around the Upload-Release-Assets call: catch transient
failures when calling the Upload-Release-Assets command (the block referencing
Tag "v$($env:GitVersion_SemVer)" and Path "./.publish"), retry a configurable
number of times with exponential backoff (and short jitter), log each attempt
and failure, and fail only after exhausting retries so we don't mask the
underlying timing/race condition with a hard-coded delay.
- Around line 58-68: The generate-info.ps1 invocations run without error
checking so failures can be ignored and downstream steps like New-tmBundle.ps1
will run against bad state; wrap each pwsh block that calls .\generate-info.ps1
(and the block that calls .\New-tmBundle.ps1) in explicit error handling: set
ErrorActionPreference='Stop' or use -ErrorAction Stop when invoking
generate-info.ps1, catch exceptions in a try/catch around the call, log the
error and exit non‑zero (or rethrow) to halt the pipeline; do the same for the
New-tmBundle.ps1 block (the Push-Location / Pop-Location block) so any failure
there is propagated and the job stops.

In `@Expressif.Syntax/New-tmLanguage.ps1`:
- Around line 8-9: The parameters LanguageName and ScopeName are declared but
unused; either remove their declarations from New-tmLanguage.ps1 or wire them
into the template rendering logic so they affect output; to fix, search for the
[string] $LanguageName and [string] $ScopeName declarations and either delete
them (and update any docs/tests expecting them) or pass those variables into
whatever template/model rendering function you use (e.g., the function that
builds the tmLanguage content or calls a template engine) so the generated file
uses $LanguageName and $ScopeName in the appropriate fields.

In `@Expressif.Syntax/README`:
- Around line 36-42: The installation steps under the "From VSIX" section are
written as a compact text block; convert them into a Markdown ordered list for
readability by replacing the lines starting with "From VSIX", "Open Visual
Studio Code", "Go to Extensions", "Click ... (top-right)", "Select Install from
VSIX...", and "Choose your .vsix file" with a numbered list (1., 2., 3., ...) so
the steps render as an ordered list in the README; keep the "File Types" heading
after the list unchanged.

In `@github.ps1`:
- Around line 261-292: The filename extraction in Download-Release-Asset uses
$url.Substring($url.LastIndexOf('/') + 1) which is fragile; replace that logic
with a robust extraction (e.g., create a [System.Uri] from $url then call
[System.IO.Path]::GetFileName($uri.AbsolutePath) or split on '/' and take the
last non-empty segment) and ensure you strip any query string or trailing
slashes and fallback to a safe default filename if extraction yields empty;
update the variable used in Invoke-WebRequest -OutFile accordingly (refer to
Download-Release-Asset, $url and the Invoke-WebRequest -OutFile usage).
- Around line 52-77: The Send-GitHub-FileUpload-Request function currently
hardcodes the Content-Type to "application/zip"; change it to be flexible by
using "application/octet-stream" as a safe default and do not overwrite an
existing Content-Type header if one is supplied; update the header handling
around $headers.Keys / $headers.Remove / $headers.Add so it first checks if
$headers contains "Content-Type" and only adds "application/octet-stream" when
absent (or alternatively accept a new parameter like [string] $ContentType and
use that value if provided), and ensure $uri and Invoke-WebRequest usage stays
the same.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 24f7e568-0c05-4749-8b78-8ac4e5b52ef7

📥 Commits

Reviewing files that changed from the base of the PR and between 14fd31c and a2d7ed5.

📒 Files selected for processing (15)
  • .config/dotnet-tools.json
  • Expressif.Syntax/Ensure-DotnetLocalToolInstalled.ps1
  • Expressif.Syntax/Expressif.tmLanguage.json.sbn
  • Expressif.Syntax/New-PackageJson.ps1
  • Expressif.Syntax/New-tmBundle.ps1
  • Expressif.Syntax/New-tmLanguage.ps1
  • Expressif.Syntax/README
  • Expressif.Syntax/language-configuration.json
  • Expressif.Syntax/package.json.sbn
  • Expressif.sln
  • README.md
  • appveyor.yml
  • docs/_data/navigation_docs.yml
  • docs/_docs/vscode-extension-syntax.md
  • github.ps1

Comment thread Expressif.Syntax/New-PackageJson.ps1 Outdated
Comment thread Expressif.Syntax/New-tmBundle.ps1 Outdated
Comment thread Expressif.Syntax/New-tmBundle.ps1
Comment thread Expressif.Syntax/package.json.sbn Outdated
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
Expressif.Syntax/New-tmBundle.ps1 (1)

89-91: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Copy LICENSE from repository instead of downloading from remote.

Downloading the LICENSE from the remote main branch introduces non-determinism and a network dependency. The build should be reproducible for any checked-out commit and should not depend on the current state of the remote branch.

🔧 Proposed fix
 Write-Host "== Copy license =="
-Copy-RemoteText `
-    -Url "https://raw.githubusercontent.com/Seddryck/Expressif/main/LICENSE" `
-    -OutputPath ".\obj\LICENSE"
+$licensePath = Join-Path $PSScriptRoot "..\LICENSE"
+if (-not (Test-Path $licensePath)) {
+    throw "LICENSE file not found at $licensePath"
+}
+Copy-Item $licensePath .\obj\LICENSE
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Expressif.Syntax/New-tmBundle.ps1` around lines 89 - 91, Replace the network
download call to Copy-RemoteText in New-tmBundle.ps1 with a local file copy:
instead of calling Copy-RemoteText -Url "https://.../LICENSE" -OutputPath
".\obj\LICENSE", copy the repository LICENSE file into .\obj\LICENSE (use a path
based on $PSScriptRoot or the script's location to locate the repo root), ensure
the .\obj directory exists (create it if necessary), and remove any network
dependency so the build uses the checked-in LICENSE file.
🧹 Nitpick comments (2)
Expressif.Syntax/New-tmLanguage.ps1 (2)

34-39: ⚡ Quick win

Consider validating output directory exists.

The output path may reference a directory that doesn't exist yet. While the calling script (New-tmBundle.ps1) creates it, adding a check here would make the script more robust for standalone use.

🛡️ Proposed validation
+$outputDir = Split-Path $OutputPath -Parent
+if ($outputDir -and -not (Test-Path $outputDir)) {
+    New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
+}
+
 Write-Host "Running Didot via local installation..."
 $model | dotnet tool run didot `
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Expressif.Syntax/New-tmLanguage.ps1` around lines 34 - 39, The script invokes
"dotnet tool run didot ... -o $OutputPath" without ensuring the output directory
exists; update New-tmLanguage.ps1 to validate and create the directory
referenced by $OutputPath (use Test-Path and New-Item -ItemType Directory or
equivalent) before calling "dotnet tool run didot" so the tool has a valid
output location.

10-11: ⚡ Quick win

Consider validating input files exist.

The script reads function.json and predicate.json without checking if they exist. Adding validation would provide clearer error messages if the files are missing.

🛡️ Proposed validation
+$functionPath = Join-Path $InputFolder "function.json"
+$predicatePath = Join-Path $InputFolder "predicate.json"
+
+if (-not (Test-Path $functionPath)) {
+    throw "function.json not found in $InputFolder"
+}
+if (-not (Test-Path $predicatePath)) {
+    throw "predicate.json not found in $InputFolder"
+}
+
 $model = [ordered]@{
-        functions =  Get-Content $InputFolder\function.json -Raw |
+        functions =  Get-Content $functionPath -Raw |
             ConvertFrom-Json |
             Where-Object { $_.IsPublic -eq $true } |
             ForEach-Object {
                 [ordered]@{
                     name = $_.Name
                     scope = $_.Scope
                     regex = [regex]::Escape($_.Name)
                 }
             } 
-        predicates =  Get-Content $InputFolder\predicate.json -Raw |
+        predicates =  Get-Content $predicatePath -Raw |

Also applies to: 20-21

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Expressif.Syntax/New-tmLanguage.ps1` around lines 10 - 11, Add existence
checks for the input JSON files before trying to read them: for the block that
sets the "functions" variable (where Get-Content $InputFolder\function.json |
ConvertFrom-Json is used) and the similar block that reads "predicate.json"
(used to build predicates), call Test-Path on each full file path and if the
file is missing emit a clear terminating error (e.g., throw or Write-Error
-ErrorAction Stop) that includes the missing filename and $InputFolder so the
script fails fast with a readable message; update the code paths around the
"functions" and "predicates" reads to perform this validation and only call
Get-Content/ConvertFrom-Json after the file is confirmed to exist.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@github.ps1`:
- Around line 289-291: Remove the stray diff artifact by deleting the leading
plus character before the Invoke-WebRequest call inside the
Download-Release-Asset function; ensure the line reads Invoke-WebRequest -Uri
$url -OutFile $filename (no leading '+' or other extraneous characters) so the
github.ps1 script parses and the Download-Release-Asset function runs correctly.
- Around line 153-159: The code calls Send-GitHub-Get-Request with Segments
@('releases') and then filters by tag, which hits the paginated /releases list
and misses older tags; change the request to use the tag-specific endpoint
instead: call Send-GitHub-Get-Request with Segments @('releases','tags',$tag)
(or equivalent to GET /releases/tags/{tag}), parse the response Content with
ConvertFrom-Json and return that object directly (remove the
Select-Object/Where-Object filtering). Update the code around the
Send-GitHub-Get-Request invocation in Get-Release-Info so it returns the single
release JSON for the given $tag.

---

Duplicate comments:
In `@Expressif.Syntax/New-tmBundle.ps1`:
- Around line 89-91: Replace the network download call to Copy-RemoteText in
New-tmBundle.ps1 with a local file copy: instead of calling Copy-RemoteText -Url
"https://.../LICENSE" -OutputPath ".\obj\LICENSE", copy the repository LICENSE
file into .\obj\LICENSE (use a path based on $PSScriptRoot or the script's
location to locate the repo root), ensure the .\obj directory exists (create it
if necessary), and remove any network dependency so the build uses the
checked-in LICENSE file.

---

Nitpick comments:
In `@Expressif.Syntax/New-tmLanguage.ps1`:
- Around line 34-39: The script invokes "dotnet tool run didot ... -o
$OutputPath" without ensuring the output directory exists; update
New-tmLanguage.ps1 to validate and create the directory referenced by
$OutputPath (use Test-Path and New-Item -ItemType Directory or equivalent)
before calling "dotnet tool run didot" so the tool has a valid output location.
- Around line 10-11: Add existence checks for the input JSON files before trying
to read them: for the block that sets the "functions" variable (where
Get-Content $InputFolder\function.json | ConvertFrom-Json is used) and the
similar block that reads "predicate.json" (used to build predicates), call
Test-Path on each full file path and if the file is missing emit a clear
terminating error (e.g., throw or Write-Error -ErrorAction Stop) that includes
the missing filename and $InputFolder so the script fails fast with a readable
message; update the code paths around the "functions" and "predicates" reads to
perform this validation and only call Get-Content/ConvertFrom-Json after the
file is confirmed to exist.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9a8ab59a-58b7-41a1-9ba3-a9e4fdbb03df

📥 Commits

Reviewing files that changed from the base of the PR and between a2d7ed5 and df3b457.

📒 Files selected for processing (7)
  • Expressif.Syntax/Ensure-DotnetLocalToolInstalled.ps1
  • Expressif.Syntax/New-PackageJson.ps1
  • Expressif.Syntax/New-tmBundle.ps1
  • Expressif.Syntax/New-tmLanguage.ps1
  • Expressif.Syntax/README
  • Expressif.Syntax/package.json.sbn
  • github.ps1
✅ Files skipped from review due to trivial changes (1)
  • Expressif.Syntax/README
🚧 Files skipped from review as they are similar to previous changes (3)
  • Expressif.Syntax/package.json.sbn
  • Expressif.Syntax/Ensure-DotnetLocalToolInstalled.ps1
  • Expressif.Syntax/New-PackageJson.ps1

Comment thread github.ps1
Comment on lines +153 to +159
$response = Send-GitHub-Get-Request `
-Owner $context.Owner `
-Repository $context.Repository `
-Segments @('releases') `
-Headers $($context.SecretToken | Get-GitHub-Headers)
$json = $response | Select-Object -ExpandProperty Content | ConvertFrom-Json
return $json | Where-Object {$_.tag_name -eq $tag}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

GitHub REST API: what are the default pagination rules for GET /repos/{owner}/{repo}/releases, and is there a dedicated GET /repos/{owner}/{repo}/releases/tags/{tag} endpoint?

💡 Result:

Default pagination rules for GET /repos/{owner}/{repo}/releases (GitHub REST API): 1) Query parameters: you can paginate using page and per_page. The endpoint supports per_page (max 100) and page; per_page defaults to 30 and page defaults to 1.[1] 2) Pagination navigation: when results are paginated, GitHub includes a link header in the response that points to the next/last pages; you should follow those URLs to retrieve additional pages.[2][3] Dedicated endpoint for a release by tag: yes. There is a dedicated GET endpoint to fetch a single published release by its tag name: GET /repos/{owner}/{repo}/releases/tags/{tag}. It returns the “published release with the specified tag”.[1]

Citations:


🏁 Script executed:

# First, find the github.ps1 file
fd -t f "github.ps1"

Repository: Seddryck/Expressif

Length of output: 73


🏁 Script executed:

# Read the github.ps1 file to examine the relevant sections
wc -l github.ps1

Repository: Seddryck/Expressif

Length of output: 77


🏁 Script executed:

# Examine lines 153-159 (the function in question)
sed -n '153,159p' github.ps1

Repository: Seddryck/Expressif

Length of output: 395


🏁 Script executed:

# Examine the area around line 291 for the parse error mentioned in the scratchpad
sed -n '280,300p' github.ps1

Repository: Seddryck/Expressif

Length of output: 824


🏁 Script executed:

# Get more context around lines 153-159 to identify the function
sed -n '145,165p' github.ps1

Repository: Seddryck/Expressif

Length of output: 752


🏁 Script executed:

# Verify the exact nature of the parse error by checking the syntax
# Look at the broader context around line 291
sed -n '285,305p' github.ps1

Repository: Seddryck/Expressif

Length of output: 759


🏁 Script executed:

# Check the complete Download-Release-Asset function to verify syntax validity
sed -n '268,310p' github.ps1

Repository: Seddryck/Expressif

Length of output: 1470


🏁 Script executed:

# Verify there are no actual PowerShell syntax errors by checking the function is properly closed
sed -n '268,330p' github.ps1 | cat -n

Repository: Seddryck/Expressif

Length of output: 2453


🏁 Script executed:

# Check the exact bytes around line 291 to confirm if the leading + is actually in the file
sed -n '291p' github.ps1 | od -c | head -20

Repository: Seddryck/Expressif

Length of output: 103


🏁 Script executed:

# Also verify the function structure to ensure Download-Release-Asset is correctly defined
sed -n '250,295p' github.ps1 | cat -n

Repository: Seddryck/Expressif

Length of output: 1905


Use the tag-specific release endpoint to avoid pagination limits.

GET /releases defaults to 30 items per page, so repositories with more than 30 releases will fail to find older tags. This breaks asset operations for those tags since Upload-Release-Assets and List-Release-Assets depend on Get-Release-Info. Use the dedicated tag-specific endpoint instead.

Suggested fix
	$response = Send-GitHub-Get-Request `
					-Owner $context.Owner `
					-Repository $context.Repository `
-					-Segments @('releases') `
+					-Segments @('releases', 'tags', $tag) `
					-Headers $($context.SecretToken | Get-GitHub-Headers)
-    $json = $response | Select-Object -ExpandProperty Content | ConvertFrom-Json
-    return $json | Where-Object {$_.tag_name -eq $tag}
+    return $response | Select-Object -ExpandProperty Content | ConvertFrom-Json
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$response = Send-GitHub-Get-Request `
-Owner $context.Owner `
-Repository $context.Repository `
-Segments @('releases') `
-Headers $($context.SecretToken | Get-GitHub-Headers)
$json = $response | Select-Object -ExpandProperty Content | ConvertFrom-Json
return $json | Where-Object {$_.tag_name -eq $tag}
$response = Send-GitHub-Get-Request `
-Owner $context.Owner `
-Repository $context.Repository `
-Segments @('releases', 'tags', $tag) `
-Headers $($context.SecretToken | Get-GitHub-Headers)
return $response | Select-Object -ExpandProperty Content | ConvertFrom-Json
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@github.ps1` around lines 153 - 159, The code calls Send-GitHub-Get-Request
with Segments @('releases') and then filters by tag, which hits the paginated
/releases list and misses older tags; change the request to use the tag-specific
endpoint instead: call Send-GitHub-Get-Request with Segments
@('releases','tags',$tag) (or equivalent to GET /releases/tags/{tag}), parse the
response Content with ConvertFrom-Json and return that object directly (remove
the Select-Object/Where-Object filtering). Update the code around the
Send-GitHub-Get-Request invocation in Get-Release-Info so it returns the single
release JSON for the given $tag.

Comment thread github.ps1
Comment on lines +289 to +291
Write-Host "Downloading $($asset.name) from $url ..."
$filename = $url.Split('/')[-1]
+ Invoke-WebRequest -Uri $url -OutFile $filename
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
sed -n '289,291p' github.ps1
rg -n '^\+' github.ps1

Repository: Seddryck/Expressif

Length of output: 255


🏁 Script executed:

# Get the function context around line 291
sed -n '280,300p' github.ps1

# Check if there are any other lines with unusual leading characters
rg -n '^\s*[\+\-]' github.ps1 | head -20

# Find the Download-Release-Asset function definition
rg -n 'function.*Download-Release-Asset' github.ps1 -A 5

Repository: Seddryck/Expressif

Length of output: 1875


Remove the stray + before Invoke-WebRequest.

The literal + at line 291 is a diff artifact that causes github.ps1 to fail parsing, preventing the Download-Release-Asset function from running.

Suggested fix
-+	Invoke-WebRequest -Uri $url -OutFile $filename
+	Invoke-WebRequest -Uri $url -OutFile $filename
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Write-Host "Downloading $($asset.name) from $url ..."
$filename = $url.Split('/')[-1]
+ Invoke-WebRequest -Uri $url -OutFile $filename
Write-Host "Downloading $($asset.name) from $url ..."
$filename = $url.Split('/')[-1]
Invoke-WebRequest -Uri $url -OutFile $filename
🧰 Tools
🪛 PSScriptAnalyzer (1.25.0)

[error] 291-291: Missing expression after unary operator '+'.

(MissingExpressionAfterOperator)


[error] 291-291: Unexpected token 'Invoke-WebRequest' in expression or statement.

(UnexpectedToken)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@github.ps1` around lines 289 - 291, Remove the stray diff artifact by
deleting the leading plus character before the Invoke-WebRequest call inside the
Download-Release-Asset function; ensure the line reads Invoke-WebRequest -Uri
$url -OutFile $filename (no leading '+' or other extraneous characters) so the
github.ps1 script parses and the Download-Release-Asset function runs correctly.

@Seddryck Seddryck merged commit 69a87b1 into main May 14, 2026
7 of 10 checks passed
@Seddryck Seddryck deleted the feat/vscode-syntax branch May 14, 2026 11:35
Seddryck added a commit that referenced this pull request May 14, 2026
feat: syntax highlighter for Expressif
@Seddryck
Copy link
Copy Markdown
Owner Author

Close #110
Close #109

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant