提交 89f0c602 编写于 作者: C CyrusNajmabadi

Rename types.

上级 df01eb49
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Versions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.DesignerAttributes
{
internal abstract class AbstractDesignerAttributeService : IDesignerAttributeService
{
private const string StreamName = "<DesignerAttribute>";
private const string FormatVersion = "3";
protected abstract bool ProcessOnlyFirstTypeDefined();
protected abstract IEnumerable<SyntaxNode> GetAllTopLevelTypeDefined(SyntaxNode root);
protected abstract bool HasAttributesOrBaseTypeOrIsPartial(SyntaxNode typeNode);
public async Task<DesignerAttributeResult> ScanDesignerAttributesAsync(Document document, CancellationToken cancellationToken)
public async Task<DesignerAttributeDocumentData> ScanDesignerAttributesAsync(Document document, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
......@@ -42,7 +51,7 @@ public async Task<DesignerAttributeResult> ScanDesignerAttributesAsync(Document
{
// The DesignerCategoryAttribute doesn't exist. either not applicable or
// no idea on design attribute status, just leave things as it is.
return new DesignerAttributeResult(document.FilePath, designerAttributeArgument, documentHasError, notApplicable: true);
return new DesignerAttributeDocumentData(document.FilePath, designerAttributeArgument, documentHasError, notApplicable: true);
}
}
......@@ -73,7 +82,7 @@ public async Task<DesignerAttributeResult> ScanDesignerAttributesAsync(Document
if (attribute != null && attribute.ConstructorArguments.Length == 1)
{
designerAttributeArgument = GetArgumentString(attribute.ConstructorArguments[0]);
return new DesignerAttributeResult(document.FilePath, designerAttributeArgument, documentHasError, notApplicable: false);
return new DesignerAttributeDocumentData(document.FilePath, designerAttributeArgument, documentHasError, notApplicable: false);
}
}
}
......@@ -85,7 +94,7 @@ public async Task<DesignerAttributeResult> ScanDesignerAttributesAsync(Document
}
}
return new DesignerAttributeResult(document.FilePath, designerAttributeArgument, documentHasError, notApplicable: false);
return new DesignerAttributeDocumentData(document.FilePath, designerAttributeArgument, documentHasError, notApplicable: false);
}
private static string GetArgumentString(TypedConstant argument)
......@@ -99,5 +108,123 @@ private static string GetArgumentString(TypedConstant argument)
return ((string)argument.Value).Trim();
}
internal static async Task<ImmutableDictionary<string, DesignerAttributeDocumentData>> TryAnalyzeProjectInCurrentProcessAsync(
Project project, CancellationToken cancellationToken)
{
var projectVersion = await project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false);
var semanticVersion = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);
// Get whatever data we've current persisted.
var designerAttributeData = await ReadExistingDataAsync(project, cancellationToken).ConfigureAwait(false);
// If we have no persisted data, or the persisted data is for a previous version of
// the project, then compute the results for the current project snapshot.
if (designerAttributeData == null ||
!project.CanReusePersistedDependentSemanticVersion(projectVersion, semanticVersion, designerAttributeData.SemanticVersion))
{
designerAttributeData = await ComputeAndPersistDesignerAttributeProjectDataAsync(
project, semanticVersion, cancellationToken).ConfigureAwait(false);
}
return designerAttributeData.PathToDocumentData;
}
private static async Task<DesignerAttributeProjectData> ComputeAndPersistDesignerAttributeProjectDataAsync(
Project project, VersionStamp semanticVersion, CancellationToken cancellationToken)
{
var service = project.LanguageServices.GetService<IDesignerAttributeService>();
var builder = ImmutableDictionary.CreateBuilder<string, DesignerAttributeDocumentData>();
foreach (var document in project.Documents)
{
var result = await service.ScanDesignerAttributesAsync(document, cancellationToken).ConfigureAwait(false);
builder[document.FilePath] = result;
}
var data = new DesignerAttributeProjectData(semanticVersion, builder.ToImmutable());
PersistProjectData(project, data, cancellationToken);
return data;
}
private static async Task<DesignerAttributeProjectData> ReadExistingDataAsync(
Project project, CancellationToken cancellationToken)
{
try
{
var solution = project.Solution;
var workspace = project.Solution.Workspace;
var storageService = workspace.Services.GetService<IPersistentStorageService>();
using (var persistenceService = storageService.GetStorage(solution))
using (var stream = await persistenceService.ReadStreamAsync(project, StreamName, cancellationToken).ConfigureAwait(false))
using (var reader = ObjectReader.TryGetReader(stream, cancellationToken))
{
if (reader != null)
{
var version = reader.ReadString();
if (version == FormatVersion)
{
var semanticVersion = VersionStamp.ReadFrom(reader);
var resultCount = reader.ReadInt32();
var builder = ImmutableDictionary.CreateBuilder<string, DesignerAttributeDocumentData>();
for (var i = 0; i < resultCount; i++)
{
var filePath = reader.ReadString();
var attribute = reader.ReadString();
var containsErrors = reader.ReadBoolean();
var notApplicable = reader.ReadBoolean();
builder[filePath] = new DesignerAttributeDocumentData(filePath, attribute, containsErrors, notApplicable);
}
return new DesignerAttributeProjectData(semanticVersion, builder.ToImmutable());
}
}
}
}
catch (Exception e) when (IOUtilities.IsNormalIOException(e))
{
// Storage APIs can throw arbitrary exceptions.
}
return null;
}
private static void PersistProjectData(
Project project, DesignerAttributeProjectData data, CancellationToken cancellationToken)
{
try
{
var solution = project.Solution;
var workspace = project.Solution.Workspace;
var storageService = workspace.Services.GetService<IPersistentStorageService>();
using (var persistenceService = storageService.GetStorage(solution))
using (var stream = SerializableBytes.CreateWritableStream())
using (var writer = new ObjectWriter(stream, cancellationToken: cancellationToken))
{
writer.WriteString(FormatVersion);
data.SemanticVersion.WriteTo(writer);
writer.WriteInt32(data.PathToDocumentData.Count);
foreach (var kvp in data.PathToDocumentData)
{
var result = kvp.Value;
writer.WriteString(result.FilePath);
writer.WriteString(result.DesignerAttributeArgument);
writer.WriteBoolean(result.ContainsErrors);
writer.WriteBoolean(result.NotApplicable);
}
}
}
catch (Exception e) when (IOUtilities.IsNormalIOException(e))
{
// Storage APIs can throw arbitrary exceptions.
}
}
}
}
\ No newline at end of file
......@@ -4,14 +4,14 @@
namespace Microsoft.CodeAnalysis.DesignerAttributes
{
internal struct DesignerAttributeResult : IEquatable<DesignerAttributeResult>
internal struct DesignerAttributeDocumentData : IEquatable<DesignerAttributeDocumentData>
{
public string FilePath;
public string DesignerAttributeArgument;
public bool ContainsErrors;
public bool NotApplicable;
public DesignerAttributeResult(string filePath, string designerAttributeArgument, bool containsErrors, bool notApplicable)
public DesignerAttributeDocumentData(string filePath, string designerAttributeArgument, bool containsErrors, bool notApplicable)
{
FilePath = filePath;
DesignerAttributeArgument = designerAttributeArgument;
......@@ -20,9 +20,9 @@ public DesignerAttributeResult(string filePath, string designerAttributeArgument
}
public override bool Equals(object obj)
=> Equals((DesignerAttributeResult)obj);
=> Equals((DesignerAttributeDocumentData)obj);
public bool Equals(DesignerAttributeResult other)
public bool Equals(DesignerAttributeDocumentData other)
{
return FilePath == other.FilePath &&
DesignerAttributeArgument == other.DesignerAttributeArgument &&
......
......@@ -4,17 +4,18 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.DesignerAttributes;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.DesignerAttribute
namespace Microsoft.CodeAnalysis.DesignerAttributes
{
internal class DesignerAttributeData
internal class DesignerAttributeProjectData
{
public readonly VersionStamp SemanticVersion;
public readonly ImmutableDictionary<string, DesignerAttributeResult> PathToResult;
public readonly ImmutableDictionary<string, DesignerAttributeDocumentData> PathToDocumentData;
public DesignerAttributeData(VersionStamp semanticVersion, ImmutableDictionary<string, DesignerAttributeResult> pathToResult)
public DesignerAttributeProjectData(
VersionStamp semanticVersion, ImmutableDictionary<string, DesignerAttributeDocumentData> pathToDocumentData)
{
SemanticVersion = semanticVersion;
PathToResult = pathToResult;
PathToDocumentData = pathToDocumentData;
}
}
}
\ No newline at end of file
......@@ -8,6 +8,6 @@ namespace Microsoft.CodeAnalysis.DesignerAttributes
{
internal interface IDesignerAttributeService : ILanguageService
{
Task<DesignerAttributeResult> ScanDesignerAttributesAsync(Document document, CancellationToken cancellationToken);
Task<DesignerAttributeDocumentData> ScanDesignerAttributesAsync(Document document, CancellationToken cancellationToken);
}
}
......@@ -6,6 +6,6 @@ namespace Microsoft.CodeAnalysis.DesignerAttributes
{
internal interface IRemoteDesignerAttributeService
{
Task<DesignerAttributeResult[]> ScanDesignerAttributesAsync(ProjectId projectId);
Task<DesignerAttributeDocumentData[]> ScanDesignerAttributesAsync(ProjectId projectId);
}
}
......@@ -122,7 +122,8 @@
<Compile Include="Completion\Providers\AbstractCrefCompletionProvider.cs" />
<Compile Include="ConvertToInterpolatedString\AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs" />
<Compile Include="DesignerAttributes\AbstractDesignerAttributeService.cs" />
<Compile Include="DesignerAttributes\DesignerAttributeResult.cs" />
<Compile Include="DesignerAttributes\DesignerAttributeProjectData.cs" />
<Compile Include="DesignerAttributes\DesignerAttributeDocumentData.cs" />
<Compile Include="DesignerAttributes\IDesignerAttributeService.cs" />
<Compile Include="DesignerAttributes\IRemoteDesignerAttributeService.cs" />
<Compile Include="Diagnostics\Analyzers\NamingStyleDiagnosticAnalyzerBase.cs" />
......
......@@ -28,9 +28,6 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.DesignerAttribu
{
internal partial class DesignerAttributeIncrementalAnalyzer : ForegroundThreadAffinitizedObject, IIncrementalAnalyzer
{
private const string StreamName = "<DesignerAttribute>";
private const string FormatVersion = "3";
private readonly IForegroundNotificationService _notificationService;
private readonly IServiceProvider _serviceProvider;
......@@ -43,8 +40,12 @@ internal partial class DesignerAttributeIncrementalAnalyzer : ForegroundThreadAf
/// </summary>
private IVSMDDesignerService _dotNotAccessDirectlyDesigner;
private readonly ConcurrentDictionary<ProjectId, ImmutableDictionary<string, DesignerAttributeResult>> _lastReportedProjectData =
new ConcurrentDictionary<ProjectId, ImmutableDictionary<string, DesignerAttributeResult>>();
/// <summary>
/// Keep track of the last results we reported to VS. We can use this to diff future results
/// to report only what actually changed.
/// </summary>
private readonly ConcurrentDictionary<ProjectId, ImmutableDictionary<string, DesignerAttributeDocumentData>> _lastReportedProjectData =
new ConcurrentDictionary<ProjectId, ImmutableDictionary<string, DesignerAttributeDocumentData>>();
public DesignerAttributeIncrementalAnalyzer(
IServiceProvider serviceProvider,
......@@ -92,133 +93,22 @@ public async Task AnalyzeProjectAsync(Project project, bool semanticsChanged, In
return;
}
// Try to compute this data in the remote process. If that fails, then compute
// the results in the local process.
var pathToResult = await TryAnalyzeProjectInRemoteProcessAsync(project, cancellationToken).ConfigureAwait(false);
if (pathToResult == null)
{
pathToResult = await TryAnalyzeProjectInCurrentProcessAsync(project, cancellationToken).ConfigureAwait(false);
pathToResult = await AbstractDesignerAttributeService.TryAnalyzeProjectInCurrentProcessAsync(
project, cancellationToken).ConfigureAwait(false);
}
cancellationToken.ThrowIfCancellationRequested();
RegisterDesignerAttributes(project, pathToResult);
}
private async Task<ImmutableDictionary<string, DesignerAttributeResult>> TryAnalyzeProjectInCurrentProcessAsync(
Project project, CancellationToken cancellationToken)
{
// use tree version so that things like compiler option changes are considered
var projectVersion = await project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false);
var semanticVersion = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);
var designerAttributeData = await ReadExistingDataAsync(project, cancellationToken).ConfigureAwait(false);
if (designerAttributeData == null ||
!project.CanReusePersistedDependentSemanticVersion(projectVersion, semanticVersion, designerAttributeData.SemanticVersion))
{
designerAttributeData = await ComputeAndPersistDesignerAttributeDataAsync(
project, semanticVersion, cancellationToken).ConfigureAwait(false);
}
return designerAttributeData.PathToResult;
}
private async Task<DesignerAttributeData> ComputeAndPersistDesignerAttributeDataAsync(
Project project, VersionStamp semanticVersion, CancellationToken cancellationToken)
{
var service = project.LanguageServices.GetService<IDesignerAttributeService>();
var builder = ImmutableDictionary.CreateBuilder<string, DesignerAttributeResult>();
foreach (var document in project.Documents)
{
var result = await service.ScanDesignerAttributesAsync(document, cancellationToken).ConfigureAwait(false);
builder[document.FilePath] = result;
}
var data = new DesignerAttributeData(semanticVersion, builder.ToImmutable());
PersistData(project, data, cancellationToken);
return data;
}
private async Task<DesignerAttributeData> ReadExistingDataAsync(
Project project, CancellationToken cancellationToken)
{
try
{
var solution = project.Solution;
var workspace = project.Solution.Workspace;
var storageService = workspace.Services.GetService<IPersistentStorageService>();
using (var persistenceService = storageService.GetStorage(solution))
using (var stream = await persistenceService.ReadStreamAsync(project, StreamName, cancellationToken).ConfigureAwait(false))
using (var reader = ObjectReader.TryGetReader(stream, cancellationToken))
{
if (reader != null)
{
var version = reader.ReadString();
if (version == FormatVersion)
{
var semanticVersion = VersionStamp.ReadFrom(reader);
var resultCount = reader.ReadInt32();
var builder = ImmutableDictionary.CreateBuilder<string, DesignerAttributeResult>();
for (var i = 0; i < resultCount; i++)
{
var filePath = reader.ReadString();
var attribute = reader.ReadString();
var containsErrors = reader.ReadBoolean();
var notApplicable = reader.ReadBoolean();
builder[filePath] = new DesignerAttributeResult(filePath, attribute, containsErrors, notApplicable);
}
return new DesignerAttributeData(semanticVersion, builder.ToImmutable());
}
}
}
}
catch (Exception e) when (IOUtilities.IsNormalIOException(e))
{
// Storage APIs can throw arbitrary exceptions.
}
return null;
}
private void PersistData(
Project project, DesignerAttributeData data, CancellationToken cancellationToken)
{
try
{
var solution = project.Solution;
var workspace = project.Solution.Workspace;
var storageService = workspace.Services.GetService<IPersistentStorageService>();
using (var persistenceService = storageService.GetStorage(solution))
using (var stream = SerializableBytes.CreateWritableStream())
using (var writer = new ObjectWriter(stream, cancellationToken: cancellationToken))
{
writer.WriteString(FormatVersion);
data.SemanticVersion.WriteTo(writer);
writer.WriteInt32(data.PathToResult.Count);
foreach (var kvp in data.PathToResult)
{
var result = kvp.Value;
writer.WriteString(result.FilePath);
writer.WriteString(result.DesignerAttributeArgument);
writer.WriteBoolean(result.ContainsErrors);
writer.WriteBoolean(result.NotApplicable);
}
}
}
catch (Exception e) when (IOUtilities.IsNormalIOException(e))
{
// Storage APIs can throw arbitrary exceptions.
}
// Once we get the current data, diff it and report the results to VS.
RegisterDesignerAttributes(project, pathToResult);
}
private async Task<ImmutableDictionary<string, DesignerAttributeResult>> TryAnalyzeProjectInRemoteProcessAsync(Project project, CancellationToken cancellationToken)
private async Task<ImmutableDictionary<string, DesignerAttributeDocumentData>> TryAnalyzeProjectInRemoteProcessAsync(Project project, CancellationToken cancellationToken)
{
using (var session = await TryGetRemoteSessionAsync(project.Solution, cancellationToken).ConfigureAwait(false))
{
......@@ -227,7 +117,7 @@ public async Task AnalyzeProjectAsync(Project project, bool semanticsChanged, In
return null;
}
var serializedResults = await session.InvokeAsync<DesignerAttributeResult[]>(
var serializedResults = await session.InvokeAsync<DesignerAttributeDocumentData[]>(
nameof(IRemoteDesignerAttributeService.ScanDesignerAttributesAsync), project.Id).ConfigureAwait(false);
var data = serializedResults.ToImmutableDictionary(kvp => kvp.FilePath);
......@@ -249,12 +139,12 @@ public async Task AnalyzeProjectAsync(Project project, bool semanticsChanged, In
}
private void RegisterDesignerAttributes(
Project project, ImmutableDictionary<string, DesignerAttributeResult> pathToResult)
Project project, ImmutableDictionary<string, DesignerAttributeDocumentData> pathToResult)
{
// Diff this result against the last result we reported for this project.
// If there are any changes report them all at once to VS.
var lastPathToResult = _lastReportedProjectData.GetOrAdd(
project.Id, ImmutableDictionary<string, DesignerAttributeResult>.Empty);
project.Id, ImmutableDictionary<string, DesignerAttributeDocumentData>.Empty);
_lastReportedProjectData[project.Id] = pathToResult;
......@@ -276,11 +166,11 @@ public async Task AnalyzeProjectAsync(Project project, bool semanticsChanged, In
}, _listener.BeginAsyncOperation("RegisterDesignerAttribute"));
}
private ImmutableDictionary<string, DesignerAttributeResult> GetDifference(
ImmutableDictionary<string, DesignerAttributeResult> oldFileToResult,
ImmutableDictionary<string, DesignerAttributeResult> newFileToResult)
private ImmutableDictionary<string, DesignerAttributeDocumentData> GetDifference(
ImmutableDictionary<string, DesignerAttributeDocumentData> oldFileToResult,
ImmutableDictionary<string, DesignerAttributeDocumentData> newFileToResult)
{
var difference = ImmutableDictionary.CreateBuilder<string, DesignerAttributeResult>();
var difference = ImmutableDictionary.CreateBuilder<string, DesignerAttributeDocumentData>();
foreach (var newKvp in newFileToResult)
{
......
......@@ -57,7 +57,6 @@
<Compile Include="Implementation\AnalyzerDependency\IgnorableAssemblyIdentityList.cs" />
<Compile Include="Implementation\AnalyzerDependency\IgnorableAssemblyNameList.cs" />
<Compile Include="Implementation\AnalyzerDependency\IgnorableAssemblyNamePrefixList.cs" />
<Compile Include="Implementation\DesignerAttribute\DesignerAttributeData.cs" />
<Compile Include="Implementation\Diagnostics\VisualStudioVenusSpanMappingService.cs" />
<Compile Include="Implementation\Diagnostics\VisualStudioWorkspaceDiagnosticAnalyzerProviderService.AnalyzerAssemblyLoader.cs" />
<Compile Include="Implementation\EditAndContinue\Interop\NativeMethods.cs" />
......
......@@ -92,7 +92,7 @@ class Test { }";
var solution = workspace.CurrentSolution;
var result = await client.RunCodeAnalysisServiceOnRemoteHostAsync<DesignerAttributeResult>(
var result = await client.RunCodeAnalysisServiceOnRemoteHostAsync<DesignerAttributeDocumentData>(
solution, nameof(IRemoteDesignerAttributeService.ScanDesignerAttributesAsync),
solution.Projects.First().DocumentIds.First(), CancellationToken.None);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.DesignerAttributes;
using Microsoft.CodeAnalysis.Internal.Log;
......@@ -15,24 +16,16 @@ internal partial class CodeAnalysisService : IRemoteDesignerAttributeService
///
/// This will be called by ServiceHub/JsonRpc framework
/// </summary>
public async Task<DesignerAttributeResult[]> ScanDesignerAttributesAsync(ProjectId projectId)
public async Task<DesignerAttributeDocumentData[]> ScanDesignerAttributesAsync(ProjectId projectId)
{
using (RoslynLogger.LogBlock(FunctionId.CodeAnalysisService_GetDesignerAttributesAsync, projectId.DebugName, CancellationToken))
{
var solution = await GetSolutionAsync().ConfigureAwait(false);
var project = solution.GetProject(projectId);
var service = project.LanguageServices.GetService<IDesignerAttributeService>();
var data = await AbstractDesignerAttributeService.TryAnalyzeProjectInCurrentProcessAsync(
project, CancellationToken).ConfigureAwait(false);
var results = new DesignerAttributeResult[project.DocumentIds.Count];
var index = 0;
foreach (var document in project.Documents)
{
var result = await service.ScanDesignerAttributesAsync(document, CancellationToken).ConfigureAwait(false);
results[index] = result;
index++;
}
return results;
return data.Values.ToArray();
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册