Пример #1
0
        /// <summary>
        /// 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)
        {
            // Analyze if the symbol and all its declaring syntax references are analyzed.
            var symbolDeclaredEvent = compilationEvent as SymbolDeclaredCompilationEvent;

            if (symbolDeclaredEvent != null)
            {
                OnSymbolDeclaredEventProcessed(symbolDeclaredEvent, analysisScope.Analyzers);
            }

            // 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.
            lock (_gate)
            {
                UpdateEventsMap_NoLock(compilationEvent, add: false);
            }
        }
Пример #2
0
        private Task ProcessEventAsync(CompilationEvent e, CancellationToken cancellationToken)
        {
            var symbolEvent = e as SymbolDeclaredCompilationEvent;

            if (symbolEvent != null)
            {
                return(ProcessSymbolDeclaredAsync(symbolEvent, cancellationToken));
            }

            var completedEvent = e as CompilationUnitCompletedEvent;

            if (completedEvent != null)
            {
                return(ProcessCompilationUnitCompletedAsync(completedEvent, cancellationToken));
            }

            var endEvent = e as CompilationCompletedEvent;

            if (endEvent != null)
            {
                return(ProcessCompilationCompletedAsync(endEvent, cancellationToken));
            }

            if (e is CompilationStartedEvent)
            {
                // Ignore CompilationStartedEvent.
                return(null);
            }

            throw new InvalidOperationException("Unexpected compilation event of type " + e.GetType().Name);
        }
Пример #3
0
        /// <summary>
        /// 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 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)
            {
                await OnSymbolDeclaredEventProcessedAsync(symbolDeclaredEvent, analysisScope.Analyzers, cancellationToken).ConfigureAwait(false);
            }

            // Check if event is fully analyzed for all analyzers.
            foreach (var analyzerState in _analyzerStates)
            {
                var eventAnalyzed = await analyzerState.IsEventAnalyzedAsync(compilationEvent, cancellationToken).ConfigureAwait(false);

                if (!eventAnalyzed)
                {
                    return;
                }
            }

            // Remove the event from event map.
            using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                UpdateEventsMap_NoLock(compilationEvent, add: false);
            }

            if (symbolDeclaredEvent != null)
            {
                AnalyzerDriver.RemoveCachedDeclaringReferences(symbolDeclaredEvent.Symbol, symbolDeclaredEvent.Compilation);
            }
        }
Пример #4
0
        private async Task ProcessEvent(CompilationEvent e, CancellationToken cancellationToken)
        {
            var symbolEvent = e as SymbolDeclaredCompilationEvent;

            if (symbolEvent != null)
            {
                await ProcessSymbolDeclared(symbolEvent, cancellationToken).ConfigureAwait(false);

                return;
            }

            var completedEvent = e as CompilationUnitCompletedEvent;

            if (completedEvent != null)
            {
                await ProcessCompilationUnitCompleted(completedEvent, cancellationToken).ConfigureAwait(false);

                return;
            }

            var endEvent = e as CompilationCompletedEvent;

            if (endEvent != null)
            {
                await ProcessCompilationCompleted(endEvent, cancellationToken).ConfigureAwait(false);

                return;
            }

            throw new InvalidOperationException("Unexpected compilation event of type " + e.GetType().Name);
        }
Пример #5
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);
            }
        }
Пример #6
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);
     }
 }
Пример #7
0
        private static bool TryStartProcessingEvent(CompilationEvent nonSymbolCompilationEvent, DiagnosticAnalyzer analyzer, AnalysisScope analysisScope, AnalysisState analysisStateOpt, out AnalyzerStateData analyzerStateOpt)
        {
            Debug.Assert(!(nonSymbolCompilationEvent is SymbolDeclaredCompilationEvent));
            Debug.Assert(analysisScope.Analyzers.Contains(analyzer));

            analyzerStateOpt = null;
            return(analysisStateOpt == null || analysisStateOpt.TryStartProcessingEvent(nonSymbolCompilationEvent, analyzer, out analyzerStateOpt));
        }
Пример #8
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);
                }
            }
        }
