未验证 提交 d8e676b0 编写于 作者: M Manish Vasani 提交者: GitHub

Merge pull request #25496 from mavasani/RaceConditionFix

Fix race condition in analyzer driver where multiple threads attempti…
......@@ -14,14 +14,25 @@ namespace Microsoft.CodeAnalysis.CSharp
{
internal class CSharpDeclarationComputer : DeclarationComputer
{
public static void ComputeDeclarationsInSpan(SemanticModel model, TextSpan span, bool getSymbol, List<DeclarationInfo> builder, CancellationToken cancellationToken)
public static void ComputeDeclarationsInSpan(
SemanticModel model,
TextSpan span,
bool getSymbol,
ArrayBuilder<DeclarationInfo> builder,
CancellationToken cancellationToken)
{
ComputeDeclarations(model, model.SyntaxTree.GetRoot(cancellationToken),
(node, level) => !node.Span.OverlapsWith(span) || InvalidLevel(level),
getSymbol, builder, null, cancellationToken);
}
public static void ComputeDeclarationsInNode(SemanticModel model, SyntaxNode node, bool getSymbol, List<DeclarationInfo> builder, CancellationToken cancellationToken, int? levelsToCompute = null)
public static void ComputeDeclarationsInNode(
SemanticModel model,
SyntaxNode node,
bool getSymbol,
ArrayBuilder<DeclarationInfo> builder,
CancellationToken cancellationToken,
int? levelsToCompute = null)
{
ComputeDeclarations(model, node, (n, level) => InvalidLevel(level), getSymbol, builder, levelsToCompute, cancellationToken);
}
......@@ -41,7 +52,7 @@ private static bool InvalidLevel(int? level)
SyntaxNode node,
Func<SyntaxNode, int?, bool> shouldSkip,
bool getSymbol,
List<DeclarationInfo> builder,
ArrayBuilder<DeclarationInfo> builder,
int? levelsToCompute,
CancellationToken cancellationToken)
{
......
......@@ -4747,12 +4747,12 @@ protected sealed override ImmutableArray<ISymbol> GetDeclaredSymbolsCore(SyntaxN
return ImmutableArray.Create<ISymbol>();
}
internal override void ComputeDeclarationsInSpan(TextSpan span, bool getSymbol, List<DeclarationInfo> builder, CancellationToken cancellationToken)
internal override void ComputeDeclarationsInSpan(TextSpan span, bool getSymbol, ArrayBuilder<DeclarationInfo> builder, CancellationToken cancellationToken)
{
CSharpDeclarationComputer.ComputeDeclarationsInSpan(this, span, getSymbol, builder, cancellationToken);
}
internal override void ComputeDeclarationsInNode(SyntaxNode node, bool getSymbol, List<DeclarationInfo> builder, CancellationToken cancellationToken, int? levelsToCompute = null)
internal override void ComputeDeclarationsInNode(SyntaxNode node, bool getSymbol, ArrayBuilder<DeclarationInfo> builder, CancellationToken cancellationToken, int? levelsToCompute = null)
{
CSharpDeclarationComputer.ComputeDeclarationsInNode(this, node, getSymbol, builder, cancellationToken, levelsToCompute);
}
......
......@@ -5,6 +5,7 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis
......@@ -859,12 +860,12 @@ public PreprocessingSymbolInfo GetPreprocessingSymbolInfo(SyntaxNode nameSyntax)
/// If false, then <see cref="DeclarationInfo.DeclaredSymbol"/> is always null.</param>
/// <param name="builder">Builder to add declarations.</param>
/// <param name="cancellationToken">Cancellation token.</param>
internal abstract void ComputeDeclarationsInSpan(TextSpan span, bool getSymbol, List<DeclarationInfo> builder, CancellationToken cancellationToken);
internal abstract void ComputeDeclarationsInSpan(TextSpan span, bool getSymbol, ArrayBuilder<DeclarationInfo> builder, CancellationToken cancellationToken);
/// <summary>
/// Takes a node and returns a set of declarations that overlap the node's span.
/// </summary>
internal abstract void ComputeDeclarationsInNode(SyntaxNode node, bool getSymbol, List<DeclarationInfo> builder, CancellationToken cancellationToken, int? levelsToCompute = null);
internal abstract void ComputeDeclarationsInNode(SyntaxNode node, bool getSymbol, ArrayBuilder<DeclarationInfo> builder, CancellationToken cancellationToken, int? levelsToCompute = null);
/// <summary>
/// Takes a Symbol and syntax for one of its declaring syntax reference and returns the topmost syntax node to be used by syntax analyzer.
......
......@@ -161,7 +161,7 @@ private PerAnalyzerState GetAnalyzerState(DiagnosticAnalyzer analyzer)
}
}
private IEnumerable<ISymbol> GetDeclaredSymbolsInTree(
private ImmutableArray<ISymbol> GetDeclaredSymbolsInTree(
SyntaxTree tree,
Compilation compilation,
Func<SyntaxTree, Compilation, CancellationToken, SemanticModel> getCachedSemanticModel,
......@@ -169,9 +169,11 @@ private PerAnalyzerState GetAnalyzerState(DiagnosticAnalyzer analyzer)
{
var model = getCachedSemanticModel(tree, compilation, cancellationToken);
var fullSpan = tree.GetRoot(cancellationToken).FullSpan;
var declarationInfos = new List<DeclarationInfo>();
model.ComputeDeclarationsInSpan(fullSpan, getSymbol: true, builder: declarationInfos, cancellationToken: cancellationToken);
return declarationInfos.Select(declInfo => declInfo.DeclaredSymbol).Distinct().WhereNotNull();
var declarationInfoBuilder = ArrayBuilder<DeclarationInfo>.GetInstance();
model.ComputeDeclarationsInSpan(fullSpan, getSymbol: true, builder: declarationInfoBuilder, cancellationToken: cancellationToken);
ImmutableArray<ISymbol> result = declarationInfoBuilder.Select(declInfo => declInfo.DeclaredSymbol).Distinct().WhereNotNull().ToImmutableArray();
declarationInfoBuilder.Free();
return result;
}
private static ImmutableArray<CompilationEvent> CreateCompilationEventsForTree(IEnumerable<ISymbol> declaredSymbols, SyntaxTree tree, Compilation compilation)
......
......@@ -21,14 +21,12 @@ internal class CompilationData
private readonly Dictionary<SyntaxTree, SemanticModel> _semanticModelsMap;
private readonly Dictionary<SyntaxReference, DeclarationAnalysisData> _declarationAnalysisDataMap;
private readonly ObjectPool<DeclarationAnalysisData> _declarationAnalysisDataPool;
public CompilationData(Compilation comp)
{
_semanticModelsMap = new Dictionary<SyntaxTree, SemanticModel>();
this.SuppressMessageAttributeState = new SuppressMessageAttributeState(comp);
_declarationAnalysisDataMap = new Dictionary<SyntaxReference, DeclarationAnalysisData>();
_declarationAnalysisDataPool = new ObjectPool<DeclarationAnalysisData>(() => new DeclarationAnalysisData());
}
public SuppressMessageAttributeState SuppressMessageAttributeState { get; }
......@@ -64,28 +62,34 @@ public bool RemoveCachedSemanticModel(SyntaxTree tree)
internal DeclarationAnalysisData GetOrComputeDeclarationAnalysisData(
SyntaxReference declaration,
Func<Func<DeclarationAnalysisData>, DeclarationAnalysisData> computeDeclarationAnalysisData,
Func<DeclarationAnalysisData> computeDeclarationAnalysisData,
bool cacheAnalysisData)
{
if (!cacheAnalysisData)
{
return computeDeclarationAnalysisData(_declarationAnalysisDataPool.Allocate);
return computeDeclarationAnalysisData();
}
DeclarationAnalysisData data;
lock (_declarationAnalysisDataMap)
{
if (_declarationAnalysisDataMap.TryGetValue(declaration, out data))
if (_declarationAnalysisDataMap.TryGetValue(declaration, out DeclarationAnalysisData cachedData))
{
return data;
return cachedData;
}
}
data = computeDeclarationAnalysisData(_declarationAnalysisDataPool.Allocate);
DeclarationAnalysisData data = computeDeclarationAnalysisData();
lock (_declarationAnalysisDataMap)
{
_declarationAnalysisDataMap[declaration] = data;
if (!_declarationAnalysisDataMap.TryGetValue(declaration, out DeclarationAnalysisData existingData))
{
_declarationAnalysisDataMap.Add(declaration, data);
}
else
{
data = existingData;
}
}
return data;
......@@ -93,63 +97,11 @@ public bool RemoveCachedSemanticModel(SyntaxTree tree)
internal void ClearDeclarationAnalysisData(SyntaxReference declaration)
{
DeclarationAnalysisData declarationData;
lock (_declarationAnalysisDataMap)
{
if (!_declarationAnalysisDataMap.TryGetValue(declaration, out declarationData))
{
return;
}
_declarationAnalysisDataMap.Remove(declaration);
declarationData.Free();
_declarationAnalysisDataPool.Free(declarationData);
}
}
}
internal class DeclarationAnalysisData
{
/// <summary>
/// GetSyntax() for the given SyntaxReference.
/// </summary>
public SyntaxNode DeclaringReferenceSyntax { get; set; }
/// <summary>
/// Topmost declaration node for analysis.
/// </summary>
public SyntaxNode TopmostNodeForAnalysis { get; set; }
/// <summary>
/// All member declarations within the declaration.
/// </summary>
public List<DeclarationInfo> DeclarationsInNode { get; }
/// <summary>
/// All descendant nodes for syntax node actions.
/// </summary>
public List<SyntaxNode> DescendantNodesToAnalyze { get; }
/// <summary>
/// Flag indicating if this is a partial analysis.
/// </summary>
public bool IsPartialAnalysis { get; set; }
public DeclarationAnalysisData()
{
this.DeclarationsInNode = new List<DeclarationInfo>();
this.DescendantNodesToAnalyze = new List<SyntaxNode>();
}
public void Free()
{
DeclaringReferenceSyntax = null;
TopmostNodeForAnalysis = null;
DeclarationsInNode.Clear();
DescendantNodesToAnalyze.Clear();
IsPartialAnalysis = false;
}
}
}
}
// 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.Immutable;
namespace Microsoft.CodeAnalysis.Diagnostics
{
internal abstract partial class AnalyzerDriver
{
internal sealed class DeclarationAnalysisData
{
public DeclarationAnalysisData(
SyntaxNode declaringReferenceSyntax,
SyntaxNode topmostNodeForAnalysis,
ImmutableArray<DeclarationInfo> declarationsInNodeBuilder,
ImmutableArray<SyntaxNode> descendantNodesToAnalyze,
bool isPartialAnalysis)
{
DeclaringReferenceSyntax = declaringReferenceSyntax;
TopmostNodeForAnalysis = topmostNodeForAnalysis;
DeclarationsInNode = declarationsInNodeBuilder;
DescendantNodesToAnalyze = descendantNodesToAnalyze;
IsPartialAnalysis = isPartialAnalysis;
}
/// <summary>
/// GetSyntax() for the given SyntaxReference.
/// </summary>
public SyntaxNode DeclaringReferenceSyntax { get; }
/// <summary>
/// Topmost declaration node for analysis.
/// </summary>
public SyntaxNode TopmostNodeForAnalysis { get; }
/// <summary>
/// All member declarations within the declaration.
/// </summary>
public ImmutableArray<DeclarationInfo> DeclarationsInNode { get; }
/// <summary>
/// All descendant nodes for syntax node actions.
/// </summary>
public ImmutableArray<SyntaxNode> DescendantNodesToAnalyze { get; }
/// <summary>
/// Flag indicating if this is a partial analysis.
/// </summary>
public bool IsPartialAnalysis { get; }
}
}
}
......@@ -684,11 +684,11 @@ private ImmutableHashSet<ISymbol> ComputeGeneratedCodeSymbolsInTree(SyntaxTree t
var model = compilation.GetSemanticModel(tree);
var root = tree.GetRoot(cancellationToken);
var span = root.FullSpan;
var builder = new List<DeclarationInfo>();
model.ComputeDeclarationsInSpan(span, getSymbol: true, builder: builder, cancellationToken: cancellationToken);
var declarationInfoBuilder = ArrayBuilder<DeclarationInfo>.GetInstance();
model.ComputeDeclarationsInSpan(span, getSymbol: true, builder: declarationInfoBuilder, cancellationToken: cancellationToken);
ImmutableHashSet<ISymbol>.Builder generatedSymbolsBuilderOpt = null;
foreach (var declarationInfo in builder)
foreach (var declarationInfo in declarationInfoBuilder)
{
var symbol = declarationInfo.DeclaredSymbol;
if (symbol != null &&
......@@ -699,6 +699,7 @@ private ImmutableHashSet<ISymbol> ComputeGeneratedCodeSymbolsInTree(SyntaxTree t
}
}
declarationInfoBuilder.Free();
return generatedSymbolsBuilderOpt != null ? generatedSymbolsBuilderOpt.ToImmutable() : ImmutableHashSet<ISymbol>.Empty;
}
......@@ -1391,8 +1392,6 @@ internal class AnalyzerDriver<TLanguageKindEnum> : AnalyzerDriver where TLanguag
private ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<OperationBlockAnalyzerAction>> _lazyOperationBlockActionsByAnalyzer;
private ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<OperationBlockAnalyzerAction>> _lazyOperationBlockEndActionsByAnalyzer;
private static readonly ObjectPool<DeclarationAnalysisData> s_declarationAnalysisDataPool = new ObjectPool<DeclarationAnalysisData>(() => new DeclarationAnalysisData());
/// <summary>
/// Create an analyzer driver.
/// </summary>
......@@ -1675,30 +1674,22 @@ private void ClearCachedAnalysisDataIfAnalyzed(SyntaxReference declaration, ISym
SyntaxReference declaration,
SemanticModel semanticModel,
AnalysisScope analysisScope,
Func<DeclarationAnalysisData> allocateData,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var declarationAnalysisData = allocateData();
var builder = declarationAnalysisData.DeclarationsInNode;
var declaringReferenceSyntax = declaration.GetSyntax(cancellationToken);
var topmostNodeForAnalysis = semanticModel.GetTopmostNodeForDiagnosticAnalysis(symbol, declaringReferenceSyntax);
var builder = ArrayBuilder<DeclarationInfo>.GetInstance();
SyntaxNode declaringReferenceSyntax = declaration.GetSyntax(cancellationToken);
SyntaxNode topmostNodeForAnalysis = semanticModel.GetTopmostNodeForDiagnosticAnalysis(symbol, declaringReferenceSyntax);
ComputeDeclarationsInNode(semanticModel, symbol, declaringReferenceSyntax, topmostNodeForAnalysis, builder, cancellationToken);
ImmutableArray<DeclarationInfo> declarationInfos = builder.ToImmutableAndFree();
var isPartialDeclAnalysis = analysisScope.FilterSpanOpt.HasValue && !analysisScope.ContainsSpan(topmostNodeForAnalysis.FullSpan);
var nodesToAnalyze = GetSyntaxNodesToAnalyze(topmostNodeForAnalysis, symbol, builder, analysisScope, isPartialDeclAnalysis, semanticModel, analyzerExecutor);
declarationAnalysisData.DeclaringReferenceSyntax = declaringReferenceSyntax;
declarationAnalysisData.TopmostNodeForAnalysis = topmostNodeForAnalysis;
declarationAnalysisData.DescendantNodesToAnalyze.AddRange(nodesToAnalyze);
declarationAnalysisData.IsPartialAnalysis = isPartialDeclAnalysis;
return declarationAnalysisData;
bool isPartialDeclAnalysis = analysisScope.FilterSpanOpt.HasValue && !analysisScope.ContainsSpan(topmostNodeForAnalysis.FullSpan);
ImmutableArray<SyntaxNode> nodesToAnalyze = GetSyntaxNodesToAnalyze(topmostNodeForAnalysis, symbol, declarationInfos, analysisScope, isPartialDeclAnalysis, semanticModel, analyzerExecutor);
return new DeclarationAnalysisData(declaringReferenceSyntax, topmostNodeForAnalysis, declarationInfos, nodesToAnalyze, isPartialDeclAnalysis);
}
private static void ComputeDeclarationsInNode(SemanticModel semanticModel, ISymbol declaredSymbol, SyntaxNode declaringReferenceSyntax, SyntaxNode topmostNodeForAnalysis, List<DeclarationInfo> builder, CancellationToken cancellationToken)
private static void ComputeDeclarationsInNode(SemanticModel semanticModel, ISymbol declaredSymbol, SyntaxNode declaringReferenceSyntax, SyntaxNode topmostNodeForAnalysis, ArrayBuilder<DeclarationInfo> builder, CancellationToken cancellationToken)
{
// We only care about the top level symbol declaration and its immediate member declarations.
int? levelsToCompute = 2;
......@@ -1740,8 +1731,8 @@ private static void ComputeDeclarationsInNode(SemanticModel semanticModel, ISymb
var declarationAnalysisData = compilationData.GetOrComputeDeclarationAnalysisData(
decl,
allocateData => ComputeDeclarationAnalysisData(symbol, decl, semanticModel, analysisScope, allocateData, cancellationToken),
cacheAnalysisData);
computeDeclarationAnalysisData: () => ComputeDeclarationAnalysisData(symbol, decl, semanticModel, analysisScope, cancellationToken),
cacheAnalysisData: cacheAnalysisData);
if (!analysisScope.ShouldAnalyze(declarationAnalysisData.TopmostNodeForAnalysis))
{
......@@ -1971,10 +1962,10 @@ yield return
}
}
private static IEnumerable<SyntaxNode> GetSyntaxNodesToAnalyze(
private static ImmutableArray<SyntaxNode> GetSyntaxNodesToAnalyze(
SyntaxNode declaredNode,
ISymbol declaredSymbol,
IEnumerable<DeclarationInfo> declarationsInNode,
ImmutableArray<DeclarationInfo> declarationsInNode,
AnalysisScope analysisScope,
bool isPartialDeclAnalysis,
SemanticModel semanticModel,
......@@ -1982,7 +1973,7 @@ yield return
{
// Eliminate descendant member declarations within declarations.
// There will be separate symbols declared for the members.
HashSet<SyntaxNode> descendantDeclsToSkip = null;
HashSet<SyntaxNode> descendantDeclsToSkipOpt = null;
bool first = true;
foreach (var declInNode in declarationsInNode)
{
......@@ -2013,23 +2004,25 @@ yield return
declarationNodeToSkip = semanticModel.GetTopmostNodeForDiagnosticAnalysis(declaredSymbolOfDeclInNode, declInNode.DeclaredNode);
}
descendantDeclsToSkip = descendantDeclsToSkip ?? new HashSet<SyntaxNode>();
descendantDeclsToSkip.Add(declarationNodeToSkip);
descendantDeclsToSkipOpt = descendantDeclsToSkipOpt ?? new HashSet<SyntaxNode>();
descendantDeclsToSkipOpt.Add(declarationNodeToSkip);
}
first = false;
}
var nodesToAnalyze = descendantDeclsToSkip == null ?
declaredNode.DescendantNodesAndSelf(descendIntoTrivia: true) :
GetSyntaxNodesToAnalyze(declaredNode, descendantDeclsToSkip);
if (isPartialDeclAnalysis)
bool shouldAddNode(SyntaxNode node) => descendantDeclsToSkipOpt == null || !descendantDeclsToSkipOpt.Contains(node);
var nodeBuilder = ArrayBuilder<SyntaxNode>.GetInstance();
foreach (var node in declaredNode.DescendantNodesAndSelf(descendIntoChildren: shouldAddNode, descendIntoTrivia: true))
{
nodesToAnalyze = nodesToAnalyze.Where(node => analysisScope.ShouldAnalyze(node));
if (shouldAddNode(node) &&
(!isPartialDeclAnalysis || analysisScope.ShouldAnalyze(node)))
{
nodeBuilder.Add(node);
}
}
return nodesToAnalyze;
return nodeBuilder.ToImmutableAndFree();
}
private static bool IsEquivalentSymbol(ISymbol declaredSymbol, ISymbol otherSymbol)
......@@ -2109,19 +2102,5 @@ private static bool IsEquivalentSymbol(ISymbol declaredSymbol, ISymbol otherSymb
Debug.Assert(operationsToAnalyze.ToImmutableHashSet().Count == operationsToAnalyze.Count);
return operationsToAnalyze.ToImmutableAndFree();
}
private static IEnumerable<SyntaxNode> GetSyntaxNodesToAnalyze(SyntaxNode declaredNode, HashSet<SyntaxNode> descendantDeclsToSkip)
{
Debug.Assert(declaredNode != null);
Debug.Assert(descendantDeclsToSkip != null);
foreach (var node in declaredNode.DescendantNodesAndSelf(n => !descendantDeclsToSkip.Contains(n), descendIntoTrivia: true))
{
if (!descendantDeclsToSkip.Contains(node))
{
yield return node;
}
}
}
}
}
......@@ -2,6 +2,7 @@
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
......@@ -9,13 +10,21 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Friend Class VisualBasicDeclarationComputer
Inherits DeclarationComputer
Public Shared Sub ComputeDeclarationsInSpan(model As SemanticModel, span As TextSpan, getSymbol As Boolean, builder As List(Of DeclarationInfo), cancellationToken As CancellationToken)
Public Shared Sub ComputeDeclarationsInSpan(model As SemanticModel,
span As TextSpan,
getSymbol As Boolean,
builder As ArrayBuilder(Of DeclarationInfo),
cancellationToken As CancellationToken)
ComputeDeclarationsCore(model, model.SyntaxTree.GetRoot(),
Function(node, level) Not node.Span.OverlapsWith(span) OrElse InvalidLevel(level),
getSymbol, builder, Nothing, cancellationToken)
End Sub
Public Shared Sub ComputeDeclarationsInNode(model As SemanticModel, node As SyntaxNode, getSymbol As Boolean, builder As List(Of DeclarationInfo), cancellationToken As CancellationToken, Optional levelsToCompute As Integer? = Nothing)
Public Shared Sub ComputeDeclarationsInNode(model As SemanticModel,
node As SyntaxNode,
getSymbol As Boolean,
builder As ArrayBuilder(Of DeclarationInfo),
cancellationToken As CancellationToken, Optional levelsToCompute As Integer? = Nothing)
ComputeDeclarationsCore(model, node, Function(n, level) InvalidLevel(level), getSymbol, builder, levelsToCompute, cancellationToken)
End Sub
......@@ -28,7 +37,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return If(level.HasValue, level.Value - 1, level)
End Function
Private Shared Sub ComputeDeclarationsCore(model As SemanticModel, node As SyntaxNode, shouldSkip As Func(Of SyntaxNode, Integer?, Boolean), getSymbol As Boolean, builder As List(Of DeclarationInfo), levelsToCompute As Integer?, cancellationToken As CancellationToken)
Private Shared Sub ComputeDeclarationsCore(model As SemanticModel,
node As SyntaxNode,
shouldSkip As Func(Of SyntaxNode, Integer?, Boolean),
getSymbol As Boolean,
builder As ArrayBuilder(Of DeclarationInfo),
levelsToCompute As Integer?,
cancellationToken As CancellationToken)
cancellationToken.ThrowIfCancellationRequested()
If shouldSkip(node, levelsToCompute) Then
......
......@@ -3430,11 +3430,11 @@ _Default:
Return False
End Function
Friend Overrides Sub ComputeDeclarationsInSpan(span As TextSpan, getSymbol As Boolean, builder As List(Of DeclarationInfo), cancellationToken As CancellationToken)
Friend Overrides Sub ComputeDeclarationsInSpan(span As TextSpan, getSymbol As Boolean, builder As ArrayBuilder(Of DeclarationInfo), cancellationToken As CancellationToken)
VisualBasicDeclarationComputer.ComputeDeclarationsInSpan(Me, span, getSymbol, builder, cancellationToken)
End Sub
Friend Overrides Sub ComputeDeclarationsInNode(node As SyntaxNode, getSymbol As Boolean, builder As List(Of DeclarationInfo), cancellationToken As CancellationToken, Optional levelsToCompute As Integer? = Nothing)
Friend Overrides Sub ComputeDeclarationsInNode(node As SyntaxNode, getSymbol As Boolean, builder As ArrayBuilder(Of DeclarationInfo), cancellationToken As CancellationToken, Optional levelsToCompute As Integer? = Nothing)
VisualBasicDeclarationComputer.ComputeDeclarationsInNode(Me, node, getSymbol, builder, cancellationToken)
End Sub
......
// 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.Collections.Generic;
using System.Composition;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics
......@@ -12,7 +12,12 @@ namespace Microsoft.CodeAnalysis.CSharp.Diagnostics
[ExportLanguageService(typeof(IAnalyzerDriverService), LanguageNames.CSharp), Shared]
internal sealed class CSharpAnalyzerDriverService : IAnalyzerDriverService
{
public void ComputeDeclarationsInSpan(SemanticModel model, TextSpan span, bool getSymbol, List<DeclarationInfo> builder, CancellationToken cancellationToken)
public void ComputeDeclarationsInSpan(
SemanticModel model,
TextSpan span,
bool getSymbol,
ArrayBuilder<DeclarationInfo> builder,
CancellationToken cancellationToken)
{
CSharpDeclarationComputer.ComputeDeclarationsInSpan(model, span, getSymbol, builder, cancellationToken);
}
......
......@@ -6,7 +6,6 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.PooledObjects;
......@@ -224,9 +223,11 @@ private async Task<SuppressionTargetInfo> GetSuppressionTargetInfoAsync(Document
// targetMemberNode could be a declaration node with multiple decls (e.g. field declaration defining multiple variables).
// Let us compute all the declarations intersecting the span.
var decls = new List<DeclarationInfo>();
analyzerDriverService.ComputeDeclarationsInSpan(semanticModel, span, true, decls, cancellationToken);
if (decls.Any())
var declsBuilder = ArrayBuilder<DeclarationInfo>.GetInstance();
analyzerDriverService.ComputeDeclarationsInSpan(semanticModel, span, true, declsBuilder, cancellationToken);
var decls = declsBuilder.ToImmutableAndFree();
if (!decls.IsEmpty)
{
var containedDecls = decls.Where(d => span.Contains(d.DeclaredNode.Span));
if (containedDecls.Count() == 1)
......
// 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.Collections.Generic;
using System.Threading;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Diagnostics
......@@ -18,6 +18,6 @@ internal interface IAnalyzerDriverService : ILanguageService
/// If false, then <see cref="DeclarationInfo.DeclaredSymbol"/> is always null.</param>
/// <param name="builder">Builder to add computed declarations.</param>
/// <param name="cancellationToken">Cancellation token.</param>
void ComputeDeclarationsInSpan(SemanticModel model, TextSpan span, bool getSymbol, List<DeclarationInfo> builder, CancellationToken cancellationToken);
void ComputeDeclarationsInSpan(SemanticModel model, TextSpan span, bool getSymbol, ArrayBuilder<DeclarationInfo> builder, CancellationToken cancellationToken);
}
}
......@@ -4,6 +4,7 @@ Imports System.Composition
Imports System.Threading
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text
Namespace Microsoft.CodeAnalysis.VisualBasic.Diagnostics
......@@ -11,7 +12,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Diagnostics
Friend NotInheritable Class VisualBasicAnalyzerDriverService
Implements IAnalyzerDriverService
Public Sub ComputeDeclarationsInSpan(model As SemanticModel, span As TextSpan, getSymbol As Boolean, builder As List(Of DeclarationInfo), cancellationToken As CancellationToken) Implements IAnalyzerDriverService.ComputeDeclarationsInSpan
Public Sub ComputeDeclarationsInSpan(model As SemanticModel,
span As TextSpan,
getSymbol As Boolean,
builder As ArrayBuilder(Of DeclarationInfo),
cancellationToken As CancellationToken) Implements IAnalyzerDriverService.ComputeDeclarationsInSpan
VisualBasicDeclarationComputer.ComputeDeclarationsInSpan(model, span, getSymbol, builder, cancellationToken)
End Sub
End Class
......
......@@ -174,11 +174,11 @@ internal static void VerifyOperationTree(this Compilation compilation, string sy
SyntaxTree tree = compilation.SyntaxTrees.First();
SyntaxNode root = tree.GetRoot();
SemanticModel model = compilation.GetSemanticModel(tree);
var declarations = new List<DeclarationInfo>();
model.ComputeDeclarationsInNode(root, getSymbol: true, builder: declarations, cancellationToken: CancellationToken.None);
var declarationsBuilder = ArrayBuilder<DeclarationInfo>.GetInstance();
model.ComputeDeclarationsInNode(root, getSymbol: true, builder: declarationsBuilder, cancellationToken: CancellationToken.None);
var actualTextBuilder = new StringBuilder();
foreach (DeclarationInfo declaration in declarations.Where(d => d.DeclaredSymbol != null).OrderBy(d => d.DeclaredSymbol.ToTestDisplayString()))
foreach (DeclarationInfo declaration in declarationsBuilder.ToArrayAndFree().Where(d => d.DeclaredSymbol != null).OrderBy(d => d.DeclaredSymbol.ToTestDisplayString()))
{
if (!CanHaveExecutableCodeBlock(declaration.DeclaredSymbol))
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册