提交 51edce0f 编写于 作者: C CyrusNajmabadi

Merge pull request #10302 from CyrusNajmabadi/multipleInvokeDelegate

Do not attempt to move diagnostics with additional locations.

Fixes #10258
......@@ -250,7 +250,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
public DiagnosticAnalyzerCategory GetAnalyzerCategory()
{
return DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
return DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
}
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ErrorReporting;
......@@ -94,15 +95,28 @@ public async Task<AnalysisData> GetDocumentAnalysisDataAsync(DiagnosticAnalyzerD
{
var memberDxData = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);
diagnosticData = _owner.UpdateDocumentDiagnostics(existingData, ranges.Ranges, memberDxData.AsImmutableOrEmpty(), root.SyntaxTree, member, memberId);
ValidateMemberDiagnostics(stateSet.Analyzer, document, root, diagnosticData);
// if all the current diagnostics have all their locations in this document,
// then we can do a simple move of them.
if (existingData.Items.All(CanReuseDiagnostic) &&
memberDxData.All(CanReuseDiagnostic))
{
diagnosticData = _owner.UpdateDocumentDiagnostics(existingData, ranges.Ranges, memberDxData.AsImmutableOrEmpty(), root.SyntaxTree, member, memberId);
ValidateMemberDiagnostics(stateSet.Analyzer, document, root, diagnosticData);
}
else
{
// if we can't re-use existing document state, only option we have is updating whole document state here.
diagnosticData = await UpdateAllSemanticDiagnosticsAsync(
stateSet, analyzerDriver, diagnosticData).ConfigureAwait(false);
}
}
else
{
// if we can't re-use existing document state, only option we have is updating whole document state here.
var dx = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);
diagnosticData = dx.AsImmutableOrEmpty();
diagnosticData = await UpdateAllSemanticDiagnosticsAsync(
stateSet, analyzerDriver, diagnosticData).ConfigureAwait(false);
}
return new AnalysisData(versions.TextVersion, versions.DataVersion, GetExistingItems(existingData), diagnosticData);
}
catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
......@@ -111,6 +125,22 @@ public async Task<AnalysisData> GetDocumentAnalysisDataAsync(DiagnosticAnalyzerD
}
}
private bool CanReuseDiagnostic(DiagnosticData diagnostic)
{
// We can't reuse diagnostics that contain additional locations. It's too
// difficult to ensure that all the locations will be moved to the right
return diagnostic.AdditionalLocations == null || diagnostic.AdditionalLocations.Count == 0;
}
private static async Task<ImmutableArray<DiagnosticData>> UpdateAllSemanticDiagnosticsAsync(
StateSet stateSet, DiagnosticAnalyzerDriver analyzerDriver, ImmutableArray<DiagnosticData> diagnosticData)
{
var dx = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);
diagnosticData = dx.AsImmutableOrEmpty();
return diagnosticData;
}
private bool CanUseRange(int memberId, ImmutableArray<TextSpan> ranges)
{
// range got out of sync, don't do partial analysis
......
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
......@@ -937,11 +938,8 @@ private static ArgumentKey CreateArgumentKey(StateType type, object key, StateSe
private DiagnosticData UpdatePosition(DiagnosticData diagnostic, SyntaxTree tree, int delta)
{
var start = Math.Min(Math.Max(diagnostic.TextSpan.Start + delta, 0), tree.Length);
var newSpan = new TextSpan(start, start >= tree.Length ? 0 : diagnostic.TextSpan.Length);
var mappedLineInfo = tree.GetMappedLineSpan(newSpan);
var originalLineInfo = tree.GetLineSpan(newSpan);
Debug.Assert(diagnostic.AdditionalLocations == null || diagnostic.AdditionalLocations.Count == 0);
var newDiagnosticLocation = UpdateDiagnosticLocation(diagnostic.DataLocation, tree, delta);
return new DiagnosticData(
diagnostic.Id,
......@@ -956,22 +954,36 @@ private DiagnosticData UpdatePosition(DiagnosticData diagnostic, SyntaxTree tree
diagnostic.Properties,
diagnostic.Workspace,
diagnostic.ProjectId,
new DiagnosticDataLocation(diagnostic.DocumentId, newSpan,
originalFilePath: originalLineInfo.Path,
originalStartLine: originalLineInfo.StartLinePosition.Line,
originalStartColumn: originalLineInfo.StartLinePosition.Character,
originalEndLine: originalLineInfo.EndLinePosition.Line,
originalEndColumn: originalLineInfo.EndLinePosition.Character,
mappedFilePath: mappedLineInfo.GetMappedFilePathIfExist(),
mappedStartLine: mappedLineInfo.StartLinePosition.Line,
mappedStartColumn: mappedLineInfo.StartLinePosition.Character,
mappedEndLine: mappedLineInfo.EndLinePosition.Line,
mappedEndColumn: mappedLineInfo.EndLinePosition.Character),
newDiagnosticLocation,
additionalLocations: diagnostic.AdditionalLocations,
description: diagnostic.Description,
helpLink: diagnostic.HelpLink,
isSuppressed: diagnostic.IsSuppressed);
}
private DiagnosticDataLocation UpdateDiagnosticLocation(
DiagnosticDataLocation dataLocation, SyntaxTree tree, int delta)
{
var span = dataLocation.SourceSpan.Value;
var start = Math.Min(Math.Max(span.Start + delta, 0), tree.Length);
var newSpan = new TextSpan(start, start >= tree.Length ? 0 : span.Length);
var mappedLineInfo = tree.GetMappedLineSpan(newSpan);
var originalLineInfo = tree.GetLineSpan(newSpan);
return new DiagnosticDataLocation(dataLocation.DocumentId, newSpan,
originalFilePath: originalLineInfo.Path,
originalStartLine: originalLineInfo.StartLinePosition.Line,
originalStartColumn: originalLineInfo.StartLinePosition.Character,
originalEndLine: originalLineInfo.EndLinePosition.Line,
originalEndColumn: originalLineInfo.EndLinePosition.Character,
mappedFilePath: mappedLineInfo.GetMappedFilePathIfExist(),
mappedStartLine: mappedLineInfo.StartLinePosition.Line,
mappedStartColumn: mappedLineInfo.StartLinePosition.Character,
mappedEndLine: mappedLineInfo.EndLinePosition.Line,
mappedEndColumn: mappedLineInfo.EndLinePosition.Character);
}
private static IEnumerable<DiagnosticData> GetDiagnosticData(Document document, SyntaxTree tree, TextSpan? span, IEnumerable<Diagnostic> diagnostics)
{
return diagnostics != null ? diagnostics.Where(dx => ShouldIncludeDiagnostic(dx, tree, span)).Select(d => DiagnosticData.Create(document, d)) : null;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册