Пример #9
0
 private static bool HasActionsForEvent(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts)
 {
     return(compilationEvent switch
     {
         CompilationStartedEvent => actionCounts.CompilationActionsCount > 0 || actionCounts.SyntaxTreeActionsCount > 0 || actionCounts.AdditionalFileActionsCount > 0,
         CompilationCompletedEvent => actionCounts.CompilationEndActionsCount > 0,
         SymbolDeclaredCompilationEvent => actionCounts.SymbolActionsCount > 0 || actionCounts.HasAnyExecutableCodeActions,
         _ => actionCounts.SemanticModelActionsCount > 0
     });
            public void OnCompilationEventGenerated(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts)
            {
                lock (_gate)
                {
                    var symbolEvent = compilationEvent as SymbolDeclaredCompilationEvent;
                    if (symbolEvent != null)
                    {
                        var needsAnalysis = false;
                        var symbol        = symbolEvent.Symbol;
                        if (!AnalysisScope.ShouldSkipSymbolAnalysis(symbolEvent) && actionCounts.SymbolActionsCount > 0)
                        {
                            needsAnalysis           = true;
                            _pendingSymbols[symbol] = null;
                        }

                        if (!AnalysisScope.ShouldSkipDeclarationAnalysis(symbol) &&
                            (actionCounts.SyntaxNodeActionsCount > 0 ||
                             actionCounts.CodeBlockActionsCount > 0 ||
                             actionCounts.CodeBlockStartActionsCount > 0))
                        {
                            foreach (var syntaxRef in symbolEvent.DeclaringSyntaxReferences)
                            {
                                needsAnalysis = true;
                                _pendingDeclarations[syntaxRef.GetSyntax()] = null;
                            }
                        }

                        if (!needsAnalysis)
                        {
                            return;
                        }
                    }
                    else if (compilationEvent is CompilationStartedEvent)
                    {
                        if (actionCounts.SyntaxTreeActionsCount > 0)
                        {
                            var trees = compilationEvent.Compilation.SyntaxTrees;
                            var map   = new Dictionary <SyntaxTree, AnalyzerStateData>(trees.Count());
                            foreach (var tree in trees)
                            {
                                map[tree] = null;
                            }

                            _lazyPendingSyntaxAnalysisTrees = map;
                        }

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

                    _pendingEvents[compilationEvent] = null;
                }
            }
            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] = null;
                        }

                        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 compilationStartedEvent)
                    {
                        var fileCount = actionCounts.SyntaxTreeActionsCount > 0 ? compilationEvent.Compilation.SyntaxTrees.Count() : 0;
                        fileCount += actionCounts.AdditionalFileActionsCount > 0 ? compilationStartedEvent.AdditionalFiles.Length : 0;
                        if (fileCount > 0)
                        {
                            _lazyFilesWithAnalysisData       = new Dictionary <SourceOrAdditionalFile, AnalyzerStateData>();
                            _pendingSyntaxAnalysisFilesCount = fileCount;
                        }

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

                    _pendingEvents[compilationEvent] = null;
                }
            }
Пример #12
0
        private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent)
        {
            if (!_pendingSourceEvents.TryGetValue(tree, out HashSet <CompilationEvent> currentEvents))
            {
                currentEvents = new HashSet <CompilationEvent>();
                _pendingSourceEvents[tree] = currentEvents;
                _compilationData.RemoveCachedSemanticModel(tree);
            }

            currentEvents.Add(compilationEvent);
        }
Пример #13
0
 private void RemovePendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent)
 {
     if (_pendingSourceEvents.TryGetValue(tree, out HashSet <CompilationEvent> currentEvents))
     {
         if (currentEvents.Remove(compilationEvent) && currentEvents.Count == 0)
         {
             _pendingSourceEvents.Remove(tree);
             _compilationData.RemoveCachedSemanticModel(tree);
         }
     }
 }
Пример #14
0
        private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent)
        {
            if (!_pendingSourceEvents.TryGetValue(tree, out var currentEvents))
            {
                currentEvents = new HashSet <CompilationEvent>();
                _pendingSourceEvents[tree] = currentEvents;
                _semanticModelProvider.ClearCache(tree, compilationEvent.Compilation);
            }

            currentEvents.Add(compilationEvent);
        }
Пример #15
0
 private void RemovePendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent)
 {
     if (_pendingSourceEvents.TryGetValue(tree, out var currentEvents))
     {
         if (currentEvents.Remove(compilationEvent) && currentEvents.Count == 0)
         {
             _pendingSourceEvents.Remove(tree);
             _semanticModelProvider.ClearCache(tree, compilationEvent.Compilation);
         }
     }
 }
