File-based apps automatic discovery#82863
Conversation
064840b to
e33723a
Compare
jjonescz
left a comment
There was a problem hiding this comment.
the parts that I looked at LGTM :D
dibarbet
left a comment
There was a problem hiding this comment.
This is because soon, containing #: will no longer mean that the file is for sure an entry point. Non-entry-point files will be allowed to have them too. Still need to update impl and tests accordingly.
Would they still be part of an FBP context (e.g. referenced by an FBP)? If there's an explicit reference I don't think its wrong to include the FBP context for the file (think multi-targeted files)
|
@dibarbet for a fresh review pass |
jasonmalinowski
left a comment
There was a problem hiding this comment.
Leaving comments so far while I sign off for the day.
| { | ||
| await FindAndLoadEntryPointsAsync(); | ||
| } | ||
| catch (Exception ex) when (FatalError.ReportAndCatch(ex)) |
There was a problem hiding this comment.
This is good to have this error reporting, but you may want to consider having it in FindAndLoadEntryPointAsync() since it gives a better chance you won't get a stack unwind that might lose state.
| { | ||
| throw ExceptionUtilities.Unreachable(); | ||
| } | ||
| }, cancellationToken); |
There was a problem hiding this comment.
Did you want to pass this cancellation token elsewhere?
There was a problem hiding this comment.
Perhaps, are you thinking this should also go into FindAndLoadEntryPointsAsync() itself?
There was a problem hiding this comment.
Yep, and check it in a few places.
| // Directories can randomly fail to delete etc when we are thrashing the disk. | ||
| // Not a big deal and not a reason to fail the test, just move on to the next iteration instead. |
There was a problem hiding this comment.
Are we sure that's not because we accidentally left some stuff running async?
There was a problem hiding this comment.
I don't think so, but, if there are additional checks I could put in here instead, to give evidence of whether that is happening, I'd be interested in knowing.
There was a problem hiding this comment.
Maybe a FailFast so we can see the process state? 😄
…ests/FileBasedProgramsEntryPointDiscoveryTests.cs Co-authored-by: Jason Malinowski <jason@jason-m.com>
jasonmalinowski
left a comment
There was a problem hiding this comment.
Approved, but do double check if some of those Max() calls are needed in the recursive walk. I think they're going to force extra unnecessary scanning, but I'm happy to be proven wrong.
Only other real feedback is there's more you can move into the "AndStable" helper in the unit tests which would shorten things up and also add more coverage generally.
| if (fileInfo.Kind == CsFileKind.Directory) | ||
| VisitDirectory(fileInfo.Path, Max(createdOrModifiedTimeUtc, fileInfo.CreatedOrModifiedTimeUtc)); | ||
| else if (fileInfo.Kind == CsFileKind.Cs) | ||
| VisitCsFile(fileInfo.Path, Max(createdOrModifiedTimeUtc, fileInfo.CreatedOrModifiedTimeUtc)); |
There was a problem hiding this comment.
This seems a bit fishy: so if the directory has a newer time stamp than the file, that'd mean some file was added or removed. So good that we had to scan it again. But why are we cracking each of the .cs files? It seems like this should just be fileInfo.CreatedOrModifiedTimeUtc.
There was a problem hiding this comment.
(I don't imagine a modification to the file will always modify the directory timestamp; that'd be very strange in the case of hardlinks since there's not a backpointer anyways...)
There was a problem hiding this comment.
I guess at worst this potentially overreads a file if the directory timestamp changed? But I am not sure its necessary - maybe if there is a change in between original enumeration and when we get here?
There was a problem hiding this comment.
The problem is that when a new subdirectory is dropped in between walks, the timestamps of the subdirectory's files are not updated.
Only the "modified" timestamp of the parent directory, and the "created" timestamp of the subdirectory, are changed.
This means: even if a .cs file we encounter within the "new" subdirectory has old timestamps, we don't know whether we've seen it before or not, so we need to crack it.
Adding a comment.
| { | ||
| throw ExceptionUtilities.Unreachable(); | ||
| } | ||
| }, cancellationToken); |
There was a problem hiding this comment.
Yep, and check it in a few places.
| if (target is null) | ||
| { | ||
| _logger.LogWarning("Could not get a project for '{projectPath}' because it loaded with no targets", projectPath); | ||
| return null; |
There was a problem hiding this comment.
Is this the only case where we can return null? Maybe just throw in this case, since I think that means something is pretty broken?
There was a problem hiding this comment.
Especially since you're calling GetRequiredProject in the other path....
There was a problem hiding this comment.
could we get here if we failed to load the FBP file for some reason? What do we do in that case - fail to find the file and error out - or do we treat it as a standard misc file?
Not blocking here, but this is something we should make sure isn't a super horrible experience
| return document; | ||
| } | ||
|
|
||
| ProjectInfo CreatePrimordialProjectInfo(ProjectSystemProjectFactory projectFactory) |
There was a problem hiding this comment.
Consider just removing this parameter -- since this now returning the ProjectInfo at best you only need the workspace, but since we've already got a closure here being created just don't pass anything at all.
| }); | ||
|
|
||
| var discovery = testLspServer.GetRequiredLspService<FileBasedProgramsEntryPointDiscovery>(); | ||
| AssertEx.SequenceEqual([appFile.Path], discovery.FindEntryPoints(tempDir.Path)); |
There was a problem hiding this comment.
use the AndStable helper (ditto for any other uses in the file)
| var cacheDirectory = VirtualProjectXmlProvider.GetDiscoveryCacheDirectory(tempDir.Path); | ||
| Directory.Delete(cacheDirectory, recursive: true); | ||
|
|
||
| // Discovery without cache - should match | ||
| var uncachedResult = discovery.FindEntryPoints(tempDir.Path).Order(StringComparer.OrdinalIgnoreCase).ToArray(); | ||
| AssertEx.SequenceEqual(uncachedResult, cachedResult, StringComparer.OrdinalIgnoreCase); |
There was a problem hiding this comment.
You should be able to move this into the AndStable helper so that way you get this same guarantee for all tests. Heck do it three times: the and stable first does it once (that verifies the incremental update), then a second time (verifies there's a no-op) and then a third time after deleting the cache.
| // Directories can randomly fail to delete etc when we are thrashing the disk. | ||
| // Not a big deal and not a reason to fail the test, just move on to the next iteration instead. |
There was a problem hiding this comment.
Maybe a FailFast so we can see the process state? 😄
| try | ||
| { | ||
| using var token = listener.BeginAsyncOperation(nameof(FindAndLoadEntryPointsAsync)); | ||
| await FindAndLoadEntryPointsAsync(); |
There was a problem hiding this comment.
nit - you can use this pattern for the async listener and FatalError:
roslyn/src/EditorFeatures/Core/NavigateTo/NavigateToHelpers.cs
Lines 23 to 26 in 731242d
| } | ||
| catch (Exception ex) | ||
| { | ||
| _logger.LogDebug("Could not read cache file: {ex.Message}", ex.Message); |
There was a problem hiding this comment.
maybe warning? Assuming we don't generally expect this to fail.
| if (fileInfo.Kind == CsFileKind.Directory) | ||
| VisitDirectory(fileInfo.Path, Max(createdOrModifiedTimeUtc, fileInfo.CreatedOrModifiedTimeUtc)); | ||
| else if (fileInfo.Kind == CsFileKind.Cs) | ||
| VisitCsFile(fileInfo.Path, Max(createdOrModifiedTimeUtc, fileInfo.CreatedOrModifiedTimeUtc)); |
There was a problem hiding this comment.
I guess at worst this potentially overreads a file if the directory timestamp changed? But I am not sure its necessary - maybe if there is a change in between original enumeration and when we get here?
| if (target is null) | ||
| { | ||
| _logger.LogWarning("Could not get a project for '{projectPath}' because it loaded with no targets", projectPath); | ||
| return null; |
There was a problem hiding this comment.
could we get here if we failed to load the FBP file for some reason? What do we do in that case - fail to find the file and error out - or do we treat it as a standard misc file?
Not blocking here, but this is something we should make sure isn't a super horrible experience
|
I'm going to leave a number of comments outstanding here and try to address in a follow up. Thanks |
The feature doc lays out how this is meant to work.
Performance
As-is the discovery pass on dotnet/sdk runs in ~200ms on my PC without a cache and ~100ms with a warm cache.
In dotnet/runtime, ~600ms cold to ~170ms warm.
Note that the times in repos which actually have file-based apps, are going to reflect also the time of passing those file-based apps to the project system. So the more actual file-based apps that are discovered, the longer the reported pass will take.
TODOs
#!. This is because soon, containing#:will no longer mean that the file is for sure an entry point. Non-entry-point files will be allowed to have them too. Still need to update impl and tests accordingly.#!for file-based app entry points #82944.) As part of this we want to emit a warning in files which use#:include, and use top-level statements, and do not use#!, that user should add#!in order for editor to treat the file consistently in the workspace. This specific part should perhaps come in separate PR.Client-side PR for new config: dotnet/vscode-csharp#9096
Cache format
Example cache file contents:
{ "WorkspacePath": "c:\\Users\\rikki\\src\\roslyn", "LastWalkTimeUtc": "2026-03-24T22:41:36.945956+00:00", "FileBasedAppFullPaths": [ "c:\\Users\\rikki\\src\\roslyn\\eng\\ensure-sources-synced.cs", "c:\\Users\\rikki\\src\\roslyn\\eng\\generate-compiler-code.cs", "c:\\Users\\rikki\\src\\roslyn\\eng\\snap.cs" ], "DirectoriesContainingCsproj": [ "c:\\Users\\rikki\\src\\roslyn\\eng\\common\\internal", "c:\\Users\\rikki\\src\\roslyn\\src\\CodeStyle\\Core\\Analyzers", "c:\\Users\\rikki\\src\\roslyn\\src\\CodeStyle\\Core\\CodeFixes", "c:\\Users\\rikki\\src\\roslyn\\src\\CodeStyle\\Core\\Tests\\LegacyTestFramework", "c:\\Users\\rikki\\src\\roslyn\\src\\CodeStyle\\Core\\Tests\\UnitTestUtilities", "c:\\Users\\rikki\\src\\roslyn\\src\\CodeStyle\\CSharp\\Analyzers", "c:\\Users\\rikki\\src\\roslyn\\src\\CodeStyle\\CSharp\\CodeFixes", "c:\\Users\\rikki\\src\\roslyn\\src\\CodeStyle\\CSharp\\Tests", "c:\\Users\\rikki\\src\\roslyn\\src\\CodeStyle\\Tools", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Core\\CodeAnalysisTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Core\\MSBuildTaskTests", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Core\\MSBuildTask\\MSBuild", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Core\\MSBuildTask\\Sdk", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Core\\Portable", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Core\\Rebuild", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Core\\RebuildTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Core\\SdkTaskTests", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\csc\\AnyCpu", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\csc\\arm64", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Portable", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\CommandLine", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\CSharp15", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\Emit", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\Emit2", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\Emit3", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\EndToEnd", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\IOperation", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\Semantic", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\Symbol", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\Syntax", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\CSharp\\Test\\WinRT", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Extension", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Server\\VBCSCompilerTests", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Server\\VBCSCompiler\\AnyCpu", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Server\\VBCSCompiler\\arm64", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Test\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Test\\Resources\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\Test\\Utilities\\CSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\VisualBasic\\vbc\\AnyCpu", "c:\\Users\\rikki\\src\\roslyn\\src\\Compilers\\VisualBasic\\vbc\\arm64", "c:\\Users\\rikki\\src\\roslyn\\src\\Dependencies\\CodeAnalysis.Debugging", "c:\\Users\\rikki\\src\\roslyn\\src\\Dependencies\\Collections", "c:\\Users\\rikki\\src\\roslyn\\src\\Dependencies\\Contracts", "c:\\Users\\rikki\\src\\roslyn\\src\\Dependencies\\PooledObjects", "c:\\Users\\rikki\\src\\roslyn\\src\\Dependencies\\Threading", "c:\\Users\\rikki\\src\\roslyn\\src\\Deployment", "c:\\Users\\rikki\\src\\roslyn\\src\\EditorFeatures\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\EditorFeatures\\CSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\EditorFeatures\\CSharpTest", "c:\\Users\\rikki\\src\\roslyn\\src\\EditorFeatures\\CSharpTest2", "c:\\Users\\rikki\\src\\roslyn\\src\\EditorFeatures\\DiagnosticsTestUtilities", "c:\\Users\\rikki\\src\\roslyn\\src\\EditorFeatures\\ExternalAccess\\Debugger", "c:\\Users\\rikki\\src\\roslyn\\src\\EditorFeatures\\Test", "c:\\Users\\rikki\\src\\roslyn\\src\\EditorFeatures\\TestUtilities", "c:\\Users\\rikki\\src\\roslyn\\src\\EditorFeatures\\Text", "c:\\Users\\rikki\\src\\roslyn\\src\\EditorFeatures\\XunitHook", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\Core\\Source\\ExpressionCompiler", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\Core\\Source\\FunctionResolver", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\Core\\Source\\ResultProvider\\Portable", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\Core\\Test\\ExpressionCompiler", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\Core\\Test\\FunctionResolver", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\Core\\Test\\ResultProvider", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\CSharp\\Source\\ExpressionCompiler", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\CSharp\\Source\\ResultProvider\\Portable", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\CSharp\\Test\\ExpressionCompiler", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\CSharp\\Test\\ResultProvider", "c:\\Users\\rikki\\src\\roslyn\\src\\ExpressionEvaluator\\Package", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\Core\\Portable", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\CSharpTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\CSharp\\Portable", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\DiagnosticsTestUtilities", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\ExternalAccess\\AspNetCore", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\ExternalAccess\\Copilot", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\ExternalAccess\\HotReload", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\ExternalAccess\\HotReloadTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\ExternalAccess\\OmniSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\ExternalAccess\\OmniSharp.CSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\ExternalAccess\\OmniSharpTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\Test", "c:\\Users\\rikki\\src\\roslyn\\src\\Features\\TestUtilities", "c:\\Users\\rikki\\src\\roslyn\\src\\Interactive\\csi", "c:\\Users\\rikki\\src\\roslyn\\src\\Interactive\\Host", "c:\\Users\\rikki\\src\\roslyn\\src\\Interactive\\HostProcess\\x64", "c:\\Users\\rikki\\src\\roslyn\\src\\Interactive\\HostProcess\\x86", "c:\\Users\\rikki\\src\\roslyn\\src\\Interactive\\HostTest", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\ExternalAccess\\CompilerDeveloperSDK", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\ExternalAccess\\Copilot", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\ExternalAccess\\VisualDiagnostics", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\Microsoft.CodeAnalysis.LanguageServer", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\Microsoft.CodeAnalysis.LanguageServer.UnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\Microsoft.CommonLanguageServerProtocol.Framework", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\Microsoft.CommonLanguageServerProtocol.Framework.Example", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\Microsoft.CommonLanguageServerProtocol.Framework.UnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\Protocol", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\Protocol.TestUtilities", "c:\\Users\\rikki\\src\\roslyn\\src\\LanguageServer\\ProtocolUnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\NuGet\\Microsoft.CodeAnalysis.BuildClient.Package", "c:\\Users\\rikki\\src\\roslyn\\src\\NuGet\\Microsoft.CodeAnalysis.Compilers.Package", "c:\\Users\\rikki\\src\\roslyn\\src\\NuGet\\Microsoft.CodeAnalysis.EditorFeatures.Package", "c:\\Users\\rikki\\src\\roslyn\\src\\NuGet\\Microsoft.CodeAnalysis.Package", "c:\\Users\\rikki\\src\\roslyn\\src\\NuGet\\Microsoft.CodeAnalysis.Scripting.Package", "c:\\Users\\rikki\\src\\roslyn\\src\\NuGet\\Microsoft.Net.Compilers.Toolset\\AnyCpu", "c:\\Users\\rikki\\src\\roslyn\\src\\NuGet\\Microsoft.Net.Compilers.Toolset\\arm64", "c:\\Users\\rikki\\src\\roslyn\\src\\NuGet\\Microsoft.Net.Compilers.Toolset\\Framework", "c:\\Users\\rikki\\src\\roslyn\\src\\NuGet\\VS.ExternalAPIs.Roslyn.Package", "c:\\Users\\rikki\\src\\roslyn\\src\\NuGet\\VS.Tools.Roslyn.Package", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.Analyzers\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.Analyzers\\CSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.Analyzers\\Setup", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.Analyzers\\UnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.AnalyzerUtilities", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.BannedApiAnalyzers\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.BannedApiAnalyzers\\CSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.BannedApiAnalyzers\\Setup", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.BannedApiAnalyzers\\UnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.ResxSourceGenerator\\Microsoft.CodeAnalysis.ResxSourceGenerator", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.ResxSourceGenerator\\Microsoft.CodeAnalysis.ResxSourceGenerator.CSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.ResxSourceGenerator\\Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Microsoft.CodeAnalysis.ResxSourceGenerator\\Microsoft.CodeAnalysis.ResxSourceGenerator.VisualBasic", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\NuGet\\Microsoft.CodeAnalysis.Analyzers", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\NuGet\\Microsoft.CodeAnalysis.BannedApiAnalyzers", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\NuGet\\Microsoft.CodeAnalysis.Metrics", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\NuGet\\Microsoft.CodeAnalysis.ResxSourceGenerator", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\NuGet\\Microsoft.CodeAnalysis.RulesetToEditorconfigConverter", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\NuGet\\PerformanceSensitiveAnalyzers", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\NuGet\\PublicApiAnalyzers", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\NuGet\\Roslyn.Diagnostics.Analyzers", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\NuGet\\Text.Analyzers", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\PerformanceSensitiveAnalyzers\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\PerformanceSensitiveAnalyzers\\CSharp\\Analyzers", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\PerformanceSensitiveAnalyzers\\CSharp\\CodeFixes", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\PerformanceSensitiveAnalyzers\\Setup", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\PerformanceSensitiveAnalyzers\\UnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\PublicApiAnalyzers\\Core\\Analyzers", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\PublicApiAnalyzers\\Core\\CodeFixes", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\PublicApiAnalyzers\\Setup", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\PublicApiAnalyzers\\UnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Roslyn.Diagnostics.Analyzers\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Roslyn.Diagnostics.Analyzers\\CSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Roslyn.Diagnostics.Analyzers\\Setup", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Roslyn.Diagnostics.Analyzers\\UnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Test.Utilities", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\TestReferenceAssembly", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Text.Analyzers\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Text.Analyzers\\CSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Text.Analyzers\\Setup", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Text.Analyzers\\UnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Tools\\GenerateAnalyzerNuspec", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Tools\\GenerateDocumentationAndConfigFiles", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Tools\\GenerateDocumentationAndConfigFilesForBrokenRuntime", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Tools\\Metrics", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Tools\\Metrics.Legacy", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Tools\\RulesetToEditorconfigConverter\\Source", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Tools\\RulesetToEditorconfigConverter\\Tests", "c:\\Users\\rikki\\src\\roslyn\\src\\RoslynAnalyzers\\Utilities.UnitTests", "c:\\Users\\rikki\\src\\roslyn\\src\\Scripting\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\Scripting\\CoreTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Scripting\\CoreTest.Desktop", "c:\\Users\\rikki\\src\\roslyn\\src\\Scripting\\CoreTestUtilities", "c:\\Users\\rikki\\src\\roslyn\\src\\Scripting\\CSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\Scripting\\CSharpTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Scripting\\CSharpTest.Desktop", "c:\\Users\\rikki\\src\\roslyn\\src\\Setup\\DevDivInsertionFiles", "c:\\Users\\rikki\\src\\roslyn\\src\\Setup\\DevDivVsix\\CompilersPackage\\arm64", "c:\\Users\\rikki\\src\\roslyn\\src\\Setup\\DevDivVsix\\CompilersPackage\\x64", "c:\\Users\\rikki\\src\\roslyn\\src\\Setup\\DevDivVsix\\CompilersPackage\\x86", "c:\\Users\\rikki\\src\\roslyn\\src\\Test\\PdbUtilities", "c:\\Users\\rikki\\src\\roslyn\\src\\Test\\Perf\\StackDepthTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Test\\Perf\\tests", "c:\\Users\\rikki\\src\\roslyn\\src\\Test\\Perf\\Utilities", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\AnalyzerRunner", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\BuildActionTelemetryTable", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\BuildBoss", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\BuildValidator", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\ExternalAccess\\Extensions", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\ExternalAccess\\RazorCompiler", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\ExternalAccess\\RazorCompilerTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\ExternalAccess\\RazorTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\ExternalAccess\\Razor\\EditorFeatures", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\ExternalAccess\\Razor\\Features", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\ExternalAccess\\Xaml", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\GenerateRulesMissingDocumentation", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\IdeBenchmarks", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\IdeCoreBenchmarks", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\ManifestGenerator", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\PrepareTests", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\Replay", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\SemanticSearch\\BuildTask", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\SemanticSearch\\Extensions", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\SemanticSearch\\ReferenceAssemblies", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\SemanticSearch\\Tests", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\Source\\CompilerGeneratorTools\\Source\\BoundTreeGenerator", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\Source\\CompilerGeneratorTools\\Source\\CSharpErrorFactsGenerator", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\Source\\CompilerGeneratorTools\\Source\\CSharpSyntaxGenerator", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\Source\\CompilerGeneratorTools\\Source\\IOperationGenerator", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\Source\\RunTests", "c:\\Users\\rikki\\src\\roslyn\\src\\Tools\\TestDiscoveryWorker", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\CodeLens", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\Core\\Def", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\Core\\Impl", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\Core\\Test.Next", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\CSharp\\Impl", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\CSharp\\Test", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\DevKit\\Impl", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\ExternalAccess\\Apex", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\ExternalAccess\\Copilot", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\ExternalAccess\\EditorConfigGenerator", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\ExternalAccess\\FSharp", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\ExternalAccess\\FSharpTest", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\IntegrationTest", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\LiveShare\\Impl", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\LiveShare\\Test", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\Razor", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\SemanticSearch", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\Setup", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\Setup.Dependencies", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\Setup.ServiceHub\\arm64", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\Setup.ServiceHub\\x64", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\VisualStudioDiagnosticsToolWindow", "c:\\Users\\rikki\\src\\roslyn\\src\\VisualStudio\\Xaml\\Impl", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\CoreTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\CoreTestUtilities", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\Core\\Desktop", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\Core\\Portable", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\CSharpTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\CSharp\\Portable", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\MSBuild\\BuildHost", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\MSBuild\\Contracts", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\MSBuild\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\MSBuild\\Test", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\Remote\\Core", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\Remote\\ServiceHub", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\Remote\\ServiceHub.CoreComponents\\arm64", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\Remote\\ServiceHub.CoreComponents\\x64", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\Remote\\ServiceHubTest", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\SharedUtilitiesAndExtensions\\Compiler\\Extensions", "c:\\Users\\rikki\\src\\roslyn\\src\\Workspaces\\TestAnalyzerReference" ] }Microsoft Reviewers: Open in CodeFlow