Beispiel #1
0
 /// <summary>
 /// Marks the given event as fully analyzed for the given analyzers.
 /// </summary>
 public void MarkEventComplete(CompilationEvent compilationEvent, IEnumerable <DiagnosticAnalyzer> analyzers)
 {
     foreach (var analyzer in analyzers)
     {
         GetAnalyzerState(analyzer).MarkEventComplete(compilationEvent);
     }
 }
Beispiel #2
0
        /// <summary>
        /// Invoke this method at completion of event processing for the given analyzers.
        /// 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 async Task OnCompilationEventProcessedAsync(CompilationEvent compilationEvent, ImmutableArray <DiagnosticAnalyzer> analyzers, Func <ISymbol, DiagnosticAnalyzer, Task> onSymbolAndMembersProcessedAsync)
        {
            // Analyze if the symbol and all its declaring syntax references are analyzed.
            var symbolDeclaredEvent = compilationEvent as SymbolDeclaredCompilationEvent;

            if (symbolDeclaredEvent != null)
            {
                await OnSymbolDeclaredEventProcessedAsync(symbolDeclaredEvent, analyzers, onSymbolAndMembersProcessedAsync).ConfigureAwait(false);
            }

            // Check if event is fully analyzed for all analyzers.
            foreach (var analyzerState in _analyzerStates)
            {
                if (!analyzerState.IsEventAnalyzed(compilationEvent))
                {
                    return;
                }
            }

            // Remove the event from event map.
            // Note: We do not pass in the cancellationToken to DisposableWait to ensure the state is updated.
            using (_gate.DisposableWait())
            {
                UpdateEventsMap_NoLock(compilationEvent, add: false);
            }
        }
Beispiel #3
0
        private void UpdateEventsMap_NoLock(CompilationEvent compilationEvent, bool add)
        {
            var symbolEvent = compilationEvent as SymbolDeclaredCompilationEvent;

            if (symbolEvent != null)
            {
                // Add/remove symbol events.
                // Any diagnostics request for a tree should trigger symbol and syntax node analysis for symbols with at least one declaring reference in the tree.
                foreach (var location in symbolEvent.Symbol.Locations)
                {
                    if (location.SourceTree != null)
                    {
                        if (add)
                        {
                            AddPendingSourceEvent_NoLock(location.SourceTree, compilationEvent);
                        }
                        else
                        {
                            RemovePendingSourceEvent_NoLock(location.SourceTree, compilationEvent);
                        }
                    }
                }
            }
            else
            {
                // Add/remove compilation unit completed events.
                var compilationUnitCompletedEvent = compilationEvent as CompilationUnitCompletedEvent;
                if (compilationUnitCompletedEvent != null)
                {
                    var tree = compilationUnitCompletedEvent.SemanticModel.SyntaxTree;
                    if (add)
                    {
                        AddPendingSourceEvent_NoLock(tree, compilationEvent);
                    }
                    else
                    {
                        RemovePendingSourceEvent_NoLock(tree, compilationEvent);
                    }
                }
                else if (compilationEvent is CompilationStartedEvent || compilationEvent is CompilationCompletedEvent)
                {
                    // Add/remove compilation events.
                    if (add)
                    {
                        _pendingNonSourceEvents.Add(compilationEvent);
                    }
                    else
                    {
                        _pendingNonSourceEvents.Remove(compilationEvent);
                    }
                }
                else
                {
                    throw new InvalidOperationException("Unexpected compilation event of type " + compilationEvent.GetType().Name);
                }
            }
        }
            public void OnCompilationEventGenerated(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts)
            {
                lock (_gate)
                {
                    var symbolEvent = compilationEvent as SymbolDeclaredCompilationEvent;
                    if (symbolEvent != null)
                    {
                        var needsAnalysis      = false;
                        var symbol             = symbolEvent.Symbol;
                        var skipSymbolAnalysis = AnalysisScope.ShouldSkipSymbolAnalysis(symbolEvent);
                        if (!skipSymbolAnalysis && actionCounts.SymbolActionsCount > 0)
                        {
                            needsAnalysis           = true;
                            _pendingSymbols[symbol] = null;
                        }

                        var skipDeclarationAnalysis = AnalysisScope.ShouldSkipDeclarationAnalysis(symbol);
                        if (!skipDeclarationAnalysis &&
                            actionCounts.HasAnyExecutableCodeActions)
                        {
                            needsAnalysis = true;
                            _pendingDeclarations[symbol] = _currentlyAnalyzingDeclarationsMapPool.Allocate();
                        }

                        if (actionCounts.SymbolStartActionsCount > 0 && (!skipSymbolAnalysis || !skipDeclarationAnalysis))
                        {
                            needsAnalysis = true;
                            _lazyPendingSymbolEndAnalyses         = _lazyPendingSymbolEndAnalyses ?? new Dictionary <ISymbol, AnalyzerStateData>();
                            _lazyPendingSymbolEndAnalyses[symbol] = null;
                        }

                        if (!needsAnalysis)
                        {
                            return;
                        }
                    }
                    else if (compilationEvent is CompilationStartedEvent)
                    {
                        if (actionCounts.SyntaxTreeActionsCount > 0)
                        {
                            _lazySyntaxTreesWithAnalysisData = new Dictionary <SyntaxTree, AnalyzerStateData>();
                            _pendingSyntaxAnalysisTreesCount = compilationEvent.Compilation.SyntaxTrees.Count();
                        }

                        if (actionCounts.CompilationActionsCount == 0)
                        {
                            return;
                        }
                    }

                    _pendingEvents[compilationEvent] = null;
                }
            }