Пример #16
0
 public bool TryStartProcessingEvent(
     CompilationEvent compilationEvent,
     [NotNullWhen(returnValue: true)] out AnalyzerStateData?state
     )
 {
     return(TryStartProcessingEntity(
                compilationEvent,
                _pendingEvents,
                _analyzerStateDataPool,
                out state
                ));
 }
Пример #17
0
        private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent)
        {
            HashSet <CompilationEvent> currentEvents;

            if (!_pendingSourceEvents.TryGetValue(tree, out currentEvents))
            {
                currentEvents = _compilationEventsPool.Allocate();
                _pendingSourceEvents[tree] = currentEvents;
            }

            currentEvents.Add(compilationEvent);
        }
Пример #18
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)
                {
                    _compilationEventsPool.Free(currentEvents);
                    _pendingSourceEvents.Remove(tree);
                }
            }
        }
Пример #19
0
        private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent)
        {
            HashSet <CompilationEvent> currentEvents;

            if (!_pendingSourceEvents.TryGetValue(tree, out currentEvents))
            {
                currentEvents = _compilationEventsPool.Allocate();
                _pendingSourceEvents[tree] = currentEvents;
                AnalyzerDriver.RemoveCachedSemanticModel(tree, compilationEvent.Compilation);
            }

            currentEvents.Add(compilationEvent);
        }
            public void OnCompilationEventGenerated(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts)
            {
                lock (_gate)
                {
                    var symbolEvent = compilationEvent as SymbolDeclaredCompilationEvent;
                    if (symbolEvent != null)
                    {
                        var needsAnalysis = false;
                        var symbol        = symbolEvent.Symbol;
                        if (!AnalysisScope.ShouldSkipSymbolAnalysis(symbolEvent) && actionCounts.SymbolActionsCount > 0)
                        {
                            needsAnalysis           = true;
                            _pendingSymbols[symbol] = null;
                        }

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

                        if (!needsAnalysis)
                        {
                            return;
                        }
                    }
                    else if (compilationEvent is CompilationStartedEvent)
                    {
                        if (actionCounts.SyntaxTreeActionsCount > 0)
                        {
                            var trees = compilationEvent.Compilation.SyntaxTrees;
                            var map   = new Dictionary <SyntaxTree, AnalyzerStateData>(trees.Count());
                            foreach (var tree in trees)
                            {
                                map[tree] = null;
                            }

                            _lazyPendingSyntaxAnalysisTrees = map;
                        }

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

                    _pendingEvents[compilationEvent] = null;
                }
            }
Пример #21
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);
     }
 }
Пример #22
0
        /// <summary>
        /// Executes the semantic model actions on the given semantic model.
        /// </summary>
        /// <param name="semanticModelActions">Semantic model actions to be executed.</param>
        /// <param name="analyzer">Analyzer whose actions are to be executed.</param>
        /// <param name="semanticModel">Semantic model to analyze.</param>
        /// <param name="compilationUnitCompletedEvent">Compilation event for semantic model analysis.</param>
        /// <param name="analysisScope">Scope for analyzer execution.</param>
        /// <param name="analysisStateOpt">An optional object to track analysis state.</param>
        public void ExecuteSemanticModelActions(
            ImmutableArray <SemanticModelAnalyzerAction> semanticModelActions,
            DiagnosticAnalyzer analyzer,
            SemanticModel semanticModel,
            CompilationEvent compilationUnitCompletedEvent,
            AnalysisScope analysisScope,
            AnalysisState analysisStateOpt)
        {
            AnalyzerStateData analyzerStateOpt = null;

            try
            {
                if (TryStartProcessingEvent(compilationUnitCompletedEvent, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt))
                {
                    ExecuteSemanticModelActionsCore(semanticModelActions, analyzer, semanticModel, analyzerStateOpt);
                    analysisStateOpt?.MarkEventComplete(compilationUnitCompletedEvent, analyzer);
                }
            }
            finally
            {
                analyzerStateOpt?.ResetToReadyState();
            }
        }
Пример #23
0
 private static bool HasActionsForEvent(CompilationEvent compilationEvent, ActionCounts 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.CodeBlockActionsCount > 0 ||
                actionCounts.CodeBlockStartActionsCount > 0 ||
                actionCounts.SymbolActionsCount > 0 ||
                actionCounts.SyntaxNodeActionsCount > 0);
     }
     else
     {
         return(actionCounts.SemanticModelActionsCount > 0);
     }
 }
