-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove the BranchId concept from teh workspace #57132
Changes from all commits
0199590
2715c69
d6001fc
6812155
d1f781c
9aae5f7
7782d4b
effa0bf
d83c686
fea7fc9
ff2362b
7155386
19748d1
57c7932
e3f9cbc
48c9652
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
using System.Diagnostics; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Runtime.CompilerServices; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
@@ -48,16 +49,13 @@ public Factory() | |
|
||
private readonly object _gate = new(); | ||
|
||
/// <summary> | ||
/// Cached compile time solution corresponding to the <see cref="Workspace.PrimaryBranchId"/> | ||
/// </summary> | ||
private (int DesignTimeSolutionVersion, BranchId DesignTimeSolutionBranch, Solution CompileTimeSolution)? _primaryBranchCompileTimeCache; | ||
|
||
/// <summary> | ||
/// Cached compile time solution for a forked branch. This is used primarily by LSP cases where | ||
/// we fork the workspace solution and request diagnostics for the forked solution. | ||
/// </summary> | ||
private (int DesignTimeSolutionVersion, BranchId DesignTimeSolutionBranch, Solution CompileTimeSolution)? _forkedBranchCompileTimeCache; | ||
#if NETCOREAPP | ||
private readonly ConditionalWeakTable<Solution, Solution> _designTimeToCompileTimeSoution = new(); | ||
#else | ||
// Framework lacks both a .Clear() method. So for Framework we simulate that by just overwriting this with a | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Food for thought for a different PR: Is this a potential worthy data structure for us to eventually have? Something like a |
||
// new instance. This happens under a lock, so everyone sees a consistent dictionary. | ||
private ConditionalWeakTable<Solution, Solution> _designTimeToCompileTimeSoution = new(); | ||
#endif | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sadness. Framework lacks a 'clear' method on CWT. |
||
|
||
public CompileTimeSolutionProvider(Workspace workspace) | ||
{ | ||
|
@@ -67,8 +65,11 @@ public CompileTimeSolutionProvider(Workspace workspace) | |
{ | ||
lock (_gate) | ||
{ | ||
_primaryBranchCompileTimeCache = null; | ||
_forkedBranchCompileTimeCache = null; | ||
#if NETCOREAPP | ||
_designTimeToCompileTimeSoution.Clear(); | ||
#else | ||
_designTimeToCompileTimeSoution = new(); | ||
#endif | ||
} | ||
} | ||
}; | ||
|
@@ -82,83 +83,48 @@ public Solution GetCompileTimeSolution(Solution designTimeSolution) | |
{ | ||
lock (_gate) | ||
{ | ||
var cachedCompileTimeSolution = GetCachedCompileTimeSolution(designTimeSolution); | ||
|
||
// Design time solution hasn't changed since we calculated the last compile-time solution: | ||
if (cachedCompileTimeSolution != null) | ||
if (!_designTimeToCompileTimeSoution.TryGetValue(designTimeSolution, out var compileTimeSolution)) | ||
{ | ||
return cachedCompileTimeSolution; | ||
} | ||
|
||
using var _1 = ArrayBuilder<DocumentId>.GetInstance(out var configIdsToRemove); | ||
using var _2 = ArrayBuilder<DocumentId>.GetInstance(out var documentIdsToRemove); | ||
using var _1 = ArrayBuilder<DocumentId>.GetInstance(out var configIdsToRemove); | ||
using var _2 = ArrayBuilder<DocumentId>.GetInstance(out var documentIdsToRemove); | ||
|
||
foreach (var (_, projectState) in designTimeSolution.State.ProjectStates) | ||
{ | ||
var anyConfigs = false; | ||
|
||
foreach (var (_, configState) in projectState.AnalyzerConfigDocumentStates.States) | ||
foreach (var (_, projectState) in designTimeSolution.State.ProjectStates) | ||
{ | ||
if (IsRazorAnalyzerConfig(configState)) | ||
var anyConfigs = false; | ||
|
||
foreach (var (_, configState) in projectState.AnalyzerConfigDocumentStates.States) | ||
{ | ||
configIdsToRemove.Add(configState.Id); | ||
anyConfigs = true; | ||
if (IsRazorAnalyzerConfig(configState)) | ||
{ | ||
configIdsToRemove.Add(configState.Id); | ||
anyConfigs = true; | ||
} | ||
} | ||
} | ||
|
||
// only remove design-time only documents when source-generated ones replace them | ||
if (anyConfigs) | ||
{ | ||
foreach (var (_, documentState) in projectState.DocumentStates.States) | ||
// only remove design-time only documents when source-generated ones replace them | ||
if (anyConfigs) | ||
{ | ||
if (documentState.Attributes.DesignTimeOnly) | ||
foreach (var (_, documentState) in projectState.DocumentStates.States) | ||
{ | ||
documentIdsToRemove.Add(documentState.Id); | ||
if (documentState.Attributes.DesignTimeOnly) | ||
{ | ||
documentIdsToRemove.Add(documentState.Id); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
var compileTimeSolution = designTimeSolution | ||
.RemoveAnalyzerConfigDocuments(configIdsToRemove.ToImmutable()) | ||
.RemoveDocuments(documentIdsToRemove.ToImmutable()); | ||
compileTimeSolution = designTimeSolution | ||
.RemoveAnalyzerConfigDocuments(configIdsToRemove.ToImmutable()) | ||
.RemoveDocuments(documentIdsToRemove.ToImmutable()); | ||
|
||
UpdateCachedCompileTimeSolution(designTimeSolution, compileTimeSolution); | ||
_designTimeToCompileTimeSoution.Add(designTimeSolution, compileTimeSolution); | ||
} | ||
|
||
return compileTimeSolution; | ||
} | ||
} | ||
|
||
private Solution? GetCachedCompileTimeSolution(Solution designTimeSolution) | ||
{ | ||
// If the design time solution is for the primary branch, retrieve the last cached solution for it. | ||
// Otherwise this is a forked solution, so retrieve the last forked compile time solution we calculated. | ||
var cachedCompileTimeSolution = designTimeSolution.BranchId == _workspace.PrimaryBranchId ? _primaryBranchCompileTimeCache : _forkedBranchCompileTimeCache; | ||
|
||
// Verify that the design time solution has not changed since the last calculated compile time solution and that | ||
// the design time solution branch matches the branch of the design time solution we calculated the compile time solution for. | ||
if (cachedCompileTimeSolution != null | ||
&& designTimeSolution.WorkspaceVersion == cachedCompileTimeSolution.Value.DesignTimeSolutionVersion | ||
&& designTimeSolution.BranchId == cachedCompileTimeSolution.Value.DesignTimeSolutionBranch) | ||
{ | ||
return cachedCompileTimeSolution.Value.CompileTimeSolution; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
private void UpdateCachedCompileTimeSolution(Solution designTimeSolution, Solution compileTimeSolution) | ||
{ | ||
if (designTimeSolution.BranchId == _workspace.PrimaryBranchId) | ||
{ | ||
_primaryBranchCompileTimeCache = (designTimeSolution.WorkspaceVersion, designTimeSolution.BranchId, compileTimeSolution); | ||
} | ||
else | ||
{ | ||
_forkedBranchCompileTimeCache = (designTimeSolution.WorkspaceVersion, designTimeSolution.BranchId, compileTimeSolution); | ||
} | ||
} | ||
|
||
// Copied from | ||
// https://github.com/dotnet/sdk/blob/main/src/RazorSdk/SourceGenerators/RazorSourceGenerator.Helpers.cs#L32 | ||
private static string GetIdentifierFromPath(string filePath) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,8 +54,6 @@ public static async Task PrecalculateAsync(Document document, CancellationToken | |
|
||
using (Logger.LogBlock(FunctionId.SyntaxTreeIndex_Precalculate, cancellationToken)) | ||
{ | ||
Debug.Assert(document.IsFromPrimaryBranch()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not an unreasonable assert. we would prefer some assurances that our precalculation step is only running on the non-forked solution of some workspace. However, if that turns out to not be the case, it's not the end of the world as this ensure subsystem is checksum'ed based anyways. |
||
|
||
var checksum = await GetChecksumAsync(document, cancellationToken).ConfigureAwait(false); | ||
|
||
// Check if we've already created and persisted the index for this document. | ||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NTaylorMullen instead of a version+branch pointing to the CompileTimeSolution, i instead just use a CWT mapping teh actual designTimeSolution to the compileTimeSolution. As a CWT it will be released whenever people stop holding onto this solution.
Note: i checked with @dibarbet and for LSP as long as edits aren't coming in, we'll have the same solution instance, so thsi CWT should work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really appreciate you checking the LSP side of this too ❤️