diff --git a/ScipDotnet/IndexCommandHandler.cs b/ScipDotnet/IndexCommandHandler.cs index f4d8e8c..363f0f4 100644 --- a/ScipDotnet/IndexCommandHandler.cs +++ b/ScipDotnet/IndexCommandHandler.cs @@ -126,7 +126,12 @@ private static List FindSolutionOrProjectFile(FileInfo workingDirector string.Equals(Path.GetExtension(file), ".slnx", StringComparison.OrdinalIgnoreCase) || string.Equals(Path.GetExtension(file), ".csproj", StringComparison.OrdinalIgnoreCase) || string.Equals(Path.GetExtension(file), ".vbproj", StringComparison.OrdinalIgnoreCase) - ).ToList(); + ) + // Solutions (.sln/.slnx) before project files, each in name order. Directory.GetFiles returns + // the order of the file system, and a project file must come after the solution that loads it. + .OrderBy(file => Path.GetExtension(file).StartsWith(".sln", StringComparison.OrdinalIgnoreCase) ? 0 : 1) + .ThenBy(file => file, StringComparer.Ordinal) + .ToList(); if (paths.Count != 0) { diff --git a/ScipDotnet/ScipProjectIndexer.cs b/ScipDotnet/ScipProjectIndexer.cs index 1f1debf..d6c7e66 100644 --- a/ScipDotnet/ScipProjectIndexer.cs +++ b/ScipDotnet/ScipProjectIndexer.cs @@ -61,21 +61,29 @@ private void Restore(IndexCommandOptions options, FileInfo project) FileInfo rootProject, HashSet indexedProjects) { - if (!options.SkipDotnetRestore) - { - Restore(options, rootProject); - } - + var workspace = host.Services.GetRequiredService(); var isProjectFile = string.Equals(rootProject.Extension, ".csproj", StringComparison.OrdinalIgnoreCase) || string.Equals(rootProject.Extension, ".vbproj", StringComparison.OrdinalIgnoreCase); - var projects = (isProjectFile - ? new[] + + // A solution in the same directory may have loaded this project file already. Opening it a second time + // throws "'' is already part of the workspace", so the loaded project is used instead, and + // indexedProjects skips it because the solution indexed it. + var projects = isProjectFile + ? workspace.CurrentSolution.Projects + .Where(project => string.Equals(project.FilePath, rootProject.FullName, StringComparison.OrdinalIgnoreCase)) + .ToList() + : new List(); + if (projects.Count == 0) + { + if (!options.SkipDotnetRestore) { - await host.Services.GetRequiredService() - .OpenProjectAsync(rootProject.FullName) + Restore(options, rootProject); } - : (await host.Services.GetRequiredService() - .OpenSolutionAsync(rootProject.FullName)).Projects).ToList(); + + projects = (isProjectFile + ? new[] { await workspace.OpenProjectAsync(rootProject.FullName) } + : (await workspace.OpenSolutionAsync(rootProject.FullName)).Projects).ToList(); + } options.Logger.LogDebug($"Found {projects.Count()} projects"); diff --git a/ScipDotnet/ScipVisualBasicSyntaxWalker.cs b/ScipDotnet/ScipVisualBasicSyntaxWalker.cs index e4c191e..f71f6e7 100644 --- a/ScipDotnet/ScipVisualBasicSyntaxWalker.cs +++ b/ScipDotnet/ScipVisualBasicSyntaxWalker.cs @@ -45,7 +45,12 @@ public override void VisitEnumStatement(EnumStatementSyntax node) public override void VisitCatchStatement(CatchStatementSyntax node) { - _scipDocumentIndexer.VisitOccurrence(_semanticModel.GetDeclaredSymbol(node), node.IdentifierName.Identifier.GetLocation(), true); + // `Catch` and `Catch When condition` declare no exception variable, so IdentifierName is null. + if (node.IdentifierName != null) + { + _scipDocumentIndexer.VisitOccurrence(_semanticModel.GetDeclaredSymbol(node), node.IdentifierName.Identifier.GetLocation(), true); + } + base.VisitCatchStatement(node); } diff --git a/snapshots/input/project-beside-solution/Program.cs b/snapshots/input/project-beside-solution/Program.cs new file mode 100644 index 0000000..9ca9fad --- /dev/null +++ b/snapshots/input/project-beside-solution/Program.cs @@ -0,0 +1,9 @@ +namespace ProjectBesideSolution; + +public static class Program +{ + public static void Main() + { + Console.WriteLine("Hello, World!"); + } +} diff --git a/snapshots/input/project-beside-solution/ProjectBesideSolution.csproj b/snapshots/input/project-beside-solution/ProjectBesideSolution.csproj new file mode 100644 index 0000000..3e3505f --- /dev/null +++ b/snapshots/input/project-beside-solution/ProjectBesideSolution.csproj @@ -0,0 +1,10 @@ + + + + Exe + net10.0;net9.0;net8.0 + enable + enable + + + diff --git a/snapshots/input/project-beside-solution/ProjectBesideSolution.sln b/snapshots/input/project-beside-solution/ProjectBesideSolution.sln new file mode 100644 index 0000000..8794bf7 --- /dev/null +++ b/snapshots/input/project-beside-solution/ProjectBesideSolution.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectBesideSolution", "ProjectBesideSolution.csproj", "{96877E88-1D0A-45D0-9C35-E5A0B07783A0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {96877E88-1D0A-45D0-9C35-E5A0B07783A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96877E88-1D0A-45D0-9C35-E5A0B07783A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96877E88-1D0A-45D0-9C35-E5A0B07783A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96877E88-1D0A-45D0-9C35-E5A0B07783A0}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/snapshots/input/syntax/VBMain/Statements.vb b/snapshots/input/syntax/VBMain/Statements.vb index ed76d9a..8dc45a1 100644 --- a/snapshots/input/syntax/VBMain/Statements.vb +++ b/snapshots/input/syntax/VBMain/Statements.vb @@ -12,6 +12,16 @@ Namespace VBMain End Try End Sub + Private Sub TryWithoutExceptionVariable(fileName As String) + Try + File.ReadLines(fileName) + Catch When fileName.Length = 0 + Console.WriteLine("empty file name") + Catch + Console.WriteLine("failed") + End Try + End Sub + Private Function [Default]() As (A As String, B As Boolean) Dim C As (A As String, B As Boolean) = ("42", 42) Return C diff --git a/snapshots/output-net10.0/project-beside-solution/Program.cs b/snapshots/output-net10.0/project-beside-solution/Program.cs new file mode 100644 index 0000000..17179df --- /dev/null +++ b/snapshots/output-net10.0/project-beside-solution/Program.cs @@ -0,0 +1,16 @@ + namespace ProjectBesideSolution; +// ^^^^^^^^^^^^^^^^^^^^^ reference scip-dotnet nuget . . ProjectBesideSolution/ + + public static class Program +// ^^^^^^^ definition scip-dotnet nuget . . ProjectBesideSolution/Program# +// documentation ```cs\nclass Program\n``` + { + public static void Main() +// ^^^^ definition scip-dotnet nuget . . ProjectBesideSolution/Program#Main(). +// documentation ```cs\npublic static void Program.Main()\n``` + { + Console.WriteLine("Hello, World!"); +// ^^^^^^^ reference scip-dotnet nuget System.Console 10.0.0.0 System/Console# +// ^^^^^^^^^ reference scip-dotnet nuget System.Console 10.0.0.0 System/Console#WriteLine(+11). + } + } diff --git a/snapshots/output-net10.0/syntax/VBMain/Statements.vb b/snapshots/output-net10.0/syntax/VBMain/Statements.vb index 0f2b103..ff8e157 100644 --- a/snapshots/output-net10.0/syntax/VBMain/Statements.vb +++ b/snapshots/output-net10.0/syntax/VBMain/Statements.vb @@ -32,6 +32,29 @@ End Try End Sub + Private Sub TryWithoutExceptionVariable(fileName As String) +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable(). +' documentation ```vb\nPrivate Sub Statements.TryWithoutExceptionVariable(fileName As String)\n``` +' ^^^^^^^^ definition scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable().(fileName) +' documentation ```vb\nfileName As String\n``` + Try + File.ReadLines(fileName) +' ^^^^ reference scip-dotnet nuget System.Runtime 10.0.0.0 IO/File# +' ^^^^^^^^^ reference scip-dotnet nuget System.Runtime 10.0.0.0 IO/File#ReadLines(). +' ^^^^^^^^ reference scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable().(fileName) + Catch When fileName.Length = 0 +' ^^^^^^^^ reference scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable().(fileName) +' ^^^^^^ reference scip-dotnet nuget System.Runtime 10.0.0.0 System/String#Length. + Console.WriteLine("empty file name") +' ^^^^^^^ reference scip-dotnet nuget System.Console 10.0.0.0 System/Console# +' ^^^^^^^^^ reference scip-dotnet nuget System.Console 10.0.0.0 System/Console#WriteLine(+11). + Catch + Console.WriteLine("failed") +' ^^^^^^^ reference scip-dotnet nuget System.Console 10.0.0.0 System/Console# +' ^^^^^^^^^ reference scip-dotnet nuget System.Console 10.0.0.0 System/Console#WriteLine(+11). + End Try + End Sub + Private Function [Default]() As (A As String, B As Boolean) ' ^^^^^^^^^ definition scip-dotnet nuget . . VBMain/Statements#Default(). ' documentation ```vb\nPrivate Function Statements.Default() As (A As String, B As Boolean)\n``` diff --git a/snapshots/output-net8.0/project-beside-solution/Program.cs b/snapshots/output-net8.0/project-beside-solution/Program.cs new file mode 100644 index 0000000..aa93a12 --- /dev/null +++ b/snapshots/output-net8.0/project-beside-solution/Program.cs @@ -0,0 +1,16 @@ + namespace ProjectBesideSolution; +// ^^^^^^^^^^^^^^^^^^^^^ reference scip-dotnet nuget . . ProjectBesideSolution/ + + public static class Program +// ^^^^^^^ definition scip-dotnet nuget . . ProjectBesideSolution/Program# +// documentation ```cs\nclass Program\n``` + { + public static void Main() +// ^^^^ definition scip-dotnet nuget . . ProjectBesideSolution/Program#Main(). +// documentation ```cs\npublic static void Program.Main()\n``` + { + Console.WriteLine("Hello, World!"); +// ^^^^^^^ reference scip-dotnet nuget System.Console 8.0.0.0 System/Console# +// ^^^^^^^^^ reference scip-dotnet nuget System.Console 8.0.0.0 System/Console#WriteLine(+11). + } + } diff --git a/snapshots/output-net8.0/syntax/VBMain/Statements.vb b/snapshots/output-net8.0/syntax/VBMain/Statements.vb index 0bfc6eb..229f83e 100644 --- a/snapshots/output-net8.0/syntax/VBMain/Statements.vb +++ b/snapshots/output-net8.0/syntax/VBMain/Statements.vb @@ -32,6 +32,29 @@ End Try End Sub + Private Sub TryWithoutExceptionVariable(fileName As String) +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable(). +' documentation ```vb\nPrivate Sub Statements.TryWithoutExceptionVariable(fileName As String)\n``` +' ^^^^^^^^ definition scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable().(fileName) +' documentation ```vb\nfileName As String\n``` + Try + File.ReadLines(fileName) +' ^^^^ reference scip-dotnet nuget System.Runtime 8.0.0.0 IO/File# +' ^^^^^^^^^ reference scip-dotnet nuget System.Runtime 8.0.0.0 IO/File#ReadLines(). +' ^^^^^^^^ reference scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable().(fileName) + Catch When fileName.Length = 0 +' ^^^^^^^^ reference scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable().(fileName) +' ^^^^^^ reference scip-dotnet nuget System.Runtime 8.0.0.0 System/String#Length. + Console.WriteLine("empty file name") +' ^^^^^^^ reference scip-dotnet nuget System.Console 8.0.0.0 System/Console# +' ^^^^^^^^^ reference scip-dotnet nuget System.Console 8.0.0.0 System/Console#WriteLine(+11). + Catch + Console.WriteLine("failed") +' ^^^^^^^ reference scip-dotnet nuget System.Console 8.0.0.0 System/Console# +' ^^^^^^^^^ reference scip-dotnet nuget System.Console 8.0.0.0 System/Console#WriteLine(+11). + End Try + End Sub + Private Function [Default]() As (A As String, B As Boolean) ' ^^^^^^^^^ definition scip-dotnet nuget . . VBMain/Statements#Default(). ' documentation ```vb\nPrivate Function Statements.Default() As (A As String, B As Boolean)\n``` diff --git a/snapshots/output-net9.0/project-beside-solution/Program.cs b/snapshots/output-net9.0/project-beside-solution/Program.cs new file mode 100644 index 0000000..191d232 --- /dev/null +++ b/snapshots/output-net9.0/project-beside-solution/Program.cs @@ -0,0 +1,16 @@ + namespace ProjectBesideSolution; +// ^^^^^^^^^^^^^^^^^^^^^ reference scip-dotnet nuget . . ProjectBesideSolution/ + + public static class Program +// ^^^^^^^ definition scip-dotnet nuget . . ProjectBesideSolution/Program# +// documentation ```cs\nclass Program\n``` + { + public static void Main() +// ^^^^ definition scip-dotnet nuget . . ProjectBesideSolution/Program#Main(). +// documentation ```cs\npublic static void Program.Main()\n``` + { + Console.WriteLine("Hello, World!"); +// ^^^^^^^ reference scip-dotnet nuget System.Console 9.0.0.0 System/Console# +// ^^^^^^^^^ reference scip-dotnet nuget System.Console 9.0.0.0 System/Console#WriteLine(+11). + } + } diff --git a/snapshots/output-net9.0/syntax/VBMain/Statements.vb b/snapshots/output-net9.0/syntax/VBMain/Statements.vb index 9cc6c9b..52d4b11 100644 --- a/snapshots/output-net9.0/syntax/VBMain/Statements.vb +++ b/snapshots/output-net9.0/syntax/VBMain/Statements.vb @@ -32,6 +32,29 @@ End Try End Sub + Private Sub TryWithoutExceptionVariable(fileName As String) +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable(). +' documentation ```vb\nPrivate Sub Statements.TryWithoutExceptionVariable(fileName As String)\n``` +' ^^^^^^^^ definition scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable().(fileName) +' documentation ```vb\nfileName As String\n``` + Try + File.ReadLines(fileName) +' ^^^^ reference scip-dotnet nuget System.Runtime 9.0.0.0 IO/File# +' ^^^^^^^^^ reference scip-dotnet nuget System.Runtime 9.0.0.0 IO/File#ReadLines(). +' ^^^^^^^^ reference scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable().(fileName) + Catch When fileName.Length = 0 +' ^^^^^^^^ reference scip-dotnet nuget . . VBMain/Statements#TryWithoutExceptionVariable().(fileName) +' ^^^^^^ reference scip-dotnet nuget System.Runtime 9.0.0.0 System/String#Length. + Console.WriteLine("empty file name") +' ^^^^^^^ reference scip-dotnet nuget System.Console 9.0.0.0 System/Console# +' ^^^^^^^^^ reference scip-dotnet nuget System.Console 9.0.0.0 System/Console#WriteLine(+11). + Catch + Console.WriteLine("failed") +' ^^^^^^^ reference scip-dotnet nuget System.Console 9.0.0.0 System/Console# +' ^^^^^^^^^ reference scip-dotnet nuget System.Console 9.0.0.0 System/Console#WriteLine(+11). + End Try + End Sub + Private Function [Default]() As (A As String, B As Boolean) ' ^^^^^^^^^ definition scip-dotnet nuget . . VBMain/Statements#Default(). ' documentation ```vb\nPrivate Function Statements.Default() As (A As String, B As Boolean)\n```