Пример #24
0
        private void GenerateSimulatedCompilatioNonSourceEvent(Compilation compilation, AnalyzerDriver driver, bool started, CancellationToken cancellationToken)
        {
            lock (_gate)
            {
                bool eventAlreadyGenerated = started ? _compilationStartGenerated : _compilationEndGenerated;
                if (eventAlreadyGenerated)
                {
                    return;
                }

                CompilationEvent compilationEvent        = started ? (CompilationEvent) new CompilationStartedEvent(compilation) : new CompilationCompletedEvent(compilation);
                ImmutableArray <CompilationEvent> events = ImmutableArray.Create(compilationEvent);
                OnCompilationEventsGenerated_NoLock(events, filterTreeOpt: null, driver: driver, cancellationToken: cancellationToken);

                if (started)
                {
                    _compilationStartGenerated = true;
                }
                else
                {
                    _compilationEndGenerated = true;
                }
            }
        }
Пример #25
0
        /// <summary>
        /// Executes compilation actions or compilation end actions.
        /// </summary>
        /// <param name="compilationActions">Compilation actions to be executed.</param>
        /// <param name="analyzer">Analyzer whose actions are to be executed.</param>
        /// <param name="compilationEvent">Compilation event.</param>
        /// <param name="analysisScope">Scope for analyzer execution.</param>
        /// <param name="analysisStateOpt">An optional object to track analysis state.</param>
        public void ExecuteCompilationActions(
            ImmutableArray <CompilationAnalyzerAction> compilationActions,
            DiagnosticAnalyzer analyzer,
            CompilationEvent compilationEvent,
            AnalysisScope analysisScope,
            AnalysisState analysisStateOpt)
        {
            Debug.Assert(compilationEvent is CompilationStartedEvent || compilationEvent is CompilationCompletedEvent);

            AnalyzerStateData analyzerStateOpt = null;

            try
            {
                if (TryStartProcessingEvent(compilationEvent, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt))
                {
                    ExecuteCompilationActionsCore(compilationActions, analyzer, analyzerStateOpt);
                    analysisStateOpt?.MarkEventComplete(compilationEvent, analyzer);
                }
            }
            finally
            {
                analyzerStateOpt?.ResetToReadyState();
            }
        }
Пример #26
0
        private void ExecuteCompilationActions(
            ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<CompilationAnalyzerAction>> compilationActionsMap,
            CompilationEvent compilationEvent,
            AnalysisScope analysisScope,
            AnalysisState analysisStateOpt,
            CancellationToken cancellationToken)
        {
            Debug.Assert(compilationEvent is CompilationStartedEvent || compilationEvent is CompilationCompletedEvent);

            try
            {
                foreach (var analyzer in analysisScope.Analyzers)
                {
                    ImmutableArray<CompilationAnalyzerAction> compilationActions;
                    if (compilationActionsMap.TryGetValue(analyzer, out compilationActions))
                    {
                        analyzerExecutor.ExecuteCompilationActions(compilationActions, analyzer, compilationEvent, analysisScope, analysisStateOpt);
                    }
                    else
                    {
                        analysisStateOpt?.MarkEventComplete(compilationEvent, analyzer);
                    }
                }
            }
            finally
            {
                compilationEvent.FlushCache();
            }
        }
Пример #27
0
 /// <summary>
 /// Marks the given event as fully analyzed for the given analyzer.
 /// </summary>
 public Task MarkEventCompleteAsync(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
 {
     return GetAnalyzerState(analyzer).MarkEventCompleteAsync(compilationEvent, cancellationToken);
 }
Пример #28
0
 private async Task ProcessEventAsync(CompilationEvent e, CancellationToken cancellationToken)
 {
     try
     {
         var processEventTask = ProcessEventCoreAsync(e, cancellationToken);
         if (processEventTask != null)
         {
             await processEventTask.ConfigureAwait(false);
         }
     }
     catch (OperationCanceledException)
     {
         // when just a single operation is cancelled, we continue processing events.
         // TODO: what is the desired behavior in this case?
     }
 }
Пример #29
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 _analyzerStateMap[analyzer].TryStartProcessingEvent(compilationEvent, out state);
 }
