提交 828a1b16 编写于 作者: C Cyrus Najmabadi

Merge remote-tracking branch 'upstream/master' into waitAndGetResult

......@@ -5,6 +5,7 @@
<NuGetToolPath Condition="">$(ProjectDir)nuget.exe</NuGetToolPath>
<ToolsetPackagesDir>$(ProjectDir)build\ToolsetPackages\</ToolsetPackagesDir>
<ToolsetPackagesSemaphore>$(ToolsetPackagesDir)toolsetpackages.semaphore</ToolsetPackagesSemaphore>
<NuGetPackageRoot Condition="'$(NuGetPackageRoot)' == ''">$(NUGET_PACKAGES)</NuGetPackageRoot> <!-- Respect environment variable if set -->
<NuGetPackageRoot Condition="'$(NuGetPackageRoot)' == '' and
'$(OS)' == 'Windows_NT'">$(UserProfile)\.nuget\packages</NuGetPackageRoot>
<NuGetPackageRoot Condition="'$(NuGetPackageRoot)' == '' and
......@@ -37,10 +38,6 @@
<Import Project="$(MSBuildExtensionsPath)\Microsoft\NuGet\Microsoft.NuGet.props"
Condition="'$(OS)' != 'Windows_NT'" />
<PropertyGroup>
<NuGetPackageRoot Condition="'$(NuGetPackageRoot)' == ''">$(UserProfile)\.nuget\packages</NuGetPackageRoot>
</PropertyGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
</PropertyGroup>
......
......@@ -185,6 +185,8 @@
<Compile Include="InternalUtilities\CompilerOptionParseUtilities.cs" />
<Compile Include="InternalUtilities\ImmutableArrayInterop.cs" />
<Compile Include="InternalUtilities\ReflectionUtilities.cs" />
<Compile Include="InternalUtilities\SemaphoreSlimExtensions.cs" />
<Compile Include="InternalUtilities\SemaphoreSlimFactory.cs" />
<Compile Include="CorLightup.cs" />
<Compile Include="Desktop\AssemblyPortabilityPolicy.cs" />
<Compile Include="Desktop\AssemblyVersion.cs" />
......
......@@ -4,6 +4,8 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics.Telemetry;
using Roslyn.Utilities;
......@@ -16,7 +18,7 @@ internal partial class AnalysisState
{
private class PerAnalyzerState
{
private readonly object _gate = new object();
private readonly SemaphoreSlim _gate = new SemaphoreSlim(initialCount: 1);
private readonly Dictionary<CompilationEvent, AnalyzerStateData> _pendingEvents = new Dictionary<CompilationEvent, AnalyzerStateData>();
private readonly Dictionary<ISymbol, AnalyzerStateData> _pendingSymbols = new Dictionary<ISymbol, AnalyzerStateData>();
private readonly Dictionary<SyntaxNode, DeclarationAnalyzerStateData> _pendingDeclarations = new Dictionary<SyntaxNode, DeclarationAnalyzerStateData>();
......@@ -33,35 +35,36 @@ public PerAnalyzerState(ObjectPool<AnalyzerStateData> analyzerStateDataPool, Obj
public IEnumerable<CompilationEvent> PendingEvents_NoLock => _pendingEvents.Keys;
public bool HasPendingSyntaxAnalysis(SyntaxTree treeOpt)
public async Task<bool> HasPendingSyntaxAnalysisAsync(SyntaxTree treeOpt, CancellationToken cancellationToken)
{
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
return _lazyPendingSyntaxAnalysisTrees != null &&
(treeOpt != null ? _lazyPendingSyntaxAnalysisTrees.ContainsKey(treeOpt) : _lazyPendingSyntaxAnalysisTrees.Count > 0);
}
}
public bool HasPendingSymbolAnalysis(ISymbol symbol)
public async Task<bool> HasPendingSymbolAnalysisAsync(ISymbol symbol, CancellationToken cancellationToken)
{
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
return _pendingSymbols.ContainsKey(symbol);
}
}
private bool TryStartProcessingEntity<TAnalysisEntity, TAnalyzerStateData>(TAnalysisEntity analysisEntity, Dictionary<TAnalysisEntity, TAnalyzerStateData> pendingEntities, ObjectPool<TAnalyzerStateData> pool, out TAnalyzerStateData newState)
private async Task<TAnalyzerStateData> TryStartProcessingEntityAsync<TAnalysisEntity, TAnalyzerStateData>(TAnalysisEntity analysisEntity, Dictionary<TAnalysisEntity, TAnalyzerStateData> pendingEntities, ObjectPool<TAnalyzerStateData> pool, CancellationToken cancellationToken)
where TAnalyzerStateData : AnalyzerStateData, new()
{
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
return TryStartProcessingEntity_NoLock(analysisEntity, pendingEntities, pool, out newState);
return TryStartProcessingEntity_NoLock(analysisEntity, pendingEntities, pool);
}
}
private static bool TryStartProcessingEntity_NoLock<TAnalysisEntity, TAnalyzerStateData>(TAnalysisEntity analysisEntity, Dictionary<TAnalysisEntity, TAnalyzerStateData> pendingEntities, ObjectPool<TAnalyzerStateData> pool, out TAnalyzerStateData state)
private static TAnalyzerStateData TryStartProcessingEntity_NoLock<TAnalysisEntity, TAnalyzerStateData>(TAnalysisEntity analysisEntity, Dictionary<TAnalysisEntity, TAnalyzerStateData> pendingEntities, ObjectPool<TAnalyzerStateData> pool)
where TAnalyzerStateData : AnalyzerStateData
{
TAnalyzerStateData state;
if (pendingEntities.TryGetValue(analysisEntity, out state) &&
(state == null || state.StateKind == StateKind.ReadyToProcess))
{
......@@ -73,17 +76,16 @@ public bool HasPendingSymbolAnalysis(ISymbol symbol)
state.SetStateKind(StateKind.InProcess);
Debug.Assert(state.StateKind == StateKind.InProcess);
pendingEntities[analysisEntity] = state;
return true;
return state;
}
state = null;
return false;
return null;
}
private void MarkEntityProcessed<TAnalysisEntity, TAnalyzerStateData>(TAnalysisEntity analysisEntity, Dictionary<TAnalysisEntity, TAnalyzerStateData> pendingEntities, ObjectPool<TAnalyzerStateData> pool)
private async Task MarkEntityProcessedAsync<TAnalysisEntity, TAnalyzerStateData>(TAnalysisEntity analysisEntity, Dictionary<TAnalysisEntity, TAnalyzerStateData> pendingEntities, ObjectPool<TAnalyzerStateData> pool, CancellationToken cancellationToken)
where TAnalyzerStateData : AnalyzerStateData
{
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
MarkEntityProcessed_NoLock(analysisEntity, pendingEntities, pool);
}
......@@ -104,10 +106,10 @@ public bool HasPendingSymbolAnalysis(ISymbol symbol)
}
}
private bool IsEntityFullyProcessed<TAnalysisEntity, TAnalyzerStateData>(TAnalysisEntity analysisEntity, Dictionary<TAnalysisEntity, TAnalyzerStateData> pendingEntities)
private async Task<bool> IsEntityFullyProcessedAsync<TAnalysisEntity, TAnalyzerStateData>(TAnalysisEntity analysisEntity, Dictionary<TAnalysisEntity, TAnalyzerStateData> pendingEntities, CancellationToken cancellationToken)
where TAnalyzerStateData : AnalyzerStateData
{
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
return IsEntityFullyProcessed_NoLock(analysisEntity, pendingEntities);
}
......@@ -119,58 +121,58 @@ public bool HasPendingSymbolAnalysis(ISymbol symbol)
return !pendingEntities.ContainsKey(analysisEntity);
}
public bool TryStartProcessingEvent(CompilationEvent compilationEvent, out AnalyzerStateData state)
public Task<AnalyzerStateData> TryStartProcessingEventAsync(CompilationEvent compilationEvent, CancellationToken cancellationToken)
{
return TryStartProcessingEntity(compilationEvent, _pendingEvents, _analyzerStateDataPool, out state);
return TryStartProcessingEntityAsync(compilationEvent, _pendingEvents, _analyzerStateDataPool, cancellationToken);
}
public void MarkEventComplete(CompilationEvent compilationEvent)
public Task MarkEventCompleteAsync(CompilationEvent compilationEvent, CancellationToken cancellationToken)
{
MarkEntityProcessed(compilationEvent, _pendingEvents, _analyzerStateDataPool);
return MarkEntityProcessedAsync(compilationEvent, _pendingEvents, _analyzerStateDataPool, cancellationToken);
}
public bool TryStartAnalyzingSymbol(ISymbol symbol, out AnalyzerStateData state)
public Task<AnalyzerStateData> TryStartAnalyzingSymbolAsync(ISymbol symbol, CancellationToken cancellationToken)
{
return TryStartProcessingEntity(symbol, _pendingSymbols, _analyzerStateDataPool, out state);
return TryStartProcessingEntityAsync(symbol, _pendingSymbols, _analyzerStateDataPool, cancellationToken);
}
public void MarkSymbolComplete(ISymbol symbol)
public Task MarkSymbolCompleteAsync(ISymbol symbol, CancellationToken cancellationToken)
{
MarkEntityProcessed(symbol, _pendingSymbols, _analyzerStateDataPool);
return MarkEntityProcessedAsync(symbol, _pendingSymbols, _analyzerStateDataPool, cancellationToken);
}
public bool TryStartAnalyzingDeclaration(SyntaxReference decl, out DeclarationAnalyzerStateData state)
public Task<DeclarationAnalyzerStateData> TryStartAnalyzingDeclarationAsync(SyntaxReference decl, CancellationToken cancellationToken)
{
return TryStartProcessingEntity(decl.GetSyntax(), _pendingDeclarations, _declarationAnalyzerStateDataPool, out state);
return TryStartProcessingEntityAsync(decl.GetSyntax(), _pendingDeclarations, _declarationAnalyzerStateDataPool, cancellationToken);
}
public bool IsDeclarationComplete(SyntaxNode decl)
public Task<bool> IsDeclarationCompleteAsync(SyntaxNode decl, CancellationToken cancellationToken)
{
return IsEntityFullyProcessed(decl, _pendingDeclarations);
return IsEntityFullyProcessedAsync(decl, _pendingDeclarations, cancellationToken);
}
public void MarkDeclarationComplete(SyntaxReference decl)
public Task MarkDeclarationCompleteAsync(SyntaxReference decl, CancellationToken cancellationToken)
{
MarkEntityProcessed(decl.GetSyntax(), _pendingDeclarations, _declarationAnalyzerStateDataPool);
return MarkEntityProcessedAsync(decl.GetSyntax(), _pendingDeclarations, _declarationAnalyzerStateDataPool, cancellationToken);
}
public bool TryStartSyntaxAnalysis(SyntaxTree tree, out AnalyzerStateData state)
public Task<AnalyzerStateData> TryStartSyntaxAnalysisAsync(SyntaxTree tree, CancellationToken cancellationToken)
{
Debug.Assert(_lazyPendingSyntaxAnalysisTrees != null);
return TryStartProcessingEntity(tree, _lazyPendingSyntaxAnalysisTrees, _analyzerStateDataPool, out state);
return TryStartProcessingEntityAsync(tree, _lazyPendingSyntaxAnalysisTrees, _analyzerStateDataPool, cancellationToken);
}
public void MarkSyntaxAnalysisComplete(SyntaxTree tree)
public async Task MarkSyntaxAnalysisCompleteAsync(SyntaxTree tree, CancellationToken cancellationToken)
{
if (_lazyPendingSyntaxAnalysisTrees != null)
{
MarkEntityProcessed(tree, _lazyPendingSyntaxAnalysisTrees, _analyzerStateDataPool);
await MarkEntityProcessedAsync(tree, _lazyPendingSyntaxAnalysisTrees, _analyzerStateDataPool, cancellationToken).ConfigureAwait(false);
}
}
public void MarkDeclarationsComplete(ImmutableArray<SyntaxReference> declarations)
public async Task MarkDeclarationsCompleteAsync(ImmutableArray<SyntaxReference> declarations, CancellationToken cancellationToken)
{
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
foreach (var syntaxRef in declarations)
{
......@@ -179,9 +181,9 @@ public void MarkDeclarationsComplete(ImmutableArray<SyntaxReference> declaration
}
}
public void OnCompilationEventGenerated(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts)
public async Task OnCompilationEventGeneratedAsync(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts, CancellationToken cancellationToken)
{
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
var symbolEvent = compilationEvent as SymbolDeclaredCompilationEvent;
if (symbolEvent != null)
......@@ -235,14 +237,14 @@ public void OnCompilationEventGenerated(CompilationEvent compilationEvent, Analy
}
}
public bool IsEventAnalyzed(CompilationEvent compilationEvent)
public Task<bool> IsEventAnalyzedAsync(CompilationEvent compilationEvent, CancellationToken cancellationToken)
{
return IsEntityFullyProcessed(compilationEvent, _pendingEvents);
return IsEntityFullyProcessedAsync(compilationEvent, _pendingEvents, cancellationToken);
}
public void OnSymbolDeclaredEventProcessed(SymbolDeclaredCompilationEvent symbolDeclaredEvent)
public async Task OnSymbolDeclaredEventProcessedAsync(SymbolDeclaredCompilationEvent symbolDeclaredEvent, CancellationToken cancellationToken)
{
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
OnSymbolDeclaredEventProcessed_NoLock(symbolDeclaredEvent);
}
......
......@@ -18,7 +18,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics
/// </summary>
internal partial class AnalysisState
{
private readonly object _gate;
private readonly SemaphoreSlim _gate;
/// <summary>
/// Per-analyzer analysis state map.
......@@ -60,7 +60,7 @@ internal partial class AnalysisState
public AnalysisState(ImmutableArray<DiagnosticAnalyzer> analyzers)
{
_gate = new object();
_gate = new SemaphoreSlim(initialCount: 1);
_analyzerStateMap = CreateAnalyzerStateMap(analyzers, out _analyzerStates);
_pendingSourceEvents = new Dictionary<SyntaxTree, HashSet<CompilationEvent>>();
_pendingNonSourceEvents = new HashSet<CompilationEvent>();
......@@ -100,13 +100,13 @@ public async Task OnCompilationEventsGeneratedAsync(ImmutableArray<CompilationEv
{
await EnsureAnalyzerActionCountsInitializedAsync(driver, cancellationToken).ConfigureAwait(false);
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
OnCompilationEventsGenerated_NoLock(compilationEvents, driver, cancellationToken);
await OnCompilationEventsGenerated_NoLockAsync(compilationEvents, driver, cancellationToken).ConfigureAwait(false);
}
}
private void OnCompilationEventsGenerated_NoLock(ImmutableArray<CompilationEvent> compilationEvents, AnalyzerDriver driver, CancellationToken cancellationToken)
private async Task OnCompilationEventsGenerated_NoLockAsync(ImmutableArray<CompilationEvent> compilationEvents, AnalyzerDriver driver, CancellationToken cancellationToken)
{
Debug.Assert(_lazyAnalyzerActionCountsMap != null);
......@@ -126,7 +126,7 @@ private void OnCompilationEventsGenerated_NoLock(ImmutableArray<CompilationEvent
if (HasActionsForEvent(compilationEvent, actionCounts))
{
_pooledEventsWithAnyActionsSet.Add(compilationEvent);
analyzerState.OnCompilationEventGenerated(compilationEvent, actionCounts);
await analyzerState.OnCompilationEventGeneratedAsync(compilationEvent, actionCounts, cancellationToken).ConfigureAwait(false);
}
}
}
......@@ -284,12 +284,12 @@ private static bool HasActionsForEvent(CompilationEvent compilationEvent, Analyz
}
}
private void OnSymbolDeclaredEventProcessed(SymbolDeclaredCompilationEvent symbolDeclaredEvent, ImmutableArray<DiagnosticAnalyzer> analyzers)
private async Task OnSymbolDeclaredEventProcessedAsync(SymbolDeclaredCompilationEvent symbolDeclaredEvent, ImmutableArray<DiagnosticAnalyzer> analyzers, CancellationToken cancellationToken)
{
foreach (var analyzer in analyzers)
{
var analyzerState = GetAnalyzerState(analyzer);
analyzerState.OnSymbolDeclaredEventProcessed(symbolDeclaredEvent);
await analyzerState.OnSymbolDeclaredEventProcessedAsync(symbolDeclaredEvent, cancellationToken).ConfigureAwait(false);
}
}
......@@ -297,26 +297,27 @@ private void OnSymbolDeclaredEventProcessed(SymbolDeclaredCompilationEvent symbo
/// Invoke this method at completion of event processing for the given analysis scope.
/// It updates the analysis state of this event for each analyzer and if the event has been fully processed for all analyzers, then removes it from our event cache.
/// </summary>
public void OnCompilationEventProcessed(CompilationEvent compilationEvent, AnalysisScope analysisScope)
public async Task OnCompilationEventProcessedAsync(CompilationEvent compilationEvent, AnalysisScope analysisScope, CancellationToken cancellationToken)
{
// Analyze if the symbol and all its declaring syntax references are analyzed.
var symbolDeclaredEvent = compilationEvent as SymbolDeclaredCompilationEvent;
if (symbolDeclaredEvent != null)
{
OnSymbolDeclaredEventProcessed(symbolDeclaredEvent, analysisScope.Analyzers);
await OnSymbolDeclaredEventProcessedAsync(symbolDeclaredEvent, analysisScope.Analyzers, cancellationToken).ConfigureAwait(false);
}
// Check if event is fully analyzed for all analyzers.
foreach (var analyzerState in _analyzerStates)
{
if (!analyzerState.IsEventAnalyzed(compilationEvent))
var eventAnalyzed = await analyzerState.IsEventAnalyzedAsync(compilationEvent, cancellationToken).ConfigureAwait(false);
if (!eventAnalyzed)
{
return;
}
}
// Remove the event from event map.
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
UpdateEventsMap_NoLock(compilationEvent, add: false);
}
......@@ -330,9 +331,9 @@ public void OnCompilationEventProcessed(CompilationEvent compilationEvent, Analy
/// <summary>
/// Gets pending events for given set of analyzers for the given syntax tree.
/// </summary>
public ImmutableArray<CompilationEvent> GetPendingEvents(ImmutableArray<DiagnosticAnalyzer> analyzers, SyntaxTree tree)
public async Task<ImmutableArray<CompilationEvent>> GetPendingEventsAsync(ImmutableArray<DiagnosticAnalyzer> analyzers, SyntaxTree tree, CancellationToken cancellationToken)
{
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
return GetPendingEvents_NoLock(analyzers, tree);
}
......@@ -389,9 +390,10 @@ private ImmutableArray<CompilationEvent> GetPendingEvents_NoLock(ImmutableArray<
/// <param name="analyzers"></param>
/// <param name="includeSourceEvents">Indicates if source events (symbol declared, compilation unit completed event) should be included.</param>
/// <param name="includeNonSourceEvents">Indicates if compilation wide events (compilation started and completed event) should be included.</param>
public ImmutableArray<CompilationEvent> GetPendingEvents(ImmutableArray<DiagnosticAnalyzer> analyzers, bool includeSourceEvents, bool includeNonSourceEvents)
/// <param name="cancellationToken">Cancellation token.</param>
public async Task<ImmutableArray<CompilationEvent>> GetPendingEventsAsync(ImmutableArray<DiagnosticAnalyzer> analyzers, bool includeSourceEvents, bool includeNonSourceEvents, CancellationToken cancellationToken)
{
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
return GetPendingEvents_NoLock(analyzers, includeSourceEvents, includeNonSourceEvents);
}
......@@ -451,7 +453,7 @@ private void Free(HashSet<CompilationEvent> events)
/// <summary>
/// Returns true if we have any pending syntax analysis for given analysis scope.
/// </summary>
public bool HasPendingSyntaxAnalysis(AnalysisScope analysisScope)
public async Task<bool> HasPendingSyntaxAnalysisAsync(AnalysisScope analysisScope, CancellationToken cancellationToken)
{
if (analysisScope.IsTreeAnalysis && !analysisScope.IsSyntaxOnlyTreeAnalysis)
{
......@@ -461,7 +463,7 @@ public bool HasPendingSyntaxAnalysis(AnalysisScope analysisScope)
foreach (var analyzer in analysisScope.Analyzers)
{
var analyzerState = GetAnalyzerState(analyzer);
if (analyzerState.HasPendingSyntaxAnalysis(analysisScope.FilterTreeOpt))
if (await analyzerState.HasPendingSyntaxAnalysisAsync(analysisScope.FilterTreeOpt, cancellationToken).ConfigureAwait(false))
{
return true;
}
......@@ -473,11 +475,11 @@ public bool HasPendingSyntaxAnalysis(AnalysisScope analysisScope)
/// <summary>
/// Returns true if we have any pending symbol analysis for given analysis scope.
/// </summary>
public bool HasPendingSymbolAnalysis(AnalysisScope analysisScope)
public async Task<bool> HasPendingSymbolAnalysisAsync(AnalysisScope analysisScope, CancellationToken cancellationToken)
{
Debug.Assert(analysisScope.FilterTreeOpt != null);
var symbolDeclaredEvents = GetPendingSymbolDeclaredEvents(analysisScope.FilterTreeOpt);
var symbolDeclaredEvents = await GetPendingSymbolDeclaredEventsAsync(analysisScope.FilterTreeOpt, cancellationToken).ConfigureAwait(false);
foreach (var symbolDeclaredEvent in symbolDeclaredEvents)
{
if (analysisScope.ShouldAnalyze(symbolDeclaredEvent.Symbol))
......@@ -485,7 +487,7 @@ public bool HasPendingSymbolAnalysis(AnalysisScope analysisScope)
foreach (var analyzer in analysisScope.Analyzers)
{
var analyzerState = GetAnalyzerState(analyzer);
if (analyzerState.HasPendingSymbolAnalysis(symbolDeclaredEvent.Symbol))
if (await analyzerState.HasPendingSymbolAnalysisAsync(symbolDeclaredEvent.Symbol, cancellationToken).ConfigureAwait(false))
{
return true;
}
......@@ -496,11 +498,11 @@ public bool HasPendingSymbolAnalysis(AnalysisScope analysisScope)
return false;
}
private ImmutableArray<SymbolDeclaredCompilationEvent> GetPendingSymbolDeclaredEvents(SyntaxTree tree)
private async Task<ImmutableArray<SymbolDeclaredCompilationEvent>> GetPendingSymbolDeclaredEventsAsync(SyntaxTree tree, CancellationToken cancellationToken)
{
Debug.Assert(tree != null);
lock (_gate)
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
HashSet<CompilationEvent> compilationEvents;
if (!_pendingSourceEvents.TryGetValue(tree, out compilationEvents))
......@@ -516,62 +518,63 @@ private ImmutableArray<SymbolDeclaredCompilationEvent> GetPendingSymbolDeclaredE
/// Attempts to start processing a compilation event for the given analyzer.
/// </summary>
/// <returns>
/// Returns false if the event has already been processed for the analyzer OR is currently being processed by another task.
/// If true, then it returns a non-null <paramref name="state"/> representing partial analysis state for the given event for the given analyzer.
/// Returns null if the event has already been processed for the analyzer OR is currently being processed by another task.
/// Otherwise, returns a non-null state representing partial analysis state for the given event for the given analyzer.
/// </returns>
public bool TryStartProcessingEvent(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer, out AnalyzerStateData state)
public Task<AnalyzerStateData> TryStartProcessingEventAsync(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
{
return GetAnalyzerState(analyzer).TryStartProcessingEvent(compilationEvent, out state);
return GetAnalyzerState(analyzer).TryStartProcessingEventAsync(compilationEvent, cancellationToken);
}
/// <summary>
/// Marks the given event as fully analyzed for the given analyzer.
/// </summary>
public void MarkEventComplete(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer)
public Task MarkEventCompleteAsync(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
{
GetAnalyzerState(analyzer).MarkEventComplete(compilationEvent);
return GetAnalyzerState(analyzer).MarkEventCompleteAsync(compilationEvent, cancellationToken);
}
/// <summary>
/// Attempts to start processing a symbol for the given analyzer's symbol actions.
/// </summary>
/// <returns>
/// Returns false if the symbol has already been processed for the analyzer OR is currently being processed by another task.
/// If true, then it returns a non-null <paramref name="state"/> representing partial analysis state for the given symbol for the given analyzer.
/// Returns null if the symbol has already been processed for the analyzer OR is currently being processed by another task.
/// Otherwise, returns a non-null state representing partial analysis state for the given symbol for the given analyzer.
/// </returns>
public bool TryStartAnalyzingSymbol(ISymbol symbol, DiagnosticAnalyzer analyzer, out AnalyzerStateData state)
public Task<AnalyzerStateData> TryStartAnalyzingSymbolAsync(ISymbol symbol, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
{
return GetAnalyzerState(analyzer).TryStartAnalyzingSymbol(symbol, out state);
return GetAnalyzerState(analyzer).TryStartAnalyzingSymbolAsync(symbol, cancellationToken);
}
/// <summary>
/// Marks the given symbol as fully analyzed for the given analyzer.
/// </summary>
public void MarkSymbolComplete(ISymbol symbol, DiagnosticAnalyzer analyzer)
public Task MarkSymbolCompleteAsync(ISymbol symbol, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
{
GetAnalyzerState(analyzer).MarkSymbolComplete(symbol);
return GetAnalyzerState(analyzer).MarkSymbolCompleteAsync(symbol, cancellationToken);
}
/// <summary>
/// Attempts to start processing a symbol declaration for the given analyzer's syntax node and code block actions.
/// </summary>
/// <returns>
/// Returns false if the declaration has already been processed for the analyzer OR is currently being processed by another task.
/// If true, then it returns a non-null <paramref name="state"/> representing partial analysis state for the given declaration for the given analyzer.
/// Returns null if the declaration has already been processed for the analyzer OR is currently being processed by another task.
/// Otherwise, returns a non-null state representing partial analysis state for the given declaration for the given analyzer.
/// </returns>
public bool TryStartAnalyzingDeclaration(SyntaxReference decl, DiagnosticAnalyzer analyzer, out DeclarationAnalyzerStateData state)
public Task<DeclarationAnalyzerStateData> TryStartAnalyzingDeclarationAsync(SyntaxReference decl, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
{
return GetAnalyzerState(analyzer).TryStartAnalyzingDeclaration(decl, out state);
return GetAnalyzerState(analyzer).TryStartAnalyzingDeclarationAsync(decl, cancellationToken);
}
/// <summary>
/// True if the given symbol declaration is fully analyzed.
/// Returns true if the given symbol declaration is fully analyzed.
/// </summary>
public bool IsDeclarationComplete(SyntaxNode decl)
public async Task<bool> IsDeclarationCompleteAsync(SyntaxNode decl, CancellationToken cancellationToken)
{
foreach (var analyzerState in _analyzerStates)
{
if (!analyzerState.IsDeclarationComplete(decl))
var declarationComplete = await analyzerState.IsDeclarationCompleteAsync(decl, cancellationToken).ConfigureAwait(false);
if (!declarationComplete)
{
return false;
}
......@@ -583,19 +586,19 @@ public bool IsDeclarationComplete(SyntaxNode decl)
/// <summary>
/// Marks the given symbol declaration as fully analyzed for the given analyzer.
/// </summary>
public void MarkDeclarationComplete(SyntaxReference decl, DiagnosticAnalyzer analyzer)
public Task MarkDeclarationCompleteAsync(SyntaxReference decl, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
{
GetAnalyzerState(analyzer).MarkDeclarationComplete(decl);
return GetAnalyzerState(analyzer).MarkDeclarationCompleteAsync(decl, cancellationToken);
}
/// <summary>
/// Marks all the symbol declarations for the given symbol as fully analyzed for all the given analyzers.
/// </summary>
public void MarkDeclarationsComplete(ImmutableArray<SyntaxReference> declarations, IEnumerable<DiagnosticAnalyzer> analyzers)
public async Task MarkDeclarationsCompleteAsync(ImmutableArray<SyntaxReference> declarations, IEnumerable<DiagnosticAnalyzer> analyzers, CancellationToken cancellationToken)
{
foreach (var analyzer in analyzers)
{
GetAnalyzerState(analyzer).MarkDeclarationsComplete(declarations);
await GetAnalyzerState(analyzer).MarkDeclarationsCompleteAsync(declarations, cancellationToken).ConfigureAwait(false);
}
}
......@@ -603,20 +606,20 @@ public void MarkDeclarationsComplete(ImmutableArray<SyntaxReference> declaration
/// Attempts to start processing a syntax tree for the given analyzer's syntax tree actions.
/// </summary>
/// <returns>
/// Returns false if the tree has already been processed for the analyzer OR is currently being processed by another task.
/// If true, then it returns a non-null <paramref name="state"/> representing partial syntax analysis state for the given tree for the given analyzer.
/// Returns null if the tree has already been processed for the analyzer OR is currently being processed by another task.
/// Otherwise, returns a non-null state representing partial syntax analysis state for the given tree for the given analyzer.
/// </returns>
public bool TryStartSyntaxAnalysis(SyntaxTree tree, DiagnosticAnalyzer analyzer, out AnalyzerStateData state)
public Task<AnalyzerStateData> TryStartSyntaxAnalysisAsync(SyntaxTree tree, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
{
return GetAnalyzerState(analyzer).TryStartSyntaxAnalysis(tree, out state);
return GetAnalyzerState(analyzer).TryStartSyntaxAnalysisAsync(tree, cancellationToken);
}
/// <summary>
/// Marks the given tree as fully syntactically analyzed for the given analyzer.
/// </summary>
public void MarkSyntaxAnalysisComplete(SyntaxTree tree, DiagnosticAnalyzer analyzer)
public Task MarkSyntaxAnalysisCompleteAsync(SyntaxTree tree, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
{
GetAnalyzerState(analyzer).MarkSyntaxAnalysisComplete(tree);
return GetAnalyzerState(analyzer).MarkSyntaxAnalysisCompleteAsync(tree, cancellationToken);
}
}
}
......@@ -55,10 +55,10 @@ internal partial class AnalyzerManager
{
Func<Compilation, Task<HostCompilationStartAnalysisScope>> getTask = comp =>
{
return Task.Run(() =>
return Task.Run(async() =>
{
var compilationAnalysisScope = new HostCompilationStartAnalysisScope(sessionScope);
analyzerExecutor.ExecuteCompilationStartActions(sessionScope.CompilationStartActions, compilationAnalysisScope);
await analyzerExecutor.ExecuteCompilationStartActionsAsync(sessionScope.CompilationStartActions, compilationAnalysisScope).ConfigureAwait(false);
return compilationAnalysisScope;
}, analyzerExecutor.CancellationToken);
};
......@@ -100,10 +100,10 @@ internal partial class AnalyzerManager
{
Func<DiagnosticAnalyzer, Task<HostSessionStartAnalysisScope>> getTask = a =>
{
return Task.Run(() =>
return Task.Run(async() =>
{
var sessionScope = new HostSessionStartAnalysisScope();
analyzerExecutor.ExecuteInitializeMethod(a, sessionScope);
await analyzerExecutor.ExecuteInitializeMethodAsync(a, sessionScope).ConfigureAwait(false);
return sessionScope;
}, analyzerExecutor.CancellationToken);
};
......@@ -160,14 +160,14 @@ public async Task<AnalyzerActions> GetAnalyzerActionsAsync(DiagnosticAnalyzer an
var supportedDiagnostics = ImmutableArray<DiagnosticDescriptor>.Empty;
// Catch Exception from analyzer.SupportedDiagnostics
analyzerExecutor.ExecuteAndCatchIfThrows(analyzer, () =>
analyzerExecutor.ExecuteAndCatchIfThrowsAsync(analyzer, () =>
{
var supportedDiagnosticsLocal = analyzer.SupportedDiagnostics;
if (!supportedDiagnosticsLocal.IsDefaultOrEmpty)
{
supportedDiagnostics = supportedDiagnosticsLocal;
}
});
}).Wait(analyzerExecutor.CancellationToken);
EventHandler<Exception> handler = null;
Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = analyzerExecutor.OnAnalyzerException;
......
......@@ -68,7 +68,7 @@ public class CompilationWithAnalyzers
/// Pool of event queues to serve each diagnostics request.
/// </summary>
private static readonly ObjectPool<AsyncQueue<CompilationEvent>> s_eventQueuePool = new ObjectPool<AsyncQueue<CompilationEvent>>(() => new AsyncQueue<CompilationEvent>());
private static readonly AsyncQueue<CompilationEvent> s_EmptyEventQueue = new AsyncQueue<CompilationEvent>();
private static readonly Task<AsyncQueue<CompilationEvent>> s_EmptyEventQueueTask = Task.FromResult(new AsyncQueue<CompilationEvent>());
/// <summary>
......@@ -362,11 +362,11 @@ private async Task<ImmutableArray<Diagnostic>> GetAnalyzerDiagnosticsCoreAsync(I
}
};
Func<AsyncQueue<CompilationEvent>> getEventQueue = () =>
GetPendingEvents(analyzers, includeSourceEvents, includeNonSourceEvents);
Func<Task<AsyncQueue<CompilationEvent>>> getEventQueueTask = () =>
GetPendingEventsAsync(analyzers, includeSourceEvents, includeNonSourceEvents, cancellationToken);
// Compute the analyzer diagnostics for the given analysis scope.
await ComputeAnalyzerDiagnosticsAsync(analysisScope, generateCompilationEvents, getEventQueue, newTaskToken: 0, cancellationToken: cancellationToken).ConfigureAwait(false);
await ComputeAnalyzerDiagnosticsAsync(analysisScope, generateCompilationEvents, getEventQueueTask, newTaskToken: 0, cancellationToken: cancellationToken).ConfigureAwait(false);
// Return computed analyzer diagnostics for the given analysis scope.
var analyzerDiagnostics = _analysisResult.GetDiagnostics(analysisScope, getLocalDiagnostics: includeSourceEvents, getNonLocalDiagnostics: includeNonSourceEvents);
......@@ -420,7 +420,7 @@ private async Task<ImmutableArray<Diagnostic>> GetAnalyzerSyntaxDiagnosticsCoreA
var analysisScope = new AnalysisScope(analyzers, tree, filterSpan: null, syntaxAnalysis: true, concurrentAnalysis: _analysisOptions.ConcurrentAnalysis, categorizeDiagnostics: true);
Action generateCompilationEvents = null;
Func<AsyncQueue<CompilationEvent>> getEventQueue = () => s_EmptyEventQueue;
Func<Task<AsyncQueue<CompilationEvent>>> getEventQueue = () => s_EmptyEventQueueTask;
// Compute the analyzer diagnostics for the given analysis scope.
await ComputeAnalyzerDiagnosticsAsync(analysisScope, generateCompilationEvents, getEventQueue, taskToken, cancellationToken).ConfigureAwait(false);
......@@ -487,14 +487,15 @@ private async Task<ImmutableArray<Diagnostic>> GetAnalyzerSemanticDiagnosticsCor
Action generateCompilationEvents = () =>
AnalyzerDriver.GetOrCreateCachedSemanticModel(model.SyntaxTree, _compilation, cancellationToken);
Func<AsyncQueue<CompilationEvent>> getEventQueue = () => GetPendingEvents(analyzers, model.SyntaxTree);
Func<Task<AsyncQueue<CompilationEvent>>> getEventQueueTask = () => GetPendingEventsAsync(analyzers, model.SyntaxTree, cancellationToken);
// Compute the analyzer diagnostics for the given analysis scope.
// We need to loop till symbol analysis is complete for any partial symbols being processed for other tree diagnostic requests.
do
{
await ComputeAnalyzerDiagnosticsAsync(analysisScope, generateCompilationEvents, getEventQueue, taskToken, cancellationToken).ConfigureAwait(false);
} while (_analysisOptions.ConcurrentAnalysis && _analysisState.HasPendingSymbolAnalysis(analysisScope));
await ComputeAnalyzerDiagnosticsAsync(analysisScope, generateCompilationEvents, getEventQueueTask, taskToken, cancellationToken).ConfigureAwait(false);
} while (_analysisOptions.ConcurrentAnalysis &&
(await _analysisState.HasPendingSymbolAnalysisAsync(analysisScope, cancellationToken).ConfigureAwait(false)));
// Return computed analyzer diagnostics for the given analysis scope.
return _analysisResult.GetDiagnostics(analysisScope, getLocalDiagnostics: true, getNonLocalDiagnostics: false);
......@@ -505,7 +506,7 @@ private async Task<ImmutableArray<Diagnostic>> GetAnalyzerSemanticDiagnosticsCor
}
}
private async Task ComputeAnalyzerDiagnosticsAsync(AnalysisScope analysisScope, Action generateCompilationEventsOpt, Func<AsyncQueue<CompilationEvent>> getEventQueue, int newTaskToken, CancellationToken cancellationToken)
private async Task ComputeAnalyzerDiagnosticsAsync(AnalysisScope analysisScope, Action generateCompilationEventsOpt, Func<Task<AsyncQueue<CompilationEvent>>> getEventQueueTask, int newTaskToken, CancellationToken cancellationToken)
{
try
{
......@@ -552,11 +553,11 @@ private async Task ComputeAnalyzerDiagnosticsAsync(AnalysisScope analysisScope,
AsyncQueue<CompilationEvent> eventQueue = null;
try
{
// Get event queue with pending events to analyze.
eventQueue = getEventQueue();
// Get event queue with pending events to analyze.
eventQueue = await getEventQueueTask().ConfigureAwait(false);
// Execute analyzer driver on the given analysis scope with the given event queue.
await ComputeAnalyzerDiagnosticsCoreAsync(driver, eventQueue, analysisScope, cancellationToken: linkedCts.Token).ConfigureAwait(false);
// Execute analyzer driver on the given analysis scope with the given event queue.
await ComputeAnalyzerDiagnosticsCoreAsync(driver, eventQueue, analysisScope, cancellationToken: linkedCts.Token).ConfigureAwait(false);
}
finally
{
......@@ -568,7 +569,7 @@ private async Task ComputeAnalyzerDiagnosticsAsync(AnalysisScope analysisScope,
throw ExceptionUtilities.Unreachable;
}
},
linkedCts.Token),
linkedCts.Token),
cts);
// Wait for higher priority tree document tasks to complete.
......@@ -671,7 +672,7 @@ private async Task ComputeAnalyzerDiagnosticsCoreAsync(AnalyzerDriver driver, As
{
Debug.Assert(!driver.WhenInitializedTask.IsCanceled);
if (eventQueue.Count > 0 || _analysisState.HasPendingSyntaxAnalysis(analysisScope))
if (eventQueue.Count > 0 || (await _analysisState.HasPendingSyntaxAnalysisAsync(analysisScope, cancellationToken).ConfigureAwait(false)))
{
try
{
......@@ -891,13 +892,14 @@ private ImmutableArray<CompilationEvent> DequeueGeneratedCompilationEvents()
return builder.ToImmutable();
}
private AsyncQueue<CompilationEvent> GetPendingEvents(ImmutableArray<DiagnosticAnalyzer> analyzers, SyntaxTree tree)
private async Task<AsyncQueue<CompilationEvent>> GetPendingEventsAsync(ImmutableArray<DiagnosticAnalyzer> analyzers, SyntaxTree tree, CancellationToken cancellationToken)
{
var eventQueue = s_eventQueuePool.Allocate();
Debug.Assert(!eventQueue.IsCompleted);
Debug.Assert(eventQueue.Count == 0);
foreach (var compilationEvent in _analysisState.GetPendingEvents(analyzers, tree))
var pendingEvents = await _analysisState.GetPendingEventsAsync(analyzers, tree, cancellationToken).ConfigureAwait(false);
foreach (var compilationEvent in pendingEvents)
{
eventQueue.Enqueue(compilationEvent);
}
......@@ -905,7 +907,7 @@ private AsyncQueue<CompilationEvent> GetPendingEvents(ImmutableArray<DiagnosticA
return eventQueue;
}
private AsyncQueue<CompilationEvent> GetPendingEvents(ImmutableArray<DiagnosticAnalyzer> analyzers, bool includeSourceEvents, bool includeNonSourceEvents)
private async Task<AsyncQueue<CompilationEvent>> GetPendingEventsAsync(ImmutableArray<DiagnosticAnalyzer> analyzers, bool includeSourceEvents, bool includeNonSourceEvents, CancellationToken cancellationToken)
{
Debug.Assert(includeSourceEvents || includeNonSourceEvents);
......@@ -913,7 +915,8 @@ private AsyncQueue<CompilationEvent> GetPendingEvents(ImmutableArray<DiagnosticA
Debug.Assert(!eventQueue.IsCompleted);
Debug.Assert(eventQueue.Count == 0);
foreach (var compilationEvent in _analysisState.GetPendingEvents(analyzers, includeSourceEvents, includeNonSourceEvents))
var pendingEvents = await _analysisState.GetPendingEventsAsync(analyzers, includeSourceEvents, includeNonSourceEvents, cancellationToken).ConfigureAwait(false);
foreach (var compilationEvent in pendingEvents)
{
eventQueue.Enqueue(compilationEvent);
}
......@@ -923,7 +926,7 @@ private AsyncQueue<CompilationEvent> GetPendingEvents(ImmutableArray<DiagnosticA
private void FreeEventQueue(AsyncQueue<CompilationEvent> eventQueue)
{
if (eventQueue == null || ReferenceEquals(eventQueue, s_EmptyEventQueue))
if (eventQueue == null || ReferenceEquals(eventQueue, s_EmptyEventQueueTask.Result))
{
return;
}
......
......@@ -27,7 +27,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Squiggles
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.ErrorSquiggles)>
<WpfFact(Skip:="https://github.com/dotnet/roslyn/issues/6932"), Trait(Traits.Feature, Traits.Features.ErrorSquiggles)>
Public Async Sub ErrorTagGeneratedForSimpleError()
' Make sure we have errors from the tree
Dim spans = Await ProduceSquiggles("^")
......
......@@ -256,7 +256,7 @@ internal string GetAbsoluteSolutionPath(string path, string baseDirectory)
private class LoadState
{
private Dictionary<ProjectId, ProjectInfo> _projetIdToProjectInfoMap
private Dictionary<ProjectId, ProjectInfo> _projectIdToProjectInfoMap
= new Dictionary<ProjectId, ProjectInfo>();
private List<ProjectInfo> _projectInfoList
......@@ -275,13 +275,13 @@ public LoadState(IReadOnlyDictionary<string, ProjectId> projectPathToProjectIdMa
public void Add(ProjectInfo info)
{
_projetIdToProjectInfoMap.Add(info.Id, info);
_projectIdToProjectInfoMap.Add(info.Id, info);
_projectInfoList.Add(info);
}
public bool TryGetValue(ProjectId id, out ProjectInfo info)
{
return _projetIdToProjectInfoMap.TryGetValue(id, out info);
return _projectIdToProjectInfoMap.TryGetValue(id, out info);
}
public IReadOnlyList<ProjectInfo> Projects
......
......@@ -118,6 +118,12 @@
<Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\ReferenceEqualityComparer.cs">
<Link>InternalUtilities\ReferenceEqualityComparer.cs</Link>
</Compile>
<Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\SemaphoreSlimExtensions.cs">
<Link>InternalUtilities\SemaphoreSlimExtensions.cs</Link>
</Compile>
<Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\SemaphoreSlimFactory.cs">
<Link>InternalUtilities\SemaphoreSlimFactory.cs</Link>
</Compile>
<Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\SpecializedCollections.cs">
<Link>InternalUtilities\SpecializedCollections.cs</Link>
</Compile>
......@@ -788,7 +794,6 @@
<Compile Include="Utilities\AbstractSpeculationAnalyzer.cs" />
<Compile Include="Utilities\AnnotationTable.cs" />
<Compile Include="Utilities\AsyncLazy`1.cs" />
<Compile Include="Utilities\SemaphoreSlimFactory.cs" />
<Compile Include="Utilities\BidirectionalMap.cs" />
<Compile Include="Utilities\CancellableLazy.cs" />
<Compile Include="Utilities\CancellableLazy`1.cs" />
......@@ -807,7 +812,6 @@
<Compile Include="Utilities\LazyInitialization.cs" />
<Compile Include="Utilities\ObjectPools\Extensions.cs" />
<Compile Include="Utilities\ObjectPools\SharedPools.cs" />
<Compile Include="Utilities\SemaphoreSlimExtensions.cs" />
<Compile Include="Utilities\SerializableBytes.cs" />
<Compile Include="Utilities\SimpleTaskQueue.cs" />
<Compile Include="Utilities\SpecializedTasks.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册