diff --git a/.vscode/launch.json b/.vscode/launch.json
index ae371f1da31ef..5c446623b4d14 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -12,7 +12,10 @@
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/artifacts/bin/BuildValidator/Debug/netcoreapp3.1/BuildValidator.dll",
"args": [
- "--assembliesPath", "./artifacts/obj/RunTests",
+ "--assembliesPath", "./artifacts/obj/csc/Debug/netcoreapp3.1",
+ "--referencesPath", "./artifacts/bin",
+ "--referencesPath", "C:/Program Files/dotnet/packs/Microsoft.AspNetCore.App.Ref",
+ "--referencesPath", "C:/Program Files/dotnet/packs/Microsoft.NETCore.App.Ref",
"--debugPath", "./artifacts/BuildValidator",
"--sourcePath", "."
],
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index bb28e7fecfffc..13b78bf4cffba 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -215,7 +215,8 @@ jobs:
- job: Correctness_Rebuild
pool:
- vmImage: windows-2019
+ name: NetCorePublic-Pool
+ queue: BuildPool.Windows.10.Amd64.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-windows-task.yml
@@ -226,13 +227,7 @@ jobs:
filePath: eng/build.ps1
arguments: -configuration Debug -prepareMachine -ci -restore -binaryLog
- - task: PowerShell@2
- displayName: Build
- inputs:
- filePath: eng/build.ps1
- arguments: -configuration Debug -prepareMachine -ci -build -bootstrap -publish -binaryLog -skipDocumentation
-
- - script: .\artifacts\bin\BuildValidator\Debug\net472\BuildValidator.exe --assembliesPath .\artifacts\obj\Microsoft.CodeAnalysis --debugPath .\artifacts\BuildValidator --sourcePath .
+ - powershell: .\eng\test-rebuild.ps1 -ci
displayName: Run BuildValidator
- task: PublishBuildArtifacts@1
diff --git a/eng/Versions.props b/eng/Versions.props
index ff47291de76c7..d9cf03240810c 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -91,9 +91,8 @@
16.9.0-beta1.21055.5
1.5.0
3.0.0-preview1-03617-02
- 2.1.1
- 2.1.1
- 2.1.1
+ 5.0.0
+ 5.0.0
3.13.8
15.8.27812-alpha
14.3.25407-alpha
diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1
index 6e32af8866751..3ba5c48b83003 100644
--- a/eng/build-utils.ps1
+++ b/eng/build-utils.ps1
@@ -333,7 +333,7 @@ function Make-BootstrapBuild([switch]$force32 = $false) {
Run-MSBuild $projectPath "/restore /t:Pack /p:RoslynEnforceCodeStyle=false /p:RunAnalyzersDuringBuild=false /p:DotNetUseShippingVersions=true /p:InitialDefineConstants=BOOTSTRAP /p:PackageOutputPath=`"$dir`" /p:EnableNgenOptimization=false /p:PublishWindowsPdb=false $force32Flag" -logFileName "Bootstrap" -configuration $bootstrapConfiguration -runAnalyzers
$packageFile = Get-ChildItem -Path $dir -Filter "$packageName.*.nupkg"
- Unzip (Join-Path $dir $packageFile) $dir
+ Unzip (Join-Path $dir $packageFile.Name) $dir
Write-Host "Cleaning Bootstrap compiler artifacts"
Run-MSBuild $projectPath "/t:Clean" -logFileName "BootstrapClean"
diff --git a/eng/test-rebuild.ps1 b/eng/test-rebuild.ps1
index 10b83f7ce4a73..3bb1aac9eb35e 100644
--- a/eng/test-rebuild.ps1
+++ b/eng/test-rebuild.ps1
@@ -6,6 +6,7 @@
param(
[string]$configuration = "Debug",
[switch]$ci = $false,
+ [switch]$noBuild = $false,
[switch]$help)
Set-StrictMode -version 2.0
@@ -15,6 +16,7 @@ function Print-Usage() {
Write-Host "Usage: test-rebuild.ps1"
Write-Host " -configuration Build configuration ('Debug' or 'Release')"
Write-Host " -ci Set when running on CI server"
+ Write-Host " -noBuild If set, skips running a bootstrap build before running the rebuild"
Write-Host " -help Print help and exit"
}
@@ -27,9 +29,21 @@ try {
. (Join-Path $PSScriptRoot "build-utils.ps1")
Push-Location $RepoRoot
- Write-Host "Building Roslyn"
- Exec-Console (Join-Path $PSScriptRoot "build.ps1") "-restore -build -ci:$ci -configuration:$configuration -pack -binaryLog"
- Exec-Console "artifacts\bin\BuildValidator\$configuration\net472\BuildValidator.exe" "--assembliesPath '$ArtifactsDir/obj/Microsoft.CodeAnalysis'"
+ if (-not $noBuild) {
+ Write-Host "Building Roslyn"
+ Exec-Block { & (Join-Path $PSScriptRoot "build.ps1") -build -bootstrap -ci:$ci -configuration:$configuration -pack -binaryLog }
+ }
+
+ $dotnetInstallDir = (InitializeDotNetCli -install:$true)
+ $rebuildArgs = ("--verbose" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis/$configuration`"" +
+ " --assembliesPath $ArtifactsDir/obj/csc/$configuration/netcoreapp3.1" +
+ " --debugPath `"$ArtifactsDir/BuildValidator`"" +
+ " --sourcePath `"$RepoRoot`"" +
+ " --referencesPath `"$ArtifactsDir/bin`"" +
+ " --referencesPath `"$dotnetInstallDir/packs/Microsoft.AspNetCore.App.Ref`"" +
+ " --referencesPath `"$dotnetInstallDir/packs/Microsoft.NETCore.App.Ref`"")
+ Exec-Console "$ArtifactsDir/bin/BuildValidator/$configuration/net472/BuildValidator.exe" $rebuildArgs
exit 0
}
diff --git a/src/Compilers/CSharp/csc/csc.csproj b/src/Compilers/CSharp/csc/csc.csproj
index 01e6741bb0961..cc6e6cabf8098 100644
--- a/src/Compilers/CSharp/csc/csc.csproj
+++ b/src/Compilers/CSharp/csc/csc.csproj
@@ -12,6 +12,7 @@
true
false
true
+ true
diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.cs
index cfb3d808f9c38..3ca7347fd4759 100644
--- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.cs
@@ -34,13 +34,16 @@ public class ExtensionMethodImportCompletionProviderTests : AbstractCSharpComple
private bool HideAdvancedMembers { get; set; }
+ private bool UsePartialSemantic { get; set; } = false;
+
protected override OptionSet WithChangedOptions(OptionSet options)
{
return options
.WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp, ShowImportCompletionItemsOptionValue)
.WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, IsExpandedCompletion)
.WithChangedOption(CompletionOptions.HideAdvancedMembers, LanguageNames.CSharp, HideAdvancedMembers)
- .WithChangedOption(CompletionServiceOptions.TimeoutInMillisecondsForExtensionMethodImportCompletion, TimeoutInMilliseconds);
+ .WithChangedOption(CompletionServiceOptions.TimeoutInMillisecondsForExtensionMethodImportCompletion, TimeoutInMilliseconds)
+ .WithChangedOption(CompletionServiceOptions.UsePartialSemanticForImportCompletion, UsePartialSemantic);
}
protected override TestComposition GetComposition()
diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs
index 808c679e06f5c..61cf9343de22a 100644
--- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs
@@ -33,13 +33,16 @@ internal override Type GetCompletionProviderType()
private bool HideAdvancedMembers { get; set; }
+ private bool UsePartialSemantic { get; set; } = false;
+
protected override OptionSet WithChangedOptions(OptionSet options)
{
return options
.WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp, ShowImportCompletionItemsOptionValue)
.WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, IsExpandedCompletion)
.WithChangedOption(CompletionServiceOptions.DisallowAddingImports, DisallowAddingImports)
- .WithChangedOption(CompletionOptions.HideAdvancedMembers, LanguageNames.CSharp, HideAdvancedMembers);
+ .WithChangedOption(CompletionOptions.HideAdvancedMembers, LanguageNames.CSharp, HideAdvancedMembers)
+ .WithChangedOption(CompletionServiceOptions.UsePartialSemanticForImportCompletion, UsePartialSemantic);
}
protected override TestComposition GetComposition()
diff --git a/src/EditorFeatures/Test/Diagnostics/DiagnosticDataSerializerTests.cs b/src/EditorFeatures/Test/Diagnostics/DiagnosticDataSerializerTests.cs
index 0b561853b1862..6002a22d63a53 100644
--- a/src/EditorFeatures/Test/Diagnostics/DiagnosticDataSerializerTests.cs
+++ b/src/EditorFeatures/Test/Diagnostics/DiagnosticDataSerializerTests.cs
@@ -349,9 +349,14 @@ public Task WriteStreamAsync(Document document, string name, Stream stream
return SpecializedTasks.True;
}
- public virtual void Dispose()
+ public void Dispose()
{
}
+
+ public ValueTask DisposeAsync()
+ {
+ return ValueTaskFactory.CompletedTask;
+ }
}
}
}
diff --git a/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs b/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs
index 5d7b4aef25381..4db4b72a73af6 100644
--- a/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs
+++ b/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs
@@ -127,7 +127,7 @@ public async Task TestPreviewServices()
var persistentService = previewWorkspace.Services.GetRequiredService();
- using var storage = await persistentService.GetStorageAsync(previewWorkspace.CurrentSolution, CancellationToken.None);
+ await using var storage = await persistentService.GetStorageAsync(previewWorkspace.CurrentSolution, CancellationToken.None);
Assert.IsType(storage);
}
diff --git a/src/EditorFeatures/Text/Extensions.cs b/src/EditorFeatures/Text/Extensions.cs
index c38c3d7ab7c61..c0abe4ace4d07 100644
--- a/src/EditorFeatures/Text/Extensions.cs
+++ b/src/EditorFeatures/Text/Extensions.cs
@@ -84,19 +84,6 @@ public static IEnumerable GetRelatedDocumentsWithChanges(this ITextSna
public static IEnumerable GetRelatedDocuments(this ITextBuffer buffer)
=> buffer.AsTextContainer().GetRelatedDocuments();
- ///
- /// Tries to get the document corresponding to the text from the current partial solution
- /// associated with the text's container. If the document does not contain the exact text a document
- /// from a new solution containing the specified text is constructed. If no document is associated
- /// with the specified text's container, or the text's container isn't associated with a workspace,
- /// then the method returns false.
- ///
- internal static Document? GetDocumentWithFrozenPartialSemantics(this SourceText text, CancellationToken cancellationToken)
- {
- var document = text.GetOpenDocumentInCurrentContextWithChanges();
- return document?.WithFrozenPartialSemantics(cancellationToken);
- }
-
internal static bool CanApplyChangeDocumentToWorkspace(this ITextBuffer buffer)
=> Workspace.TryGetWorkspace(buffer.AsTextContainer(), out var workspace) &&
workspace.CanApplyChange(ApplyChangesKind.ChangeDocument);
diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.vb
index c9cf512757760..93a087195ce35 100644
--- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.vb
+++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.vb
@@ -18,12 +18,14 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
Private Property TimeoutInMilliseconds As Integer = -1
Private Property ShowImportCompletionItemsOptionValue As Boolean = True
+ Private Property UsePartialSemantic As Boolean = False
Protected Overrides Function WithChangedOptions(options As OptionSet) As OptionSet
Return options _
.WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, LanguageNames.VisualBasic, ShowImportCompletionItemsOptionValue) _
.WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, IsExpandedCompletion) _
- .WithChangedOption(CompletionServiceOptions.TimeoutInMillisecondsForExtensionMethodImportCompletion, TimeoutInMilliseconds)
+ .WithChangedOption(CompletionServiceOptions.TimeoutInMillisecondsForExtensionMethodImportCompletion, TimeoutInMilliseconds) _
+ .WithChangedOption(CompletionServiceOptions.UsePartialSemanticForImportCompletion, UsePartialSemantic)
End Function
Protected Overrides Function GetComposition() As TestComposition
diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.vb
index 890b260696255..a21a9f8bafc6a 100644
--- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.vb
+++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.vb
@@ -15,11 +15,13 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
Private Property ShowImportCompletionItemsOptionValue As Boolean = True
Private Property IsExpandedCompletion As Boolean = True
+ Private Property UsePartialSemantic As Boolean = False
Protected Overrides Function WithChangedOptions(options As OptionSet) As OptionSet
Return options _
.WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, LanguageNames.VisualBasic, ShowImportCompletionItemsOptionValue) _
- .WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, IsExpandedCompletion)
+ .WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, IsExpandedCompletion) _
+ .WithChangedOption(CompletionServiceOptions.UsePartialSemanticForImportCompletion, UsePartialSemantic)
End Function
Protected Overrides Function GetComposition() As TestComposition
diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ExtensionMethodImportCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ExtensionMethodImportCompletionProvider.cs
index 02e8cc228aba9..da74b72eff123 100644
--- a/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ExtensionMethodImportCompletionProvider.cs
+++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ExtensionMethodImportCompletionProvider.cs
@@ -44,8 +44,8 @@ protected override ImmutableArray GetImportedNamespaces(
CancellationToken cancellationToken)
=> ImportCompletionProviderHelper.GetImportedNamespaces(location, semanticModel);
- protected override Task CreateContextAsync(Document document, int position, CancellationToken cancellationToken)
- => ImportCompletionProviderHelper.CreateContextAsync(document, position, cancellationToken);
+ protected override Task CreateContextAsync(Document document, int position, bool usePartialSemantic, CancellationToken cancellationToken)
+ => ImportCompletionProviderHelper.CreateContextAsync(document, position, usePartialSemantic, cancellationToken);
protected override bool IsFinalSemicolonOfUsingOrExtern(SyntaxNode directive, SyntaxToken token)
{
diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ImportCompletionProviderHelper.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ImportCompletionProviderHelper.cs
index 10208430c8253..5115b26714e29 100644
--- a/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ImportCompletionProviderHelper.cs
+++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ImportCompletionProviderHelper.cs
@@ -21,11 +21,15 @@ public static ImmutableArray GetImportedNamespaces(
=> semanticModel.GetUsingNamespacesInScope(location)
.SelectAsArray(namespaceSymbol => namespaceSymbol.ToDisplayString(SymbolDisplayFormats.NameFormat));
- public static async Task CreateContextAsync(Document document, int position, CancellationToken cancellationToken)
+ public static async Task CreateContextAsync(Document document, int position, bool usePartialSemantic, CancellationToken cancellationToken)
{
// Need regular semantic model because we will use it to get imported namespace symbols. Otherwise we will try to
// reach outside of the span and ended up with "node not within syntax tree" error from the speculative model.
- var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
+ // Also we use partial model unless full model is explictly request (e.g. in tests) so that we don't have to wait for all semantics to be computed.
+ var semanticModel = usePartialSemantic
+ ? await document.GetPartialSemanticModelAsync(cancellationToken).ConfigureAwait(false)
+ : await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
+ Contract.ThrowIfNull(semanticModel);
return CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken);
}
}
diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/TypeImportCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/TypeImportCompletionProvider.cs
index 6d7dd6cc3a0e4..59e6118414cbd 100644
--- a/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/TypeImportCompletionProvider.cs
+++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/TypeImportCompletionProvider.cs
@@ -45,8 +45,8 @@ protected override ImmutableArray GetImportedNamespaces(
CancellationToken cancellationToken)
=> ImportCompletionProviderHelper.GetImportedNamespaces(location, semanticModel);
- protected override Task CreateContextAsync(Document document, int position, CancellationToken cancellationToken)
- => ImportCompletionProviderHelper.CreateContextAsync(document, position, cancellationToken);
+ protected override Task CreateContextAsync(Document document, int position, bool usePartialSemantic, CancellationToken cancellationToken)
+ => ImportCompletionProviderHelper.CreateContextAsync(document, position, usePartialSemantic, cancellationToken);
protected override bool IsFinalSemicolonOfUsingOrExtern(SyntaxNode directive, SyntaxToken token)
{
diff --git a/src/Features/Core/Portable/Completion/CompletionServiceOptions.cs b/src/Features/Core/Portable/Completion/CompletionServiceOptions.cs
index e059d2fb688c3..15df57e3e42a4 100644
--- a/src/Features/Core/Portable/Completion/CompletionServiceOptions.cs
+++ b/src/Features/Core/Portable/Completion/CompletionServiceOptions.cs
@@ -14,6 +14,12 @@ internal static class CompletionServiceOptions
public static readonly Option2 IsExpandedCompletion
= new(nameof(CompletionServiceOptions), nameof(IsExpandedCompletion), defaultValue: false);
+ ///
+ /// For testing only. Changing the default value in actual product might cause perf issues.
+ ///
+ public static readonly Option2 UsePartialSemanticForImportCompletion
+ = new(nameof(CompletionServiceOptions), nameof(UsePartialSemanticForImportCompletion), defaultValue: true);
+
///
/// Indicates if the completion should be disallowed to add imports.
///
diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs
index 22cce31897d64..b5f68b5edb547 100644
--- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs
+++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs
@@ -22,7 +22,7 @@ namespace Microsoft.CodeAnalysis.Completion.Providers
{
internal abstract class AbstractImportCompletionProvider : LSPCompletionProvider
{
- protected abstract Task CreateContextAsync(Document document, int position, CancellationToken cancellationToken);
+ protected abstract Task CreateContextAsync(Document document, int position, bool usePartialSemantic, CancellationToken cancellationToken);
protected abstract ImmutableArray GetImportedNamespaces(SyntaxNode location, SemanticModel semanticModel, CancellationToken cancellationToken);
protected abstract bool ShouldProvideCompletion(CompletionContext completionContext, SyntaxContext syntaxContext);
protected abstract Task AddCompletionItemsAsync(CompletionContext completionContext, SyntaxContext syntaxContext, HashSet namespacesInScope, bool isExpandedCompletion, CancellationToken cancellationToken);
@@ -54,7 +54,8 @@ public override async Task ProvideCompletionsAsync(CompletionContext completionC
// We need to check for context before option values, so we can tell completion service that we are in a context to provide expanded items
// even though import completion might be disabled. This would show the expander in completion list which user can then use to explicitly ask for unimported items.
- var syntaxContext = await CreateContextAsync(document, completionContext.Position, cancellationToken).ConfigureAwait(false);
+ var usePartialSemantic = completionContext.Options.GetOption(CompletionServiceOptions.UsePartialSemanticForImportCompletion);
+ var syntaxContext = await CreateContextAsync(document, completionContext.Position, usePartialSemantic, cancellationToken).ConfigureAwait(false);
if (!ShouldProvideCompletion(completionContext, syntaxContext))
{
return;
diff --git a/src/Features/Core/Portable/SolutionCrawler/State/AbstractAnalyzerState.cs b/src/Features/Core/Portable/SolutionCrawler/State/AbstractAnalyzerState.cs
index 119913a91aa92..7d3043672cb77 100644
--- a/src/Features/Core/Portable/SolutionCrawler/State/AbstractAnalyzerState.cs
+++ b/src/Features/Core/Portable/SolutionCrawler/State/AbstractAnalyzerState.cs
@@ -61,7 +61,8 @@ public async Task TryGetExistingDataAsync(TValue value, CancellationToken
try
{
- using var storage = await persistService.GetStorageAsync(solution, cancellationToken).ConfigureAwait(false);
+ var storage = await persistService.GetStorageAsync(solution, cancellationToken).ConfigureAwait(false);
+ await using var _ = storage.ConfigureAwait(false);
using var stream = await ReadStreamAsync(storage, value, cancellationToken).ConfigureAwait(false);
if (stream != null)
@@ -102,7 +103,8 @@ private async Task WriteToStreamAsync(TValue value, TData data, Cancellati
var solution = GetSolution(value);
var persistService = solution.Workspace.Services.GetService();
- using var storage = await persistService.GetStorageAsync(solution, cancellationToken).ConfigureAwait(false);
+ var storage = await persistService.GetStorageAsync(solution, cancellationToken).ConfigureAwait(false);
+ await using var _ = storage.ConfigureAwait(false);
stream.Position = 0;
return await WriteStreamAsync(storage, value, stream, cancellationToken).ConfigureAwait(false);
}
diff --git a/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs b/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs
index 714219d32c531..68a960905b158 100644
--- a/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs
+++ b/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs
@@ -116,7 +116,8 @@ private async Task CreateSpellCheckCodeIssueAsync(
var originalOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var options = originalOptions
.WithChangedOption(CompletionOptions.SnippetsBehavior, document.Project.Language, SnippetsRule.NeverInclude)
- .WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, document.Project.Language, false);
+ .WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, document.Project.Language, false)
+ .WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, false);
var completionList = await service.GetCompletionsAsync(
document, nameToken.SpanStart, options: options, cancellationToken: cancellationToken).ConfigureAwait(false);
diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs
index 99e8c3d6ab9b7..68cdb23096e87 100644
--- a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs
+++ b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs
@@ -61,7 +61,7 @@ void M()
var solution = testLspServer.TestWorkspace.CurrentSolution;
// Make sure the unimported types option is on by default.
- solution = solution.WithOptions(solution.Options
+ testLspServer.TestWorkspace.SetOptions(testLspServer.TestWorkspace.CurrentSolution.Options
.WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp, true)
.WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, true));
diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ExtensionMethodImportCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ExtensionMethodImportCompletionProvider.vb
index 532159840d425..ff0e435bcafcc 100644
--- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ExtensionMethodImportCompletionProvider.vb
+++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ExtensionMethodImportCompletionProvider.vb
@@ -37,8 +37,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Public Overrides ReadOnly Property TriggerCharacters As ImmutableHashSet(Of Char) = CompletionUtilities.CommonTriggerCharsAndParen
- Protected Overrides Function CreateContextAsync(document As Document, position As Integer, cancellationToken As CancellationToken) As Task(Of SyntaxContext)
- Return ImportCompletionProviderHelper.CreateContextAsync(document, position, cancellationToken)
+ Protected Overrides Function CreateContextAsync(document As Document, position As Integer, usePartialSemantic As Boolean, cancellationToken As CancellationToken) As Task(Of SyntaxContext)
+ Return ImportCompletionProviderHelper.CreateContextAsync(document, position, usePartialSemantic, cancellationToken)
End Function
Protected Overrides Function GetImportedNamespaces(location As SyntaxNode, semanticModel As SemanticModel, cancellationToken As CancellationToken) As ImmutableArray(Of String)
diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ImportCompletionProviderHelper.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ImportCompletionProviderHelper.vb
index 9c6703fa937cd..8de0fc9964150 100644
--- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ImportCompletionProviderHelper.vb
+++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ImportCompletionProviderHelper.vb
@@ -30,10 +30,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Return builder.ToImmutableAndFree()
End Function
- Public Shared Async Function CreateContextAsync(document As Document, position As Integer, cancellationToken As CancellationToken) As Task(Of SyntaxContext)
+ Public Shared Async Function CreateContextAsync(document As Document, position As Integer, usePartialSemantic As Boolean, cancellationToken As CancellationToken) As Task(Of SyntaxContext)
' Need regular semantic model because we will use it to get imported namespace symbols. Otherwise we will try to
' reach outside of the span And ended up with "node not within syntax tree" error from the speculative model.
- Dim semanticModel = Await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(False)
+ ' Also we use partial model unless full model is explictly request (e.g. in tests) so that we don't have to wait for all semantics to be computed.
+ Dim semanticModel = If(usePartialSemantic,
+ Await document.GetPartialSemanticModelAsync(cancellationToken).ConfigureAwait(False),
+ Await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(False))
+ Contract.ThrowIfNull(semanticModel)
Return VisualBasicSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken)
End Function
End Class
diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/TypeImportCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/TypeImportCompletionProvider.vb
index 5e3cf4798c8c4..70b9147188e26 100644
--- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/TypeImportCompletionProvider.vb
+++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/TypeImportCompletionProvider.vb
@@ -32,8 +32,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Public Overrides ReadOnly Property TriggerCharacters As ImmutableHashSet(Of Char) = CompletionUtilities.CommonTriggerCharsAndParen
- Protected Overrides Function CreateContextAsync(document As Document, position As Integer, cancellationToken As CancellationToken) As Task(Of SyntaxContext)
- Return ImportCompletionProviderHelper.CreateContextAsync(document, position, cancellationToken)
+ Protected Overrides Function CreateContextAsync(document As Document, position As Integer, usePartialSemantic As Boolean, cancellationToken As CancellationToken) As Task(Of SyntaxContext)
+ Return ImportCompletionProviderHelper.CreateContextAsync(document, position, usePartialSemantic, cancellationToken)
End Function
Protected Overrides Function GetImportedNamespaces(location As SyntaxNode, semanticModel As SemanticModel, cancellationToken As CancellationToken) As ImmutableArray(Of String)
diff --git a/src/Tools/AnalyzerRunner/IncrementalAnalyzerRunner.cs b/src/Tools/AnalyzerRunner/IncrementalAnalyzerRunner.cs
index 9a86808f42d82..59a27b0e8093e 100644
--- a/src/Tools/AnalyzerRunner/IncrementalAnalyzerRunner.cs
+++ b/src/Tools/AnalyzerRunner/IncrementalAnalyzerRunner.cs
@@ -55,7 +55,7 @@ public async Task RunAsync(CancellationToken cancellationToken)
if (usePersistentStorage)
{
var persistentStorageService = _workspace.Services.GetRequiredService();
- using var persistentStorage = await persistentStorageService.GetStorageAsync(_workspace.CurrentSolution, cancellationToken).ConfigureAwait(false);
+ await using var persistentStorage = await persistentStorageService.GetStorageAsync(_workspace.CurrentSolution, cancellationToken).ConfigureAwait(false);
if (persistentStorage is NoOpPersistentStorage)
{
throw new InvalidOperationException("Benchmark is not configured to use persistent storage.");
diff --git a/src/Tools/BuildValidator/BuildConstructor.cs b/src/Tools/BuildValidator/BuildConstructor.cs
index 7919972107383..bfac2b9d93830 100644
--- a/src/Tools/BuildValidator/BuildConstructor.cs
+++ b/src/Tools/BuildValidator/BuildConstructor.cs
@@ -38,7 +38,7 @@ public BuildConstructor(LocalReferenceResolver referenceResolver, LocalSourceRes
_logger = logger;
}
- public Compilation CreateCompilation(CompilationOptionsReader compilationOptionsReader, string name)
+ public Compilation CreateCompilation(CompilationOptionsReader compilationOptionsReader, string fileName)
{
var pdbCompilationOptions = compilationOptionsReader.GetMetadataCompilationOptions();
if (pdbCompilationOptions.Length == 0)
@@ -62,8 +62,8 @@ public Compilation CreateCompilation(CompilationOptionsReader compilationOptions
{
var compilation = language switch
{
- LanguageNames.CSharp => CreateCSharpCompilation(name, compilationOptionsReader, sources, metadataReferences),
- LanguageNames.VisualBasic => CreateVisualBasicCompilation(name, compilationOptionsReader, sources, metadataReferences),
+ LanguageNames.CSharp => CreateCSharpCompilation(fileName, compilationOptionsReader, sources, metadataReferences),
+ LanguageNames.VisualBasic => CreateVisualBasicCompilation(fileName, compilationOptionsReader, sources, metadataReferences),
_ => throw new InvalidDataException($"{language} is not a known language")
};
@@ -88,7 +88,10 @@ void logResolvedSources()
{
var sourceFileInfo = resolvedSource.SourceFileInfo;
var hash = BitConverter.ToString(sourceFileInfo.Hash).Replace("-", "");
- _logger.LogInformation($@"""{resolvedSource.DisplayPath}"" - {sourceFileInfo.HashAlgorithm} - {hash}");
+ var embeddedCompressedHash = sourceFileInfo.EmbeddedCompressedHash is { } compressedHash
+ ? ("[uncompressed]" + BitConverter.ToString(compressedHash).Replace("-", ""))
+ : null;
+ _logger.LogInformation($@"""{resolvedSource.DisplayPath}"" - {sourceFileInfo.HashAlgorithm} - {hash} - {embeddedCompressedHash}");
}
}
}
@@ -129,20 +132,20 @@ private ImmutableArray ResolveSources(
#region CSharp
private Compilation CreateCSharpCompilation(
- string assemblyName,
+ string fileName,
CompilationOptionsReader optionsReader,
ImmutableArray sources,
ImmutableArray metadataReferences)
{
- var (compilationOptions, parseOptions) = CreateCSharpCompilationOptions(optionsReader, assemblyName);
+ var (compilationOptions, parseOptions) = CreateCSharpCompilationOptions(optionsReader, fileName);
return CSharpCompilation.Create(
- assemblyName,
+ Path.GetFileNameWithoutExtension(fileName),
syntaxTrees: sources.Select(s => CSharpSyntaxTree.ParseText(s.SourceText, options: parseOptions, path: s.SourceFileInfo.SourceFilePath)).ToImmutableArray(),
references: metadataReferences,
options: compilationOptions);
}
- private (CSharpCompilationOptions, CSharpParseOptions) CreateCSharpCompilationOptions(CompilationOptionsReader optionsReader, string assemblyName)
+ private (CSharpCompilationOptions, CSharpParseOptions) CreateCSharpCompilationOptions(CompilationOptionsReader optionsReader, string fileName)
{
using var scope = _logger.BeginScope("Options");
var pdbCompilationOptions = optionsReader.GetMetadataCompilationOptions();
@@ -175,9 +178,7 @@ private Compilation CreateCSharpCompilation(
optionsReader.GetOutputKind(),
reportSuppressedDiagnostics: false,
- // TODO: can't rely on the implicity moduleName here. In the case of .NET Core EXE the output name will
- // end with .dll but the inferred name will be .exe
- moduleName: assemblyName + ".dll",
+ moduleName: fileName,
mainTypeName: optionsReader.GetMainTypeName(),
scriptClassName: null,
usings: null,
@@ -213,10 +214,10 @@ private Compilation CreateCSharpCompilation(
return (compilationOptions, parseOptions);
}
- private static (OptimizationLevel, bool) GetOptimizationLevel(string optimizationLevel)
+ private static (OptimizationLevel, bool) GetOptimizationLevel(string? optimizationLevel)
=> optimizationLevel switch
{
- "debug" => (OptimizationLevel.Debug, false),
+ null or "debug" => (OptimizationLevel.Debug, false),
"debug-plus" => (OptimizationLevel.Debug, true),
"release" => (OptimizationLevel.Release, false),
_ => throw new InvalidDataException($"Optimization \"{optimizationLevel}\" level not recognized")
@@ -226,14 +227,14 @@ private static (OptimizationLevel, bool) GetOptimizationLevel(string optimizatio
#region Visual Basic
private Compilation CreateVisualBasicCompilation(
- string assemblyName,
+ string fileName,
CompilationOptionsReader optionsReader,
ImmutableArray sources,
ImmutableArray metadataReferences)
{
var compilationOptions = CreateVisualBasicCompilationOptions(optionsReader);
return VisualBasicCompilation.Create(
- assemblyName,
+ Path.GetFileNameWithoutExtension(fileName),
syntaxTrees: sources.Select(s => VisualBasicSyntaxTree.ParseText(s.SourceText, options: compilationOptions.ParseOptions, path: s.DisplayPath)).ToImmutableArray(),
references: metadataReferences,
options: compilationOptions);
@@ -244,7 +245,7 @@ private static VisualBasicCompilationOptions CreateVisualBasicCompilationOptions
var pdbCompilationOptions = optionsReader.GetMetadataCompilationOptions();
var langVersionString = pdbCompilationOptions.GetUniqueOption("language-version");
- var optimization = pdbCompilationOptions.GetUniqueOption("optimization");
+ pdbCompilationOptions.TryGetUniqueOption("optimization", out var optimization);
pdbCompilationOptions.TryGetUniqueOption("define", out var define);
pdbCompilationOptions.TryGetUniqueOption("strict", out var strict);
pdbCompilationOptions.TryGetUniqueOption("checked", out var checkedString);
diff --git a/src/Tools/BuildValidator/BuildValidator.csproj b/src/Tools/BuildValidator/BuildValidator.csproj
index 1634c165010d1..1f87b9e58f7e8 100644
--- a/src/Tools/BuildValidator/BuildValidator.csproj
+++ b/src/Tools/BuildValidator/BuildValidator.csproj
@@ -22,6 +22,7 @@
+
diff --git a/src/Tools/BuildValidator/CompilationDiff.cs b/src/Tools/BuildValidator/CompilationDiff.cs
index ee3828d61bfd7..f0729cb069dc8 100644
--- a/src/Tools/BuildValidator/CompilationDiff.cs
+++ b/src/Tools/BuildValidator/CompilationDiff.cs
@@ -18,6 +18,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Text;
+using Microsoft.DiaSymReader.Tools;
using Microsoft.Extensions.Logging;
using Microsoft.Metadata.Tools;
@@ -61,6 +62,13 @@ public static unsafe CompilationDiff Create(
iconInIcoFormat: null);
var sourceLink = optionsReader.GetSourceLinkUTF8();
+
+ var embeddedTexts = producedCompilation.SyntaxTrees
+ .Select(st => (path: st.FilePath, text: st.GetText()))
+ .Where(pair => pair.text.CanBeEmbedded)
+ .Select(pair => EmbeddedText.FromSource(pair.path, pair.text))
+ .ToImmutableArray();
+
var emitResult = producedCompilation.Emit(
peStream: rebuildPeStream,
pdbStream: null,
@@ -73,10 +81,7 @@ public static unsafe CompilationDiff Create(
metadataPEStream: null,
pdbOptionsBlobReader: optionsReader.GetMetadataCompilationOptionsBlobReader(),
sourceLinkStream: sourceLink != null ? new MemoryStream(sourceLink) : null,
- embeddedTexts: producedCompilation.SyntaxTrees
- .Select(st => (path: st.FilePath, text: st.GetText()))
- .Where(pair => pair.text.CanBeEmbedded)
- .Select(pair => EmbeddedText.FromSource(pair.path, pair.text)),
+ embeddedTexts: embeddedTexts,
cancellationToken: CancellationToken.None);
if (!emitResult.Success)
@@ -141,6 +146,26 @@ public static unsafe CompilationDiff Create(
writeVisualization(originalPeMdvPath, optionsReader.PeReader.GetMetadataReader());
writeVisualization(originalPdbMdvPath, optionsReader.PdbReader);
+ var originalPdbXmlPath = Path.Combine(originalPath, assemblyName + ".pdb.xml");
+ using var originalPdbXml = File.Create(originalPdbXmlPath);
+
+ var rebuildPdbXmlPath = Path.Combine(rebuildPath, assemblyName + ".pdb.xml");
+
+ var pdbToXmlOptions = PdbToXmlOptions.ResolveTokens
+ | PdbToXmlOptions.ThrowOnError
+ | PdbToXmlOptions.ExcludeScopes
+ | PdbToXmlOptions.IncludeSourceServerInformation
+ | PdbToXmlOptions.IncludeEmbeddedSources
+ | PdbToXmlOptions.IncludeTokens
+ | PdbToXmlOptions.IncludeMethodSpans;
+
+ PdbToXmlConverter.ToXml(
+ new StreamWriter(originalPdbXml),
+ pdbStream: new UnmanagedMemoryStream(optionsReader.PdbReader.MetadataPointer, optionsReader.PdbReader.MetadataLength),
+ peStream: new MemoryStream(originalBytes),
+ options: pdbToXmlOptions,
+ methodName: null);
+
var rebuildPeMdvPath = Path.Combine(rebuildPath, assemblyName + ".pe.mdv");
var rebuildPdbMdvPath = Path.Combine(rebuildPath, assemblyName + ".pdb.mdv");
fixed (byte* ptr = rebuildBytes)
@@ -156,6 +181,28 @@ public static unsafe CompilationDiff Create(
{
var rebuildPdbReader = provider.GetMetadataReader(MetadataReaderOptions.Default);
writeVisualization(rebuildPdbMdvPath, rebuildPdbReader);
+
+ using var rebuildPdbXml = File.Create(rebuildPdbXmlPath);
+ PdbToXmlConverter.ToXml(
+ new StreamWriter(rebuildPdbXml),
+ pdbStream: new UnmanagedMemoryStream(rebuildPdbReader.MetadataPointer, rebuildPdbReader.MetadataLength),
+ peStream: new MemoryStream(rebuildBytes),
+ options: pdbToXmlOptions,
+ methodName: null);
+
+ using (logger.BeginScope("Rebuild Embedded Texts raw SHAs"))
+ {
+ var rebuildReader = new CompilationOptionsReader(logger, rebuildPdbReader, rebuildPeReader);
+ var rebuildSourceFileInfos = rebuildReader.GetSourceFileInfos(rebuildReader.GetEncoding());
+ foreach (var info in rebuildSourceFileInfos)
+ {
+ if (info.EmbeddedCompressedHash is { } hash)
+ {
+ var hashString = BitConverter.ToString(hash).Replace("-", "");
+ logger.LogInformation($@"""{info.SourceFilePath}"" - {hashString}");
+ }
+ }
+ }
}
}
@@ -163,11 +210,12 @@ public static unsafe CompilationDiff Create(
var ildasmRebuildOutputPath = Path.Combine(rebuildPath, assemblyName + ".il");
// TODO: can we bundle ildasm in with the utility?
- Process.Start(@"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\ildasm.exe", $@"{originalBinaryPath.FullName} /out={ildasmOriginalOutputPath}").WaitForExit();
- Process.Start(@"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\ildasm.exe", $@"{rebuildAssemblyPath} /out={ildasmRebuildOutputPath}").WaitForExit();
+ Process.Start(@"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\ildasm.exe", $@"{originalBinaryPath.FullName} /all /out={ildasmOriginalOutputPath}").WaitForExit();
+ Process.Start(@"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\ildasm.exe", $@"{rebuildAssemblyPath} /all /out={ildasmRebuildOutputPath}").WaitForExit();
File.WriteAllText(Path.Combine(assemblyDebugPath, "compare-pe.mdv.ps1"), $@"code --diff (Join-Path $PSScriptRoot ""{originalPeMdvPath.Substring(assemblyDebugPath.Length)}"") (Join-Path $PSScriptRoot ""{rebuildPeMdvPath.Substring(assemblyDebugPath.Length)}"")");
File.WriteAllText(Path.Combine(assemblyDebugPath, "compare-pdb.mdv.ps1"), $@"code --diff (Join-Path $PSScriptRoot ""{originalPdbMdvPath.Substring(assemblyDebugPath.Length)}"") (Join-Path $PSScriptRoot ""{rebuildPdbMdvPath.Substring(assemblyDebugPath.Length)}"")");
+ File.WriteAllText(Path.Combine(assemblyDebugPath, "compare-pdb.xml.ps1"), $@"code --diff (Join-Path $PSScriptRoot ""{originalPdbXmlPath.Substring(assemblyDebugPath.Length)}"") (Join-Path $PSScriptRoot ""{rebuildPdbXmlPath.Substring(assemblyDebugPath.Length)}"")");
File.WriteAllText(Path.Combine(assemblyDebugPath, "compare-il.ps1"), $@"code --diff (Join-Path $PSScriptRoot ""{ildasmOriginalOutputPath.Substring(assemblyDebugPath.Length)}"") (Join-Path $PSScriptRoot ""{ildasmRebuildOutputPath.Substring(assemblyDebugPath.Length)}"")");
}
}
diff --git a/src/Tools/BuildValidator/CompilationOptionsReader.cs b/src/Tools/BuildValidator/CompilationOptionsReader.cs
index 9b9cd0f14776e..0cdf44a87f7f1 100644
--- a/src/Tools/BuildValidator/CompilationOptionsReader.cs
+++ b/src/Tools/BuildValidator/CompilationOptionsReader.cs
@@ -27,17 +27,20 @@ internal readonly struct SourceFileInfo
internal SourceHashAlgorithm HashAlgorithm { get; }
internal byte[] Hash { get; }
internal SourceText? EmbeddedText { get; }
+ internal byte[]? EmbeddedCompressedHash { get; }
internal SourceFileInfo(
string sourceFilePath,
SourceHashAlgorithm hashAlgorithm,
byte[] hash,
- SourceText? embeddedText)
+ SourceText? embeddedText,
+ byte[]? embeddedCompressedHash)
{
SourceFilePath = sourceFilePath;
HashAlgorithm = hashAlgorithm;
Hash = hash;
EmbeddedText = embeddedText;
+ EmbeddedCompressedHash = embeddedCompressedHash;
}
}
@@ -192,7 +195,7 @@ public OutputKind GetOutputKind() =>
return (typeName, methodName);
}
- private SourceText? ResolveEmbeddedSource(DocumentHandle document, SourceHashAlgorithm hashAlgorithm, Encoding encoding)
+ private (SourceText? embeddedText, byte[]? compressedHash) ResolveEmbeddedSource(DocumentHandle document, SourceHashAlgorithm hashAlgorithm, Encoding encoding)
{
byte[] bytes = (from handle in PdbReader.GetCustomDebugInformation(document)
let cdi = PdbReader.GetCustomDebugInformation(handle)
@@ -201,14 +204,18 @@ where PdbReader.GetGuid(cdi.Kind) == EmbeddedSourceGuid
if (bytes == null)
{
- return null;
+ return default;
}
int uncompressedSize = BitConverter.ToInt32(bytes, 0);
var stream = new MemoryStream(bytes, sizeof(int), bytes.Length - sizeof(int));
+ byte[]? compressedHash = null;
if (uncompressedSize != 0)
{
+ using var algorithm = CryptographicHashProvider.TryGetAlgorithm(hashAlgorithm) ?? throw new InvalidOperationException();
+ compressedHash = algorithm.ComputeHash(bytes);
+
var decompressed = new MemoryStream(uncompressedSize);
using (var deflater = new DeflateStream(stream, CompressionMode.Decompress))
@@ -227,7 +234,8 @@ where PdbReader.GetGuid(cdi.Kind) == EmbeddedSourceGuid
using (stream)
{
// todo: IVT and EncodedStringText.Create?
- return SourceText.From(stream, encoding: encoding, checksumAlgorithm: hashAlgorithm, canBeEmbedded: true);
+ var embeddedText = SourceText.From(stream, encoding: encoding, checksumAlgorithm: hashAlgorithm, canBeEmbedded: true);
+ return (embeddedText, compressedHash);
}
}
@@ -293,7 +301,7 @@ public ImmutableArray GetSourceFileInfos(Encoding encoding)
var hash = PdbReader.GetBlobBytes(document.Hash);
var embeddedContent = ResolveEmbeddedSource(documentHandle, hashAlgorithm, encoding);
- builder.Add(new SourceFileInfo(name, hashAlgorithm, hash, embeddedContent));
+ builder.Add(new SourceFileInfo(name, hashAlgorithm, hash, embeddedContent.embeddedText, embeddedContent.compressedHash));
}
return builder.MoveToImmutable();
diff --git a/src/Tools/BuildValidator/LocalReferenceResolver.cs b/src/Tools/BuildValidator/LocalReferenceResolver.cs
index 72de32d852b86..242260162265a 100644
--- a/src/Tools/BuildValidator/LocalReferenceResolver.cs
+++ b/src/Tools/BuildValidator/LocalReferenceResolver.cs
@@ -30,11 +30,10 @@ internal class LocalReferenceResolver
public LocalReferenceResolver(Options options, ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger();
- foreach (var directoryInfo in GetRefAssembliesDirectories())
+ foreach (var path in options.AssembliesPaths)
{
- _indexDirectories.Add(directoryInfo);
+ _indexDirectories.Add(new DirectoryInfo(path));
}
- _indexDirectories.Add(new DirectoryInfo(options.AssembliesPath));
_indexDirectories.Add(GetNugetCacheDirectory());
foreach (var path in options.ReferencesPaths)
{
@@ -44,7 +43,7 @@ public LocalReferenceResolver(Options options, ILoggerFactory loggerFactory)
using var _ = _logger.BeginScope("Assembly Reference Search Paths");
foreach (var directory in _indexDirectories)
{
- _logger.LogInformation($@"""{directory}""");
+ _logger.LogInformation($@"""{directory.FullName}""");
}
}
@@ -59,16 +58,6 @@ public static DirectoryInfo GetNugetCacheDirectory()
return new DirectoryInfo(nugetPackageDirectory);
}
- public static DirectoryInfo[] GetRefAssembliesDirectories()
- {
- // TODO: Don't hardcode the paths here.
- return new[]
- {
- new DirectoryInfo(@"C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref"),
- new DirectoryInfo(@"C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref")
- };
- }
-
public string GetReferencePath(MetadataReferenceInfo referenceInfo)
{
if (_cache.TryGetValue(referenceInfo.Mvid, out var value))
diff --git a/src/Tools/BuildValidator/Options.cs b/src/Tools/BuildValidator/Options.cs
index b7a23f5e1c982..31f269ff34fc7 100644
--- a/src/Tools/BuildValidator/Options.cs
+++ b/src/Tools/BuildValidator/Options.cs
@@ -10,7 +10,7 @@
namespace BuildValidator
{
internal record Options(
- string AssembliesPath,
+ string[] AssembliesPaths,
string[] ReferencesPaths,
string SourcePath,
bool Verbose,
diff --git a/src/Tools/BuildValidator/Program.cs b/src/Tools/BuildValidator/Program.cs
index 941eea0f318b1..734921b08fc0a 100644
--- a/src/Tools/BuildValidator/Program.cs
+++ b/src/Tools/BuildValidator/Program.cs
@@ -43,14 +43,14 @@ static int Main(string[] args)
var rootCommand = new RootCommand
{
new Option(
- "--assembliesPath", "Path to assemblies to rebuild"
- ) { IsRequired = true },
+ "--assembliesPath", "Path to assemblies to rebuild (can be specified one or more times)"
+ ) { IsRequired = true, Argument = { Arity = ArgumentArity.OneOrMore } },
new Option(
"--sourcePath", "Path to sources to use in rebuild"
) { IsRequired = true },
- new Option(
- "--referencesPaths", "Additional paths to referenced assemblies"
- ),
+ new Option(
+ "--referencesPath", "Path to referenced assemblies (can be specified zero or more times)"
+ ) { Argument = { Arity = ArgumentArity.ZeroOrMore } },
new Option(
"--verbose", "Output verbose log information"
),
@@ -64,32 +64,30 @@ static int Main(string[] args)
"--debugPath", "Path to output debug info. Defaults to the user temp directory. Note that a unique debug path should be specified for every instance of the tool running with `--debug` enabled."
)
};
- rootCommand.Handler = CommandHandler.Create(HandleCommand);
+ rootCommand.Handler = CommandHandler.Create(HandleCommand);
return rootCommand.Invoke(args);
}
- static int HandleCommand(string assembliesPath, string sourcePath, string[]? referencesPaths, bool verbose, bool quiet, bool debug, string? debugPath)
+ static int HandleCommand(string[] assembliesPath, string sourcePath, string[]? referencesPath, bool verbose, bool quiet, bool debug, string? debugPath)
{
// If user provided a debug path then assume we should write debug outputs.
debug |= debugPath is object;
debugPath ??= Path.Combine(Path.GetTempPath(), $"BuildValidator");
- referencesPaths ??= Array.Empty();
+ referencesPath ??= Array.Empty();
- var options = new Options(assembliesPath, referencesPaths, sourcePath, verbose, quiet, debug, debugPath);
+ var options = new Options(assembliesPath, referencesPath, sourcePath, verbose, quiet, debug, debugPath);
- // TODO: remove the DemoLoggerProvider, update this dependency,
- // and move to the built in logger.
- var loggerFactory = new LoggerFactory(
- new[] { new ConsoleLoggerProvider(new ConsoleLoggerSettings()) },
- new LoggerFilterOptions()
+ // TODO: remove the DemoLoggerProvider or convert it to something more permanent
+ var loggerFactory = LoggerFactory.Create(builder =>
+ {
+ builder.SetMinimumLevel((options.Verbose, options.Quiet) switch
{
- MinLevel = options.Verbose ? LogLevel.Trace : LogLevel.Information
+ (_, true) => LogLevel.Error,
+ (true, _) => LogLevel.Trace,
+ _ => LogLevel.Information
});
-
- if (!options.Quiet)
- {
- loggerFactory.AddProvider(new DemoLoggerProvider());
- }
+ builder.AddProvider(new DemoLoggerProvider());
+ });
var logger = loggerFactory.CreateLogger();
try
@@ -111,10 +109,11 @@ static int HandleCommand(string assembliesPath, string sourcePath, string[]? ref
var buildConstructor = new BuildConstructor(referenceResolver, sourceResolver, logger);
- var artifactsDir = new DirectoryInfo(options.AssembliesPath);
+ var artifactsDirs = options.AssembliesPaths.Select(path => new DirectoryInfo(path));
- var filesToValidate = artifactsDir.EnumerateFiles("*.exe", SearchOption.AllDirectories)
- .Concat(artifactsDir.EnumerateFiles("*.dll", SearchOption.AllDirectories))
+ var filesToValidate = artifactsDirs.SelectMany(dir =>
+ dir.EnumerateFiles("*.exe", SearchOption.AllDirectories)
+ .Concat(dir.EnumerateFiles("*.dll", SearchOption.AllDirectories)))
.Distinct(FileNameEqualityComparer.Instance);
var success = ValidateFiles(filesToValidate, buildConstructor, logger, options);
@@ -213,7 +212,7 @@ private static bool ValidateFiles(IEnumerable originalBinaries, BuildC
var compilation = buildConstructor.CreateCompilation(
optionsReader,
- Path.GetFileNameWithoutExtension(originalBinary.Name));
+ originalBinary.Name);
var compilationDiff = CompilationDiff.Create(originalBinary, optionsReader, compilation, getDebugEntryPoint(), logger, options);
return compilationDiff;
diff --git a/src/Tools/ManifestGenerator/README.md b/src/Tools/ManifestGenerator/README.md
index ef0eaaf06037e..d796d86bfb342 100644
--- a/src/Tools/ManifestGenerator/README.md
+++ b/src/Tools/ManifestGenerator/README.md
@@ -1,4 +1,3 @@
# dotnet-roslyn-manifest-generator
-https://github.com/dotnet/roslyn/blob/efd69176d6ad7f9dbe1d87525201760a6c44e7a0/docs/compilers/terrapin.md#artifacts-manifest-file
-
+[Terrapin doc](../../../docs/compilers/terrapin.md#artifacts-manifest-file)
diff --git a/src/VisualStudio/CSharp/Test/PersistentStorage/AbstractPersistentStorageTests.cs b/src/VisualStudio/CSharp/Test/PersistentStorage/AbstractPersistentStorageTests.cs
index c7528173a19b1..4c54f7cca1358 100644
--- a/src/VisualStudio/CSharp/Test/PersistentStorage/AbstractPersistentStorageTests.cs
+++ b/src/VisualStudio/CSharp/Test/PersistentStorage/AbstractPersistentStorageTests.cs
@@ -100,7 +100,7 @@ public async Task TestNullFilePaths()
var streamName = "stream";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
var project = solution.Projects.First();
var document = project.Documents.First();
Assert.False(await storage.WriteStreamAsync(project, streamName, EncodeString("")));
@@ -118,13 +118,13 @@ public async Task PersistentService_Solution_WriteReadDifferentInstances(Size si
var streamName1 = "PersistentService_Solution_WriteReadDifferentInstances1";
var streamName2 = "PersistentService_Solution_WriteReadDifferentInstances2";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(size)), GetChecksum1(withChecksum)));
Assert.True(await storage.WriteStreamAsync(streamName2, EncodeString(GetData2(size)), GetChecksum2(withChecksum)));
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.Equal(GetData1(size), ReadStringToEnd(await storage.ReadStreamAsync(streamName1, GetChecksum1(withChecksum))));
Assert.Equal(GetData2(size), ReadStringToEnd(await storage.ReadStreamAsync(streamName2, GetChecksum2(withChecksum))));
@@ -139,7 +139,7 @@ public async Task PersistentService_Solution_WriteReadReopenSolution(Size size,
var streamName1 = "PersistentService_Solution_WriteReadReopenSolution1";
var streamName2 = "PersistentService_Solution_WriteReadReopenSolution2";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(size)), GetChecksum1(withChecksum)));
Assert.True(await storage.WriteStreamAsync(streamName2, EncodeString(GetData2(size)), GetChecksum2(withChecksum)));
@@ -147,7 +147,7 @@ public async Task PersistentService_Solution_WriteReadReopenSolution(Size size,
solution = CreateOrOpenSolution();
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.Equal(GetData1(size), ReadStringToEnd(await storage.ReadStreamAsync(streamName1, GetChecksum1(withChecksum))));
Assert.Equal(GetData2(size), ReadStringToEnd(await storage.ReadStreamAsync(streamName2, GetChecksum2(withChecksum))));
@@ -162,7 +162,7 @@ public async Task PersistentService_Solution_WriteReadSameInstance(Size size, bo
var streamName1 = "PersistentService_Solution_WriteReadSameInstance1";
var streamName2 = "PersistentService_Solution_WriteReadSameInstance2";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(size)), GetChecksum1(withChecksum)));
Assert.True(await storage.WriteStreamAsync(streamName2, EncodeString(GetData2(size)), GetChecksum2(withChecksum)));
@@ -178,7 +178,7 @@ public async Task PersistentService_Project_WriteReadSameInstance(Size size, boo
var streamName1 = "PersistentService_Project_WriteReadSameInstance1";
var streamName2 = "PersistentService_Project_WriteReadSameInstance2";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
var project = solution.Projects.Single();
Assert.True(await storage.WriteStreamAsync(project, streamName1, EncodeString(GetData1(size)), GetChecksum1(withChecksum)));
@@ -196,7 +196,7 @@ public async Task PersistentService_Document_WriteReadSameInstance(Size size, bo
var streamName1 = "PersistentService_Document_WriteReadSameInstance1";
var streamName2 = "PersistentService_Document_WriteReadSameInstance2";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
var document = solution.Projects.Single().Documents.Single();
Assert.True(await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(size)), GetChecksum1(withChecksum)));
@@ -213,7 +213,7 @@ public async Task PersistentService_Solution_SimultaneousWrites()
var streamName1 = "PersistentService_Solution_SimultaneousWrites1";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
DoSimultaneousWrites(s => storage.WriteStreamAsync(streamName1, EncodeString(s)));
var value = int.Parse(ReadStringToEnd(await storage.ReadStreamAsync(streamName1)));
Assert.True(value >= 0);
@@ -227,7 +227,7 @@ public async Task PersistentService_Project_SimultaneousWrites()
var streamName1 = "PersistentService_Project_SimultaneousWrites1";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
DoSimultaneousWrites(s => storage.WriteStreamAsync(solution.Projects.Single(), streamName1, EncodeString(s)));
var value = int.Parse(ReadStringToEnd(await storage.ReadStreamAsync(solution.Projects.Single(), streamName1)));
Assert.True(value >= 0);
@@ -241,7 +241,7 @@ public async Task PersistentService_Document_SimultaneousWrites()
var streamName1 = "PersistentService_Document_SimultaneousWrites1";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
DoSimultaneousWrites(s => storage.WriteStreamAsync(solution.Projects.Single().Documents.Single(), streamName1, EncodeString(s)));
var value = int.Parse(ReadStringToEnd(await storage.ReadStreamAsync(solution.Projects.Single().Documents.Single(), streamName1)));
Assert.True(value >= 0);
@@ -273,7 +273,7 @@ public async Task PersistentService_Solution_SimultaneousReads(Size size, bool w
var solution = CreateOrOpenSolution();
var streamName1 = "PersistentService_Solution_SimultaneousReads1";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(size)), GetChecksum1(withChecksum)));
DoSimultaneousReads(async () => ReadStringToEnd(await storage.ReadStreamAsync(streamName1, GetChecksum1(withChecksum))), GetData1(size));
}
@@ -285,7 +285,7 @@ public async Task PersistentService_Project_SimultaneousReads(Size size, bool wi
var solution = CreateOrOpenSolution();
var streamName1 = "PersistentService_Project_SimultaneousReads1";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
Assert.True(await storage.WriteStreamAsync(solution.Projects.Single(), streamName1, EncodeString(GetData1(size)), GetChecksum1(withChecksum)));
DoSimultaneousReads(async () => ReadStringToEnd(await storage.ReadStreamAsync(solution.Projects.Single(), streamName1, GetChecksum1(withChecksum))), GetData1(size));
}
@@ -299,7 +299,7 @@ public async Task PersistentService_Document_SimultaneousReads(Size size, bool w
var solution = CreateOrOpenSolution();
var streamName1 = "PersistentService_Document_SimultaneousReads1";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
Assert.True(await storage.WriteStreamAsync(solution.Projects.Single().Documents.Single(), streamName1, EncodeString(GetData1(size)), GetChecksum1(withChecksum)));
DoSimultaneousReads(async () => ReadStringToEnd(await storage.ReadStreamAsync(solution.Projects.Single().Documents.Single(), streamName1, GetChecksum1(withChecksum))), GetData1(size));
}
@@ -311,7 +311,7 @@ public async Task TestReadChecksumReturnsNullWhenNeverWritten()
var streamName1 = "TestReadChecksumReturnsNullWhenNeverWritten";
- using var storage = await GetStorageAsync(solution);
+ await using var storage = await GetStorageAsync(solution);
Assert.False(await storage.ChecksumMatchesAsync(streamName1, s_checksum1));
}
@@ -322,12 +322,12 @@ public async Task TestCanReadWithNullChecksumSomethingWrittenWithNonNullChecksum
var streamName1 = "TestCanReadWithNullChecksumSomethingWrittenWithNonNullChecksum";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(Size.Small)), s_checksum1));
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(streamName1, checksum: null)));
}
@@ -340,12 +340,12 @@ public async Task TestCannotReadWithMismatchedChecksums()
var streamName1 = "TestCannotReadWithMismatchedChecksums";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(Size.Small)), s_checksum1));
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.Null(await storage.ReadStreamAsync(streamName1, s_checksum2));
}
@@ -358,12 +358,12 @@ public async Task TestCannotReadChecksumIfWriteDidNotIncludeChecksum()
var streamName1 = "TestCannotReadChecksumIfWriteDidNotIncludeChecksum";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(Size.Small)), checksum: null));
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.False(await storage.ChecksumMatchesAsync(streamName1, s_checksum1));
}
@@ -376,12 +376,12 @@ public async Task TestReadChecksumProducesWrittenChecksum()
var streamName1 = "TestReadChecksumProducesWrittenChecksum";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1));
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(streamName1, s_checksum1));
}
@@ -394,13 +394,13 @@ public async Task TestReadChecksumProducesLastWrittenChecksum1()
var streamName1 = "TestReadChecksumProducesLastWrittenChecksum1";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1));
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(Size.Small)), checksum: null));
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.False(await storage.ChecksumMatchesAsync(streamName1, s_checksum1));
}
@@ -413,13 +413,13 @@ public async Task TestReadChecksumProducesLastWrittenChecksum2()
var streamName1 = "TestReadChecksumProducesLastWrittenChecksum2";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(Size.Small)), checksum: null));
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1));
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(streamName1, s_checksum1));
}
@@ -432,13 +432,13 @@ public async Task TestReadChecksumProducesLastWrittenChecksum3()
var streamName1 = "TestReadChecksumProducesLastWrittenChecksum3";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1));
Assert.True(await storage.WriteStreamAsync(streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum2));
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(streamName1, s_checksum2));
}
@@ -452,12 +452,12 @@ public async Task TestOpenWithSolutionKeyReadWithDocumentKey()
var streamName1 = "stream";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
Assert.True(await storage.ChecksumMatchesAsync(DocumentKey.ToDocumentKey(document), streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(DocumentKey.ToDocumentKey(document), streamName1)));
@@ -472,12 +472,12 @@ public async Task TestOpenWithSolutionKeyReadWithDocument()
var streamName1 = "stream";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
Assert.True(await storage.ChecksumMatchesAsync(document, streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(document, streamName1)));
@@ -492,12 +492,12 @@ public async Task TestOpenWithSolutionReadWithDocumentKey()
var streamName1 = "stream";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(DocumentKey.ToDocumentKey(document), streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(DocumentKey.ToDocumentKey(document), streamName1)));
@@ -512,12 +512,12 @@ public async Task TestOpenWithSolutionReadWithDocument()
var streamName1 = "stream";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(document, streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(document, streamName1)));
@@ -532,12 +532,12 @@ public async Task TestOpenWithSolutionReadWithDocumentKeyAndDocument1()
var streamName1 = "stream";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(DocumentKey.ToDocumentKey(document), streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(DocumentKey.ToDocumentKey(document), streamName1)));
@@ -555,12 +555,12 @@ public async Task TestOpenWithSolutionReadWithDocumentKeyAndDocument2()
var streamName1 = "stream";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(document, streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(document, streamName1)));
@@ -578,12 +578,12 @@ public async Task TestOpenWithSolutionKeyReadWithDocumentKeyAndDocument1()
var streamName1 = "stream";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
Assert.True(await storage.ChecksumMatchesAsync(DocumentKey.ToDocumentKey(document), streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(DocumentKey.ToDocumentKey(document), streamName1)));
@@ -601,12 +601,12 @@ public async Task TestOpenWithSolutionKeyReadWithDocumentKeyAndDocument2()
var streamName1 = "stream";
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
Assert.True(await storage.ChecksumMatchesAsync(document, streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(document, streamName1)));
@@ -624,12 +624,12 @@ public async Task TestOpenWithSolutionKeyReadWithDocumentKey_WriteWithSolutionKe
var streamName1 = "stream";
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
Assert.True(await storage.ChecksumMatchesAsync(DocumentKey.ToDocumentKey(document), streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(DocumentKey.ToDocumentKey(document), streamName1)));
@@ -644,12 +644,12 @@ public async Task TestOpenWithSolutionKeyReadWithDocument_WriteWithSolutionKey()
var streamName1 = "stream";
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
Assert.True(await storage.ChecksumMatchesAsync(document, streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(document, streamName1)));
@@ -664,12 +664,12 @@ public async Task TestOpenWithSolutionReadWithDocumentKey_WriteWithSolutionKey()
var streamName1 = "stream";
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(DocumentKey.ToDocumentKey(document), streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(DocumentKey.ToDocumentKey(document), streamName1)));
@@ -684,12 +684,12 @@ public async Task TestOpenWithSolutionReadWithDocument_WriteWithSolutionKey()
var streamName1 = "stream";
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(document, streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(document, streamName1)));
@@ -704,12 +704,12 @@ public async Task TestOpenWithSolutionReadWithDocumentKeyAndDocument1_WriteWithS
var streamName1 = "stream";
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(DocumentKey.ToDocumentKey(document), streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(DocumentKey.ToDocumentKey(document), streamName1)));
@@ -727,12 +727,12 @@ public async Task TestOpenWithSolutionReadWithDocumentKeyAndDocument2_WriteWithS
var streamName1 = "stream";
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageAsync(solution))
+ await using (var storage = await GetStorageAsync(solution))
{
Assert.True(await storage.ChecksumMatchesAsync(document, streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(document, streamName1)));
@@ -750,12 +750,12 @@ public async Task TestOpenWithSolutionKeyReadWithDocumentKeyAndDocument1_WriteWi
var streamName1 = "stream";
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
Assert.True(await storage.ChecksumMatchesAsync(DocumentKey.ToDocumentKey(document), streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(DocumentKey.ToDocumentKey(document), streamName1)));
@@ -773,12 +773,12 @@ public async Task TestOpenWithSolutionKeyReadWithDocumentKeyAndDocument2_WriteWi
var streamName1 = "stream";
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
await storage.WriteStreamAsync(document, streamName1, EncodeString(GetData1(Size.Small)), checksum: s_checksum1);
}
- using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
+ await using (var storage = await GetStorageFromKeyAsync(solution.Workspace, SolutionKey.ToSolutionKey(solution)))
{
Assert.True(await storage.ChecksumMatchesAsync(document, streamName1, s_checksum1));
Assert.Equal(GetData1(Size.Small), ReadStringToEnd(await storage.ReadStreamAsync(document, streamName1)));
diff --git a/src/VisualStudio/CSharp/Test/PersistentStorage/SQLiteV2PersistentStorageTests.cs b/src/VisualStudio/CSharp/Test/PersistentStorage/SQLiteV2PersistentStorageTests.cs
index 5bb184aa6c720..f05948bfd630a 100644
--- a/src/VisualStudio/CSharp/Test/PersistentStorage/SQLiteV2PersistentStorageTests.cs
+++ b/src/VisualStudio/CSharp/Test/PersistentStorage/SQLiteV2PersistentStorageTests.cs
@@ -40,7 +40,7 @@ public async Task TestCrashInNewConnection()
// Because instantiating the connection will fail, we will not get back
// a working persistent storage.
- using (var storage = await GetStorageAsync(solution, faultInjector))
+ await using (var storage = await GetStorageAsync(solution, faultInjector))
using (var memStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memStream))
{
diff --git a/src/Workspaces/Core/Portable/Diagnostics/DiagnosticDataSerializer.cs b/src/Workspaces/Core/Portable/Diagnostics/DiagnosticDataSerializer.cs
index 084d2450d05f4..4b9026b29ed95 100644
--- a/src/Workspaces/Core/Portable/Diagnostics/DiagnosticDataSerializer.cs
+++ b/src/Workspaces/Core/Portable/Diagnostics/DiagnosticDataSerializer.cs
@@ -49,7 +49,8 @@ public async Task SerializeAsync(IPersistentStorageService persistentServi
WriteDiagnosticData(writer, items, cancellationToken);
}
- using var storage = await persistentService.GetStorageAsync(project.Solution, cancellationToken).ConfigureAwait(false);
+ var storage = await persistentService.GetStorageAsync(project.Solution, cancellationToken).ConfigureAwait(false);
+ await using var _ = storage.ConfigureAwait(false);
stream.Position = 0;
@@ -69,7 +70,8 @@ public async ValueTask> DeserializeAsync(IPersist
{
Contract.ThrowIfFalse(textDocument == null || textDocument.Project == project);
- using var storage = await persistentService.GetStorageAsync(project.Solution, cancellationToken).ConfigureAwait(false);
+ var storage = await persistentService.GetStorageAsync(project.Solution, cancellationToken).ConfigureAwait(false);
+ await using var _ = storage.ConfigureAwait(false);
var readTask = (textDocument != null) ?
textDocument is Document document ?
diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Serialization.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Serialization.cs
index 197b4473abff6..08f90282d197d 100644
--- a/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Serialization.cs
+++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Serialization.cs
@@ -70,55 +70,54 @@ private static async Task TryLoadOrCreateAsync(
// Ok, we can use persistence. First try to load from the persistence service.
var persistentStorageService = (IChecksummedPersistentStorageService)solution.Workspace.Services.GetService();
- T result;
- using (var storage = await persistentStorageService.GetStorageAsync(solution, checkBranchId: false, cancellationToken).ConfigureAwait(false))
+ var storage = await persistentStorageService.GetStorageAsync(solution, checkBranchId: false, cancellationToken).ConfigureAwait(false);
+ await using var _ = storage.ConfigureAwait(false);
+
+ // Get the unique key to identify our data.
+ var key = PrefixMetadataSymbolTreeInfo + keySuffix;
+ using (var stream = await storage.ReadStreamAsync(key, checksum, cancellationToken).ConfigureAwait(false))
+ using (var reader = ObjectReader.TryGetReader(stream, cancellationToken: cancellationToken))
{
- // Get the unique key to identify our data.
- var key = PrefixMetadataSymbolTreeInfo + keySuffix;
- using (var stream = await storage.ReadStreamAsync(key, checksum, cancellationToken).ConfigureAwait(false))
- using (var reader = ObjectReader.TryGetReader(stream, cancellationToken: cancellationToken))
+ if (reader != null)
{
- if (reader != null)
+ // We have some previously persisted data. Attempt to read it back.
+ // If we're able to, and the version of the persisted data matches
+ // our version, then we can reuse this instance.
+ var read = tryReadObject(reader);
+ if (read != null)
{
- // We have some previously persisted data. Attempt to read it back.
- // If we're able to, and the version of the persisted data matches
- // our version, then we can reuse this instance.
- result = tryReadObject(reader);
- if (result != null)
- {
- // If we were able to read something in, it's checksum better
- // have matched the checksum we expected.
- Debug.Assert(result.Checksum == checksum);
- return result;
- }
+ // If we were able to read something in, it's checksum better
+ // have matched the checksum we expected.
+ Debug.Assert(read.Checksum == checksum);
+ return read;
}
}
+ }
- cancellationToken.ThrowIfCancellationRequested();
+ cancellationToken.ThrowIfCancellationRequested();
- // Couldn't read from the persistence service. If we've been asked to only load
- // data and not create new instances in their absence, then there's nothing left
- // to do at this point.
- if (loadOnly)
- {
- return null;
- }
+ // Couldn't read from the persistence service. If we've been asked to only load
+ // data and not create new instances in their absence, then there's nothing left
+ // to do at this point.
+ if (loadOnly)
+ {
+ return null;
+ }
- // Now, try to create a new instance and write it to the persistence service.
- result = await CreateWithLoggingAsync().ConfigureAwait(false);
- Contract.ThrowIfNull(result);
+ // Now, try to create a new instance and write it to the persistence service.
+ var result = await CreateWithLoggingAsync().ConfigureAwait(false);
+ Contract.ThrowIfNull(result);
- using (var stream = SerializableBytes.CreateWritableStream())
+ using (var stream = SerializableBytes.CreateWritableStream())
+ {
+ using (var writer = new ObjectWriter(stream, leaveOpen: true, cancellationToken))
{
- using (var writer = new ObjectWriter(stream, leaveOpen: true, cancellationToken))
- {
- result.WriteTo(writer);
- }
+ result.WriteTo(writer);
+ }
- stream.Position = 0;
+ stream.Position = 0;
- await storage.WriteStreamAsync(key, stream, checksum, cancellationToken).ConfigureAwait(false);
- }
+ await storage.WriteStreamAsync(key, stream, checksum, cancellationToken).ConfigureAwait(false);
}
return result;
diff --git a/src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Persistence.cs b/src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Persistence.cs
index 73e570290fb4b..518e4a3cdeb7f 100644
--- a/src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Persistence.cs
+++ b/src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Persistence.cs
@@ -28,7 +28,8 @@ internal sealed partial class SyntaxTreeIndex : IObjectWritable
try
{
// attempt to load from persisted state
- using var storage = await persistentStorageService.GetStorageAsync(solution, checkBranchId: false, cancellationToken).ConfigureAwait(false);
+ var storage = await persistentStorageService.GetStorageAsync(solution, checkBranchId: false, cancellationToken).ConfigureAwait(false);
+ await using var _ = storage.ConfigureAwait(false);
using var stream = await storage.ReadStreamAsync(document, PersistenceName, checksum, cancellationToken).ConfigureAwait(false);
using var reader = ObjectReader.TryGetReader(stream, cancellationToken: cancellationToken);
if (reader != null)
@@ -71,7 +72,8 @@ private async Task SaveAsync(
try
{
- using var storage = await persistentStorageService.GetStorageAsync(solution, checkBranchId: false, cancellationToken).ConfigureAwait(false);
+ var storage = await persistentStorageService.GetStorageAsync(solution, checkBranchId: false, cancellationToken).ConfigureAwait(false);
+ await using var _ = storage.ConfigureAwait(false);
using var stream = SerializableBytes.CreateWritableStream();
using (var writer = new ObjectWriter(stream, leaveOpen: true, cancellationToken))
@@ -99,7 +101,8 @@ private static async Task PrecalculatedAsync(
// check whether we already have info for this document
try
{
- using var storage = await persistentStorageService.GetStorageAsync(solution, checkBranchId: false, cancellationToken).ConfigureAwait(false);
+ var storage = await persistentStorageService.GetStorageAsync(solution, checkBranchId: false, cancellationToken).ConfigureAwait(false);
+ await using var _ = storage.ConfigureAwait(false);
// Check if we've already stored a checksum and it matches the checksum we
// expect. If so, we're already precalculated and don't have to recompute
// this index. Otherwise if we don't have a checksum, or the checksums don't
diff --git a/src/Workspaces/Core/Portable/Storage/AbstractPersistentStorageService.cs b/src/Workspaces/Core/Portable/Storage/AbstractPersistentStorageService.cs
index b91d57fe0e641..21743014759f0 100644
--- a/src/Workspaces/Core/Portable/Storage/AbstractPersistentStorageService.cs
+++ b/src/Workspaces/Core/Portable/Storage/AbstractPersistentStorageService.cs
@@ -234,6 +234,9 @@ public static IChecksummedPersistentStorage AddReferenceCountToAndCreateWrapper(
public void Dispose()
=> _storage.Dispose();
+ public ValueTask DisposeAsync()
+ => _storage.DisposeAsync();
+
public Task ChecksumMatchesAsync(string name, Checksum checksum, CancellationToken cancellationToken)
=> _storage.Target.ChecksumMatchesAsync(name, checksum, cancellationToken);
@@ -249,13 +252,13 @@ public Task ChecksumMatchesAsync(ProjectKey project, string name, Checksum
public Task ChecksumMatchesAsync(DocumentKey document, string name, Checksum checksum, CancellationToken cancellationToken)
=> _storage.Target.ChecksumMatchesAsync(document, name, checksum, cancellationToken);
- public Task ReadStreamAsync(string name, CancellationToken cancellationToken)
+ public Task ReadStreamAsync(string name, CancellationToken cancellationToken)
=> _storage.Target.ReadStreamAsync(name, cancellationToken);
- public Task ReadStreamAsync(Project project, string name, CancellationToken cancellationToken)
+ public Task ReadStreamAsync(Project project, string name, CancellationToken cancellationToken)
=> _storage.Target.ReadStreamAsync(project, name, cancellationToken);
- public Task ReadStreamAsync(Document document, string name, CancellationToken cancellationToken)
+ public Task ReadStreamAsync(Document document, string name, CancellationToken cancellationToken)
=> _storage.Target.ReadStreamAsync(document, name, cancellationToken);
public Task ReadStreamAsync(string name, Checksum checksum, CancellationToken cancellationToken)
diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/v2/SQLitePersistentStorage.cs b/src/Workspaces/Core/Portable/Storage/SQLite/v2/SQLitePersistentStorage.cs
index 85c0e7dbef7e8..418b29c4b8240 100644
--- a/src/Workspaces/Core/Portable/Storage/SQLite/v2/SQLitePersistentStorage.cs
+++ b/src/Workspaces/Core/Portable/Storage/SQLite/v2/SQLitePersistentStorage.cs
@@ -88,6 +88,12 @@ private SQLitePersistentStorage(
}
public override void Dispose()
+ {
+ var task = DisposeAsync().AsTask();
+ task.Wait();
+ }
+
+ public override async ValueTask DisposeAsync()
{
try
{
@@ -95,7 +101,7 @@ public override void Dispose()
// persisted to the DB.
try
{
- FlushWritesOnClose();
+ await FlushWritesOnCloseAsync().ConfigureAwait(false);
}
catch (Exception e)
{
diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/v2/SQLitePersistentStorage_FlushWrites.cs b/src/Workspaces/Core/Portable/Storage/SQLite/v2/SQLitePersistentStorage_FlushWrites.cs
index 58f3a7ee276e3..7bb665bd52a99 100644
--- a/src/Workspaces/Core/Portable/Storage/SQLite/v2/SQLitePersistentStorage_FlushWrites.cs
+++ b/src/Workspaces/Core/Portable/Storage/SQLite/v2/SQLitePersistentStorage_FlushWrites.cs
@@ -31,13 +31,13 @@ private Task FlushInMemoryDataToDiskIfNotShutdownAsync(CancellationToken cancell
return PerformWriteAsync(FlushInMemoryDataToDisk, cancellationToken);
}
- private void FlushWritesOnClose()
+ private Task FlushWritesOnCloseAsync()
{
// Issue a write task to write this all out to disk.
//
// Note: this only happens on close, so we don't try to avoid allocations here.
- var writeTask = PerformWriteAsync(
+ return PerformWriteAsync(
() =>
{
// Perform the actual write while having exclusive access to the scheduler.
@@ -59,9 +59,6 @@ private void FlushWritesOnClose()
// read/write after releasing us.
_shutdownTokenSource.Cancel();
}, CancellationToken.None);
-
- // Wait for that task to finish.
- writeTask.Wait();
}
private void FlushInMemoryDataToDisk()
diff --git a/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/AbstractPersistentStorage.cs b/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/AbstractPersistentStorage.cs
index 4fc5a526d715e..8fe74c72239b2 100644
--- a/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/AbstractPersistentStorage.cs
+++ b/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/AbstractPersistentStorage.cs
@@ -35,6 +35,7 @@ protected AbstractPersistentStorage(
}
public abstract void Dispose();
+ public abstract ValueTask DisposeAsync();
public abstract Task ChecksumMatchesAsync(string name, Checksum checksum, CancellationToken cancellationToken);
public abstract Task ReadStreamAsync(string name, Checksum? checksum, CancellationToken cancellationToken);
diff --git a/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/IPersistentStorage.cs b/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/IPersistentStorage.cs
index 0c33811f395a5..c15c8d1601937 100644
--- a/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/IPersistentStorage.cs
+++ b/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/IPersistentStorage.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#nullable disable
-
using System;
using System.IO;
using System.Threading;
@@ -11,12 +9,16 @@
namespace Microsoft.CodeAnalysis.Host
{
- public interface IPersistentStorage : IDisposable
+ ///
+ /// Instances of support both synchronous and asynchronous disposal. Asynchronous
+ /// disposal should always be preferred as the implementation of synchronous disposal may end up blocking the caller
+ /// on async work.
+ ///
+ public interface IPersistentStorage : IDisposable, IAsyncDisposable
{
- Task ReadStreamAsync(string name, CancellationToken cancellationToken = default);
-
- Task ReadStreamAsync(Project project, string name, CancellationToken cancellationToken = default);
- Task ReadStreamAsync(Document document, string name, CancellationToken cancellationToken = default);
+ Task ReadStreamAsync(string name, CancellationToken cancellationToken = default);
+ Task ReadStreamAsync(Project project, string name, CancellationToken cancellationToken = default);
+ Task ReadStreamAsync(Document document, string name, CancellationToken cancellationToken = default);
Task WriteStreamAsync(string name, Stream stream, CancellationToken cancellationToken = default);
Task WriteStreamAsync(Project project, string name, Stream stream, CancellationToken cancellationToken = default);
diff --git a/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/NoOpPersistentStorage.cs b/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/NoOpPersistentStorage.cs
index 030716cb1406c..d2bf20ad513a6 100644
--- a/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/NoOpPersistentStorage.cs
+++ b/src/Workspaces/Core/Portable/Workspace/Host/PersistentStorage/NoOpPersistentStorage.cs
@@ -22,6 +22,11 @@ public void Dispose()
{
}
+ public ValueTask DisposeAsync()
+ {
+ return ValueTaskFactory.CompletedTask;
+ }
+
public Task ChecksumMatchesAsync(string name, Checksum checksum, CancellationToken cancellationToken)
=> SpecializedTasks.False;
diff --git a/src/Workspaces/Core/Portable/Workspace/TextExtensions.cs b/src/Workspaces/Core/Portable/Workspace/TextExtensions.cs
index 2c18b2b54f6a4..5b017c4bdf750 100644
--- a/src/Workspaces/Core/Portable/Workspace/TextExtensions.cs
+++ b/src/Workspaces/Core/Portable/Workspace/TextExtensions.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
+using System.Threading;
using Microsoft.CodeAnalysis.Shared.Extensions;
namespace Microsoft.CodeAnalysis.Text
@@ -92,5 +93,18 @@ public static ImmutableArray GetRelatedDocuments(this SourceTextContai
return null;
}
+
+ ///
+ /// Tries to get the document corresponding to the text from the current partial solution
+ /// associated with the text's container. If the document does not contain the exact text a document
+ /// from a new solution containing the specified text is constructed. If no document is associated
+ /// with the specified text's container, or the text's container isn't associated with a workspace,
+ /// then the method returns false.
+ ///
+ internal static Document? GetDocumentWithFrozenPartialSemantics(this SourceText text, CancellationToken cancellationToken)
+ {
+ var document = text.GetOpenDocumentInCurrentContextWithChanges();
+ return document?.WithFrozenPartialSemantics(cancellationToken);
+ }
}
}
diff --git a/src/Workspaces/Remote/ServiceHub/Services/SemanticClassificationCache/RemoteSemanticClassificationCacheService.cs b/src/Workspaces/Remote/ServiceHub/Services/SemanticClassificationCache/RemoteSemanticClassificationCacheService.cs
index 55d905ebd223d..8ceebb90a08b1 100644
--- a/src/Workspaces/Remote/ServiceHub/Services/SemanticClassificationCache/RemoteSemanticClassificationCacheService.cs
+++ b/src/Workspaces/Remote/ServiceHub/Services/SemanticClassificationCache/RemoteSemanticClassificationCacheService.cs
@@ -94,7 +94,8 @@ private static async Task CacheSemanticClassificationsAsync(Document document, C
if (persistenceService == null)
return;
- using var storage = await persistenceService.GetStorageAsync(solution, cancellationToken).ConfigureAwait(false);
+ var storage = await persistenceService.GetStorageAsync(solution, cancellationToken).ConfigureAwait(false);
+ await using var _ = storage.ConfigureAwait(false);
if (storage == null)
return;
@@ -264,7 +265,8 @@ private async Task> TryReadCachedSemanticClassifi
if (persistenceService == null)
return default;
- using var storage = await persistenceService.GetStorageAsync(workspace, documentKey.Project.Solution, checkBranchId: false, cancellationToken).ConfigureAwait(false);
+ var storage = await persistenceService.GetStorageAsync(workspace, documentKey.Project.Solution, checkBranchId: false, cancellationToken).ConfigureAwait(false);
+ await using var _ = storage.ConfigureAwait(false);
if (storage == null)
return default;
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/IReferenceCountedDisposable.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/IReferenceCountedDisposable.cs
index 953989d8e950b..16c85b3680415 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/IReferenceCountedDisposable.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/IReferenceCountedDisposable.cs
@@ -13,6 +13,9 @@ namespace Roslyn.Utilities
///
///
internal interface IReferenceCountedDisposable : IDisposable
+#if !CODE_STYLE
+ , IAsyncDisposable
+#endif
where T : class
{
///
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ReferenceCountedDisposable.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ReferenceCountedDisposable.cs
index 3f950b1f7484f..ccc27196b760c 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ReferenceCountedDisposable.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ReferenceCountedDisposable.cs
@@ -4,6 +4,8 @@
using System;
using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
namespace Roslyn.Utilities
{
@@ -173,6 +175,27 @@ private ReferenceCountedDisposable(T instance, StrongBox referenceCount)
/// use.
///
public void Dispose()
+ {
+ var instanceToDispose = DisposeImpl();
+ instanceToDispose?.Dispose();
+ }
+
+ public ValueTask DisposeAsync()
+ {
+ var instanceToDispose = DisposeImpl();
+ if (instanceToDispose == null)
+ return ValueTaskFactory.CompletedTask;
+
+#if !CODE_STYLE
+ if (instanceToDispose is IAsyncDisposable asyncDisposable)
+ return asyncDisposable.DisposeAsync();
+#endif
+
+ instanceToDispose.Dispose();
+ return ValueTaskFactory.CompletedTask;
+ }
+
+ private T? DisposeImpl()
{
T? instanceToDispose = null;
lock (_boxedReferenceCount)
@@ -180,7 +203,7 @@ public void Dispose()
if (_instance == null)
{
// Already disposed; allow multiple without error.
- return;
+ return null;
}
_boxedReferenceCount.Value--;
@@ -193,7 +216,7 @@ public void Dispose()
_instance = null;
}
- instanceToDispose?.Dispose();
+ return instanceToDispose;
}
///
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ReferenceCountedDisposableCache.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ReferenceCountedDisposableCache.cs
index 87fcdf4704255..cd86b1d66a3e5 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ReferenceCountedDisposableCache.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ReferenceCountedDisposableCache.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace Roslyn.Utilities
{
@@ -15,8 +16,7 @@ namespace Roslyn.Utilities
internal sealed class ReferenceCountedDisposableCache where TValue : class, IDisposable
where TKey : notnull
{
- private readonly Dictionary.WeakReference> _cache =
- new();
+ private readonly Dictionary.WeakReference> _cache = new();
private readonly object _gate = new();
public IReferenceCountedDisposable> GetOrCreate(TKey key, Func valueCreator, TArg arg)