Пример #30
0
 /// <summary>
 /// Marks the given event as fully analyzed for the given analyzer.
 /// </summary>
 public void MarkEventComplete(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer)
 {
     _analyzerStateMap[analyzer].MarkEventComplete(compilationEvent);
 }
Пример #31
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);
     }
 }
Пример #32
0
        /// <summary>
        /// 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)
        {
            // Analyze if the symbol and all its declaring syntax references are analyzed.
            var symbolDeclaredEvent = compilationEvent as SymbolDeclaredCompilationEvent;
            if (symbolDeclaredEvent != null)
            {
                OnSymbolDeclaredEventProcessed(symbolDeclaredEvent, analysisScope.Analyzers);
            }

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

            // Remove the event from event map.
            lock (_gate)
            {
                UpdateEventsMap_NoLock(compilationEvent, add: false);
            }
        }
Пример #33
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);
        }
Пример #34
0
 /// <summary>
 /// Attempts to start processing a compilation event for the given analyzer.
 /// </summary>
 /// <returns>
 /// 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 Task<AnalyzerStateData> TryStartProcessingEventAsync(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
 {
     return GetAnalyzerState(analyzer).TryStartProcessingEventAsync(compilationEvent, cancellationToken);
 }
Пример #35
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);
 }
Пример #36
0
 private void ProcessEvent(CompilationEvent e, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken)
 {
     ProcessEventCore(e, analysisScope, analysisStateOpt, cancellationToken);
     analysisStateOpt?.OnCompilationEventProcessed(e, analysisScope);
 }
Пример #37
0
        private async Task ProcessEventAsync(CompilationEvent e, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken)
        {
            await ProcessEventCoreAsync(e, analysisScope, analysisStateOpt, cancellationToken).ConfigureAwait(false);

            if (analysisStateOpt != null)
            {
                await analysisStateOpt.OnCompilationEventProcessedAsync(e, analysisScope, cancellationToken).ConfigureAwait(false);
            }
        }
Пример #38
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));
 }
Пример #40
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);
         }
     }
 }
Пример #41
0
        private Task ProcessEventCoreAsync(CompilationEvent e, CancellationToken cancellationToken)
        {
            var symbolEvent = e as SymbolDeclaredCompilationEvent;
            if (symbolEvent != null)
            {
                return ProcessSymbolDeclaredAsync(symbolEvent, cancellationToken);
            }

            var completedEvent = e as CompilationUnitCompletedEvent;
            if (completedEvent != null)
            {
                return ProcessCompilationUnitCompletedAsync(completedEvent, cancellationToken);
            }

            var endEvent = e as CompilationCompletedEvent;
            if (endEvent != null)
            {
                return ProcessCompilationCompletedAsync(endEvent, cancellationToken);
            }

            if (e is CompilationStartedEvent)
            {
                // Ignore CompilationStartedEvent.
                return null;
            }

            throw new InvalidOperationException("Unexpected compilation event of type " + e.GetType().Name);
        }
Пример #42
0
 private static bool HasActionsForEvent(CompilationEvent compilationEvent, ActionCounts 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.CodeBlockActionsCount > 0 ||
             actionCounts.CodeBlockStartActionsCount > 0 ||
             actionCounts.SymbolActionsCount > 0 ||
             actionCounts.SyntaxNodeActionsCount > 0;
     }
     else
     {
         return actionCounts.SemanticModelActionsCount > 0;
     }
 }
        private async Task ProcessEventAsync(CompilationEvent e, CancellationToken cancellationToken)
        {
            var symbolEvent = e as SymbolDeclaredCompilationEvent;
            if (symbolEvent != null)
            {
                await ProcessSymbolDeclared(symbolEvent, cancellationToken).ConfigureAwait(false);
                return;
            }

            var completedEvent = e as CompilationUnitCompletedEvent;
            if (completedEvent != null)
            {
                await ProcessCompilationUnitCompleted(completedEvent, cancellationToken).ConfigureAwait(false);
                return;
            }

            var endEvent = e as CompilationCompletedEvent;
            if (endEvent != null)
            {
                await ProcessCompilationCompletedAsync(endEvent, cancellationToken).ConfigureAwait(false);
                return;
            }

            throw new InvalidOperationException("Unexpected compilation event of type " + e.GetType().Name);
        }
