Esempio n. 1
0
        private async Task <int> AnalyzeAffectedEntriesAsync(Stopwatch stopWatch)
        {
            IDependencyChainNode <PythonAnalyzerEntry> node;
            var remaining = 0;
            var ace       = new AsyncCountdownEvent(0);

            bool isCanceled;

            while ((node = await _walker.GetNextAsync(_analyzerCancellationToken)) != null)
            {
                lock (_syncObj) {
                    isCanceled = _isCanceled;
                }

                if (isCanceled && !node.Value.NotAnalyzed)
                {
                    remaining++;
                    node.MoveNext();
                    continue;
                }

                ActivityTracker.OnEnqueueModule(node.Value.Module.FilePath);

                if (Interlocked.Increment(ref _runningTasks) >= _maxTaskRunning || _walker.Remaining == 1)
                {
                    RunAnalysis(node, stopWatch);
                }
                else
                {
                    ace.AddOne();
                    StartAnalysis(node, ace, stopWatch).DoNotWait();
                }
            }

            await ace.WaitAsync(_analyzerCancellationToken);

            lock (_syncObj) {
                isCanceled = _isCanceled;
            }

            if (_walker.MissingKeys.Count == 0 || _walker.MissingKeys.All(k => k.IsTypeshed))
            {
                Interlocked.Exchange(ref _runningTasks, 0);

                if (!isCanceled)
                {
                    _analysisCompleteEvent.Set();
                }
            }
            else if (!isCanceled && _log != null && _log.LogLevel >= TraceEventType.Verbose)
            {
                _log?.Log(TraceEventType.Verbose, $"Missing keys: {string.Join(", ", _walker.MissingKeys)}");
            }

            return(remaining);
        }
Esempio n. 2
0
        private async Task <int> AnalyzeAffectedEntriesAsync(Stopwatch stopWatch)
        {
            IDependencyChainNode node;
            var remaining = 0;

            while ((node = await _walker.GetNextAsync(_analyzerCancellationToken)) != null)
            {
                var taskLimitReached = false;
                lock (_syncObj) {
                    if (_isCanceled)
                    {
                        switch (node)
                        {
                        case IDependencyChainLoopNode <PythonAnalyzerEntry> loop:
                            // Loop analysis is not cancellable or else small
                            // inner loops of a larger loop will not be analyzed
                            // correctly as large loop may cancel inner loop pass.
                            break;

                        case IDependencyChainSingleNode <PythonAnalyzerEntry> single when !single.Value.NotAnalyzed:
                            remaining++;
                            node.MoveNext();
                            continue;
                        }
                    }

                    taskLimitReached = _ace.Count >= _maxTaskRunning || _walker.Remaining == 1;
                    _ace.AddOne();
                }

                if (taskLimitReached)
                {
                    RunAnalysis(node, stopWatch);
                }
                else
                {
                    StartAnalysis(node, stopWatch).DoNotWait();
                }
            }

            await _ace.WaitAsync(_analyzerCancellationToken);

            lock (_syncObj) {
                if (_walker.MissingKeys.Count == 0 || _walker.MissingKeys.All(k => k.IsTypeshed))
                {
                    Debug.Assert(_ace.Count == 0);
                }
                else if (!_isCanceled && _log != null && _log.LogLevel >= TraceEventType.Verbose)
                {
                    _log?.Log(TraceEventType.Verbose, $"Missing keys: {string.Join(", ", _walker.MissingKeys)}");
                }
            }

            return(remaining);
        }
        /// <summary>
        /// Performs analysis of the document. Returns document global scope
        /// with declared variables and inner scopes. Does not analyze chain
        /// of dependencies, it is intended for the single file analysis.
        /// </summary>
        private void Analyze(IDependencyChainNode <PythonAnalyzerEntry> node, AsyncCountdownEvent ace, Stopwatch stopWatch)
        {
            IPythonModule module;

            try {
                ace?.AddOne();
                var entry = node.Value;
                if (!entry.IsValidVersion(_walker.Version, out module, out var ast))
                {
                    if (ast == null)
                    {
                        // Entry doesn't have ast yet. There should be at least one more session.
                        Cancel();
                    }

                    _log?.Log(TraceEventType.Verbose, $"Analysis of {module.Name}({module.ModuleType}) canceled.");
                    node.Skip();
                    return;
                }
                var startTime = stopWatch.Elapsed;
                AnalyzeEntry(entry, module, ast, _walker.Version);
                node.Commit();

                _log?.Log(TraceEventType.Verbose, $"Analysis of {module.Name}({module.ModuleType}) completed in {(stopWatch.Elapsed - startTime).TotalMilliseconds} ms.");
            } catch (OperationCanceledException oce) {
                node.Value.TryCancel(oce, _walker.Version);
                node.Skip();
                module = node.Value.Module;
                _log?.Log(TraceEventType.Verbose, $"Analysis of {module.Name}({module.ModuleType}) canceled.");
            } catch (Exception exception) {
                module = node.Value.Module;
                node.Value.TrySetException(exception, _walker.Version);
                node.Commit();
                _log?.Log(TraceEventType.Verbose, $"Analysis of {module.Name}({module.ModuleType}) failed. Exception message: {exception.Message}.");
            } finally {
                bool isCanceled;
                lock (_syncObj) {
                    isCanceled = _isCanceled;
                }

                if (!isCanceled)
                {
                    _progress.ReportRemaining(_walker.Remaining);
                }

                Interlocked.Decrement(ref _runningTasks);
                ace?.Signal();
            }
        }
        /// <summary>
        /// Performs analysis of the document. Returns document global scope
        /// with declared variables and inner scopes. Does not analyze chain
        /// of dependencies, it is intended for the single file analysis.
        /// </summary>
        private void Analyze(IDependencyChainNode <PythonAnalyzerEntry> node, AsyncCountdownEvent ace, Stopwatch stopWatch)
        {
            try {
                ace?.AddOne();
                var entry = node.Value;

                if (!entry.IsValidVersion(_walker.Version, out var module, out var ast))
                {
                    if (ast == null)
                    {
                        // Entry doesn't have ast yet. There should be at least one more session.
                        Cancel();
                    }

                    _log?.Log(TraceEventType.Verbose, $"Analysis of {module.Name}({module.ModuleType}) canceled.");
                    node.Skip();
                    return;
                }

                var startTime = stopWatch.Elapsed;
                AnalyzeEntry(entry, module, _walker.Version, node.IsComplete);
                node.Commit();
                ActivityTracker.OnModuleAnalysisComplete(node.Value.Module.FilePath);

                LogCompleted(module, stopWatch, startTime);
            } catch (OperationCanceledException oce) {
                node.Value.TryCancel(oce, _walker.Version);
                node.Skip();
                LogCanceled(node.Value.Module);
            } catch (Exception exception) {
                node.Value.TrySetException(exception, _walker.Version);
                node.Commit();
                LogException(node.Value.Module, exception);
            } finally {
                bool isCanceled;
                lock (_syncObj) {
                    isCanceled = _isCanceled;
                }

                if (!isCanceled)
                {
                    _progress.ReportRemaining(_walker.Remaining);
                }

                Interlocked.Decrement(ref _runningTasks);
                ace?.Signal();
            }
        }