Skip to content

fix: index VB.NET Catch statements with no variable, and project files beside their solution - #125

Open
denster wants to merge 2 commits into
sourcegraph:mainfrom
denster:fix-vb-catch-and-project-beside-solution
Open

denster wants to merge 2 commits into
sourcegraph:mainfrom
denster:fix-vb-catch-and-project-beside-solution

Conversation

@denster

@denster denster commented Oct 15, 2026

Copy link
Copy Markdown

This fixes two failures that came up while indexing real VB.NET repositories with scip-dotnet 0.2.14. Both are still present on main. Each fix is its own commit with its own snapshot test.

1. A Catch without an exception variable crashes the Visual Basic walker

ScipVisualBasicSyntaxWalker.VisitCatchStatement reads node.IdentifierName.Identifier. A Catch that declares no variable (Catch, or Catch When condition) has no IdentifierName, so the walker throws and the whole index fails:

Unhandled exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at ScipDotnet.ScipVisualBasicSyntaxWalker.VisitCatchStatement(CatchStatementSyntax node)

A bare Catch is common in VB code (jamesplotts/simpleide has 36, and DualBrain/bsharp uses Catch When), so such projects cannot be indexed at all. The fix records the definition occurrence only when the Catch declares a variable.

Test: snapshots/input/syntax/VBMain/Statements.vb gains a method with a Catch When and a bare Catch. On main, the syntax snapshot test fails with the exception above. (The snapshot comparison only diffs .cs outputs, so for Visual Basic the test catches this through the indexer's exit code.)

2. A project file beside its solution crashes the index or is indexed twice

With no path given, scip-dotnet index takes every .sln, .slnx, .csproj and .vbproj file in the working directory as a root, in the order Directory.GetFiles returns them. That order depends on the file system. When a solution and its project file are in the same directory (for example SimpleIDE.sln beside SimpleIDE.vbproj):

  • If the solution comes first (seen on Linux), OpenProjectAsync on the project file throws 'SimpleIDE' is already part of the workspace. and the index fails.
  • If the project file comes first (seen on macOS), opening the solution afterwards loads the project again under a new ProjectId. indexedProjects does not recognize it, so every document of the project appears twice in the index.

The fix has two parts:

  • FindSolutionOrProjectFile lists solutions before project files, each in name order, so the order no longer depends on the file system.
  • IndexProject does not open a project file that the workspace already holds. It uses the loaded project instead, which the existing indexedProjects check then skips because the solution indexed it. dotnet restore is skipped for it as well.

Test: the new snapshots/input/project-beside-solution holds ProjectBesideSolution.sln and ProjectBesideSolution.csproj in one directory. With the new order but without the IndexProject change, its test fails with 'ProjectBesideSolution(net10.0)' is already part of the workspace. On main, the result depends on the file system: on macOS the test passes, but the index holds every document of the project twice.

Verification

On macOS (arm64), with the .NET SDKs 10.0.402, 9.0.319 and 8.0.426:

  • dotnet test -p:TargetFrameworks=net10.0, net9.0 and net8.0 pass. The new snapshot outputs were generated with each of the three.
  • dotnet format --verify-no-changes passes at the root, in snapshots/input/syntax, and for snapshots/input/project-beside-solution/ProjectBesideSolution.sln.

…riable

A Visual Basic `Catch` without an exception variable (`Catch`, or
`Catch When condition`) has no IdentifierName, and
ScipVisualBasicSyntaxWalker.VisitCatchStatement read
node.IdentifierName.Identifier unconditionally. The resulting
NullReferenceException ended the whole index, so no project containing a
bare `Catch` could be indexed.

The definition occurrence is now recorded only when the Catch declares a
variable. Statements.vb in the syntax snapshot gains a `Catch When` and a
bare `Catch`; without the fix, the syntax snapshot test fails with the
exception.
With no path given, `scip-dotnet index` takes every solution and project
file in the working directory as a root, in the order Directory.GetFiles
returns them, which depends on the file system. A project file in the same
directory as the solution that includes it was handled in one of two ways:

- After the solution (the order seen on Linux): OpenProjectAsync threw
  "'<name>' is already part of the workspace", which ended the whole index.
- Before the solution (the order seen on macOS): opening the solution
  afterwards loaded the project again under a new ProjectId, which
  indexedProjects did not recognize, so every document of the project
  appeared twice in the index.

FindSolutionOrProjectFile now lists solutions before project files, each in
name order. IndexProject no longer opens a project file that the workspace
already holds: it uses the loaded project, which indexedProjects then skips
because the solution indexed it, and it skips `dotnet restore` for it.

The new project-beside-solution snapshot holds ProjectBesideSolution.sln
and ProjectBesideSolution.csproj in one directory. With the new order but
without the IndexProject change, its test fails with
"'ProjectBesideSolution(net10.0)' is already part of the workspace".

This branch has not been deployed

No deployments
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