Пример #44
0
        private void ProcessEventCore(CompilationEvent e, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var symbolEvent = e as SymbolDeclaredCompilationEvent;
            if (symbolEvent != null)
            {
                ProcessSymbolDeclared(symbolEvent, analysisScope, analysisStateOpt, cancellationToken);
                return;
            }

            var completedEvent = e as CompilationUnitCompletedEvent;
            if (completedEvent != null)
            {
                ProcessCompilationUnitCompleted(completedEvent, analysisScope, analysisStateOpt, cancellationToken);
                return;
            }

            var endEvent = e as CompilationCompletedEvent;
            if (endEvent != null)
            {
                ProcessCompilationCompleted(endEvent, analysisScope, analysisStateOpt, cancellationToken);
                return;
            }

            var startedEvent = e as CompilationStartedEvent;
            if (startedEvent != null)
            {
                ProcessCompilationStarted(startedEvent, analysisScope, analysisStateOpt, cancellationToken);
                return;
            }

            throw new InvalidOperationException("Unexpected compilation event of type " + e.GetType().Name);
        }
Пример #45
0
        /// <summary>
        /// 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 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)
            {
                await OnSymbolDeclaredEventProcessedAsync(symbolDeclaredEvent, analysisScope.Analyzers, cancellationToken).ConfigureAwait(false);
            }

            // Check if event is fully analyzed for all analyzers.
            foreach (var analyzerState in _analyzerStates)
            {
                var eventAnalyzed = await analyzerState.IsEventAnalyzedAsync(compilationEvent, cancellationToken).ConfigureAwait(false);
                if (!eventAnalyzed)
                {
                    return;
                }
            }

            // Remove the event from event map.
            using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                UpdateEventsMap_NoLock(compilationEvent, add: false);
            }

            if (symbolDeclaredEvent != null)
            {
                AnalyzerDriver.RemoveCachedDeclaringReferences(symbolDeclaredEvent.Symbol, symbolDeclaredEvent.Compilation);
            }
        }
 public void MarkEventComplete(CompilationEvent compilationEvent)
 {
     MarkEntityProcessed(compilationEvent, _pendingEvents, _analyzerStateDataPool);
 }
Пример #47
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);
 }
Пример #48
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));
 }
Пример #49
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)
         {
             _compilationEventsPool.Free(currentEvents);
             _pendingSourceEvents.Remove(tree);
         }
     }
 }
Пример #50
0
        private async Task ExecuteCompilationActionsAsync(
            ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<CompilationAnalyzerAction>> compilationActionsMap,
            CompilationEvent compilationEvent,
            AnalysisScope analysisScope,
            AnalysisState analysisStateOpt,
            CancellationToken cancellationToken)
        {
            Debug.Assert(compilationEvent is CompilationStartedEvent || compilationEvent is CompilationCompletedEvent);

            try
            {
                foreach (var analyzer in analysisScope.Analyzers)
                {
                    ImmutableArray<CompilationAnalyzerAction> compilationActions;
                    if (compilationActionsMap.TryGetValue(analyzer, out compilationActions))
                    {
                        await analyzerExecutor.ExecuteCompilationActionsAsync(compilationActions, analyzer, compilationEvent, analysisScope, analysisStateOpt).ConfigureAwait(false);
                    }
                    else if (analysisStateOpt != null)
                    {
                        await analysisStateOpt.MarkEventCompleteAsync(compilationEvent, analyzer, cancellationToken).ConfigureAwait(false);
                    }
                }
            }
            finally
            {
                compilationEvent.FlushCache();
            }
        }
Пример #51
0
        private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent)
        {
            HashSet<CompilationEvent> currentEvents;
            if (!_pendingSourceEvents.TryGetValue(tree, out currentEvents))
            {
                currentEvents = _compilationEventsPool.Allocate();
                _pendingSourceEvents[tree] = currentEvents;
                AnalyzerDriver.RemoveCachedSemanticModel(tree, compilationEvent.Compilation);
            }

            currentEvents.Add(compilationEvent);
        }
Пример #52
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);
 }
Пример #53
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);
         }
     }
 }
Пример #54
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));
 }
Пример #55
0
        private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent)
        {
            HashSet<CompilationEvent> currentEvents;
            if (!_pendingSourceEvents.TryGetValue(tree, out currentEvents))
            {
                currentEvents = _compilationEventsPool.Allocate();
                _pendingSourceEvents[tree] = currentEvents;
            }

            currentEvents.Add(compilationEvent);
        }