Beispiel #5
0
        private void RemovePendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent)
        {
            HashSet <CompilationEvent> currentEvents;

            if (_pendingSourceEvents.TryGetValue(tree, out currentEvents))
            {
                if (currentEvents.Remove(compilationEvent) && currentEvents.Count == 0)
                {
                    _pendingSourceEvents.Remove(tree);
                    _compilationData.RemoveCachedSemanticModel(tree);
                }
            }
        }
Beispiel #6
0
        private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent)
        {
            HashSet <CompilationEvent> currentEvents;

            if (!_pendingSourceEvents.TryGetValue(tree, out currentEvents))
            {
                currentEvents = new HashSet <CompilationEvent>();
                _pendingSourceEvents[tree] = currentEvents;
                _compilationData.RemoveCachedSemanticModel(tree);
            }

            currentEvents.Add(compilationEvent);
        }
Beispiel #7
0
 private static bool HasActionsForEvent(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts)
 {
     if (compilationEvent is CompilationStartedEvent)
     {
         return(actionCounts.CompilationActionsCount > 0 ||
                actionCounts.SyntaxTreeActionsCount > 0);
     }
     else if (compilationEvent is CompilationCompletedEvent)
     {
         return(actionCounts.CompilationEndActionsCount > 0);
     }
     else if (compilationEvent is SymbolDeclaredCompilationEvent)
     {
         return(actionCounts.SymbolActionsCount > 0 || actionCounts.HasAnyExecutableCodeActions);
     }
     else
     {
         return(actionCounts.SemanticModelActionsCount > 0);
     }
 }
 public bool IsEventAnalyzed(CompilationEvent compilationEvent)
 {
     return(IsEntityFullyProcessed(compilationEvent, _pendingEvents));
 }
 public void MarkEventComplete(CompilationEvent compilationEvent)
 {
     MarkEntityProcessed(compilationEvent, _pendingEvents, _analyzerStateDataPool);
 }
 public bool TryStartProcessingEvent(CompilationEvent compilationEvent, out AnalyzerStateData state)
 {
     return(TryStartProcessingEntity(compilationEvent, _pendingEvents, _analyzerStateDataPool, out state));
 }
Beispiel #11
0
 /// <summary>
 /// Checks if the given event has been fully analyzed for the given analyzer.
 /// </summary>
 public bool IsEventComplete(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer)
 {
     return(GetAnalyzerState(analyzer).IsEventAnalyzed(compilationEvent));
 }
Beispiel #12
0
 /// <summary>
 /// Marks the given event as fully analyzed for the given analyzer.
 /// </summary>
 public void MarkEventComplete(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer)
 {
     GetAnalyzerState(analyzer).MarkEventComplete(compilationEvent);
 }
Beispiel #13
0
 /// <summary>
 /// 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>
 public bool TryStartProcessingEvent(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer, out AnalyzerStateData state)
 {
     return(GetAnalyzerState(analyzer).TryStartProcessingEvent(compilationEvent, out state));
 }