public PythonAnalyzerSession(IServiceContainer services,
                                     IProgressReporter progress,
                                     Action <Task> startNextSession,
                                     CancellationToken analyzerCancellationToken,
                                     IDependencyChainWalker <AnalysisModuleKey, PythonAnalyzerEntry> walker,
                                     int version,
                                     PythonAnalyzerEntry entry,
                                     bool forceGC = false)
        {
            _services         = services;
            _startNextSession = startNextSession;

            _analyzerCancellationToken = analyzerCancellationToken;
            Version = version;
            AffectedEntriesCount = walker?.AffectedValues.Count ?? 1;
            _walker  = walker;
            _entry   = entry;
            _state   = State.NotStarted;
            _forceGC = forceGC;

            _diagnosticsService = _services.GetService <IDiagnosticsService>();
            _platformService    = _services.GetService <IOSPlatform>();
            _analyzer           = _services.GetService <IPythonAnalyzer>();
            _log = _services.GetService <ILogger>();
            _moduleDatabaseService = _services.GetService <IModuleDatabaseService>();
            _progress = progress;

            var interpreter = _services.GetService <IPythonInterpreter>();

            _modulesPathResolver  = interpreter.ModuleResolution.CurrentPathResolver;
            _typeshedPathResolver = interpreter.TypeshedResolution.CurrentPathResolver;
        }
Esempio n. 2
0
        public PythonAnalyzerSession(IServiceManager services,
                                     IProgressReporter progress,
                                     AsyncManualResetEvent analysisCompleteEvent,
                                     Action <Task> startNextSession,
                                     CancellationToken analyzerCancellationToken,
                                     IDependencyChainWalker <AnalysisModuleKey, PythonAnalyzerEntry> walker,
                                     int version,
                                     PythonAnalyzerEntry entry)
        {
            _services = services;
            _analysisCompleteEvent     = analysisCompleteEvent;
            _startNextSession          = startNextSession;
            _analyzerCancellationToken = analyzerCancellationToken;
            Version = version;
            AffectedEntriesCount = walker?.AffectedValues.Count ?? 1;
            _walker = walker;
            _entry  = entry;
            _state  = State.NotStarted;

            _diagnosticsService = _services.GetService <IDiagnosticsService>();
            _analyzer           = _services.GetService <IPythonAnalyzer>();
            _log       = _services.GetService <ILogger>();
            _telemetry = _services.GetService <ITelemetryService>();
            _progress  = progress;
        }
Esempio n. 3
0
        private async Task StartAsync()
        {
            _progress.ReportRemaining(_walker.Remaining);

            lock (_syncObj) {
                var notAnalyzed = _walker.AffectedValues.Count(e => e.NotAnalyzed);

                if (_isCanceled && notAnalyzed < _maxTaskRunning)
                {
                    _state = State.Completed;
                    return;
                }
            }

            var stopWatch = Stopwatch.StartNew();

            foreach (var affectedEntry in _walker.AffectedValues)
            {
                affectedEntry.Invalidate(Version);
            }

            var originalRemaining = _walker.Remaining;
            var remaining         = originalRemaining;

            try {
                _log?.Log(TraceEventType.Verbose, $"Analysis version {Version} of {originalRemaining} entries has started.");
                remaining = await AnalyzeAffectedEntriesAsync(stopWatch);
            } finally {
                stopWatch.Stop();

                bool isCanceled;
                bool isFinal;
                lock (_syncObj) {
                    isCanceled = _isCanceled;
                    _state     = State.Completed;
                    isFinal    = _walker.MissingKeys.Count == 0 && !isCanceled && remaining == 0;
                    _walker    = null;
                }

                if (!isCanceled)
                {
                    _progress.ReportRemaining(remaining);
                    if (isFinal)
                    {
                        var(modulesCount, totalMilliseconds) = ActivityTracker.EndTracking();
                        (_analyzer as PythonAnalyzer)?.RaiseAnalysisComplete(modulesCount, totalMilliseconds);
                        _log?.Log(TraceEventType.Verbose, $"Analysis complete: {modulesCount} modules in {totalMilliseconds} ms.");
                    }
                }
            }

            var elapsed = stopWatch.Elapsed.TotalMilliseconds;

            LogResults(_log, elapsed, originalRemaining, remaining, Version);
            ForceGCIfNeeded(originalRemaining, remaining);
        }
        private async Task StartAsync()
        {
            _progress.ReportRemaining(_walker.Remaining);

            lock (_syncObj) {
                var notAnalyzed = _walker.AffectedValues.Count(e => e.NotAnalyzed);

                if (_isCanceled && notAnalyzed < _maxTaskRunning)
                {
                    _state = State.Completed;
                    return;
                }
            }

            var stopWatch         = Stopwatch.StartNew();
            var originalRemaining = _walker.Remaining;
            var remaining         = originalRemaining;

            try {
                _log?.Log(TraceEventType.Verbose, $"Analysis version {Version} of {originalRemaining} entries has started.");
                remaining = await AnalyzeAffectedEntriesAsync(stopWatch);
            } finally {
                stopWatch.Stop();

                bool isCanceled;
                bool isFinal;
                lock (_syncObj) {
                    isCanceled = _isCanceled;
                    _state     = State.Completed;
                    isFinal    = _walker.MissingKeys.Count == 0 && !isCanceled && remaining == 0;
                    _walker    = null;
                }

                if (!isCanceled)
                {
                    _progress.ReportRemaining(remaining);
                    if (isFinal)
                    {
                        var(modulesCount, totalMilliseconds) = ActivityTracker.EndTracking();
                        totalMilliseconds = Math.Round(totalMilliseconds, 2);
                        (_analyzer as PythonAnalyzer)?.RaiseAnalysisComplete(modulesCount, totalMilliseconds);
                        _log?.Log(TraceEventType.Verbose, $"Analysis complete: {modulesCount} modules in {totalMilliseconds} ms.");
                        //#if DEBUG
                        //                        var notReady = _analyzer.LoadedModules.Where(m => (m.ModuleType == ModuleType.Library || m.ModuleType == ModuleType.Stub) && m.Analysis is EmptyAnalysis).ToArray();
                        //                        Debug.Assert(notReady.Length == 0);
                        //#endif
                    }
                }
            }

            var elapsed = stopWatch.Elapsed.TotalMilliseconds;

            LogResults(_log, elapsed, originalRemaining, remaining, Version);
            ForceGCIfNeeded(_log, originalRemaining, remaining, _forceGC);
        }
Esempio n. 5
0
        private async Task StartAsync()
        {
            _progress.ReportRemaining(_walker.Remaining);

            lock (_syncObj) {
                var notAnalyzed = _walker.AffectedValues.Count(e => e.NotAnalyzed);

                if (_isCanceled && notAnalyzed < _maxTaskRunning)
                {
                    _state = State.Completed;
                    return;
                }
            }

            var stopWatch         = Stopwatch.StartNew();
            var originalRemaining = _walker.Remaining;
            var remaining         = originalRemaining;

            try {
                _log?.Log(TraceEventType.Verbose, $"Analysis version {Version} of {originalRemaining} entries has started.");
                remaining = await AnalyzeAffectedEntriesAsync(stopWatch);

                Debug.Assert(_ace.Count == 0);
            } finally {
                stopWatch.Stop();

                var isFinal = false;
                lock (_syncObj) {
                    if (!_isCanceled)
                    {
                        _progress.ReportRemaining(remaining);
                    }

                    _state  = State.Completed;
                    isFinal = _walker.MissingKeys.Count == 0 && !_isCanceled && remaining == 0;
                    _walker = null;
                }

                if (isFinal)
                {
                    var(modulesCount, totalMilliseconds) = ActivityTracker.EndTracking();
                    totalMilliseconds = Math.Round(totalMilliseconds, 2);
                    if (await _analyzer.RaiseAnalysisCompleteAsync(modulesCount, totalMilliseconds))
                    {
                        _log?.Log(TraceEventType.Verbose, $"Analysis complete: {modulesCount} modules in {totalMilliseconds} ms.");
                    }
                }
            }

            var elapsed = stopWatch.Elapsed.TotalMilliseconds;

            LogResults(_log, elapsed, originalRemaining, remaining, Version);
            ForceGCIfNeeded(_log, originalRemaining, remaining, _forceGC);
        }
        private async Task StartAsync(IDependencyChainWalker <AnalysisModuleKey, PythonAnalyzerEntry> walker)
        {
            _progress.ReportRemaining(walker.Remaining);

            lock (_syncObj) {
                var notAnalyzed = walker.AffectedValues.Count(e => e.NotAnalyzed);

                if (_isCanceled && notAnalyzed < _maxTaskRunning)
                {
                    _state = State.Completed;
                    _cts.Dispose();
                    return;
                }
            }

            var cancellationToken = _cts.Token;
            var stopWatch         = Stopwatch.StartNew();

            foreach (var affectedEntry in walker.AffectedValues)
            {
                affectedEntry.Invalidate(Version);
            }

            var originalRemaining = walker.Remaining;
            var remaining         = originalRemaining;

            try {
                _log?.Log(TraceEventType.Verbose, $"Analysis version {walker.Version} of {originalRemaining} entries has started.");
                remaining = await AnalyzeAffectedEntriesAsync(walker, stopWatch, cancellationToken);
            } finally {
                _cts.Dispose();
                stopWatch.Stop();

                bool isCanceled;
                lock (_syncObj) {
                    isCanceled = _isCanceled;
                    _state     = State.Completed;
                }

                if (!isCanceled)
                {
                    _progress.ReportRemaining(remaining);
                }
            }

            var elapsed = stopWatch.Elapsed.TotalMilliseconds;

            SendTelemetry(elapsed, originalRemaining, remaining, walker.Version);
            LogResults(elapsed, originalRemaining, remaining, walker.Version);
        }
        private async Task StartAsync()
        {
            _progress.ReportRemaining(_walker.Remaining);

            lock (_syncObj) {
                var notAnalyzed = _walker.AffectedValues.Count(e => e.NotAnalyzed);

                if (_isCanceled && notAnalyzed < _maxTaskRunning)
                {
                    _state = State.Completed;
                    return;
                }
            }

            var stopWatch = Stopwatch.StartNew();

            foreach (var affectedEntry in _walker.AffectedValues)
            {
                affectedEntry.Invalidate(Version);
            }

            var originalRemaining = _walker.Remaining;
            var remaining         = originalRemaining;

            try {
                _log?.Log(TraceEventType.Verbose, $"Analysis version {Version} of {originalRemaining} entries has started.");
                remaining = await AnalyzeAffectedEntriesAsync(stopWatch);
            } finally {
                stopWatch.Stop();

                bool isCanceled;
                lock (_syncObj) {
                    isCanceled = _isCanceled;
                    _state     = State.Completed;
                    _walker    = null;
                }

                if (!isCanceled)
                {
                    _progress.ReportRemaining(remaining);
                }
            }

            var elapsed = stopWatch.Elapsed.TotalMilliseconds;

            SendTelemetry(_telemetry, elapsed, originalRemaining, remaining, Version);
            LogResults(_log, elapsed, originalRemaining, remaining, Version);
            ForceGCIfNeeded(originalRemaining, remaining);
        }
        private async Task <int> AnalyzeAffectedEntriesAsync(IDependencyChainWalker <AnalysisModuleKey, PythonAnalyzerEntry> walker, Stopwatch stopWatch, CancellationToken cancellationToken)
        {
            IDependencyChainNode <PythonAnalyzerEntry> node;
            var remaining = 0;

            while ((node = await walker.GetNextAsync(cancellationToken)) != null)
            {
                bool isCanceled;
                lock (_syncObj) {
                    isCanceled = _isCanceled;
                }

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

                if (Interlocked.Increment(ref _runningTasks) >= _maxTaskRunning || walker.Remaining == 1)
                {
                    Analyze(walker, node, stopWatch, cancellationToken);
                }
                else
                {
                    StartAnalysis(walker, node, stopWatch, cancellationToken).DoNotWait();
                }
            }

            if (walker.MissingKeys.All(k => k.IsTypeshed))
            {
                Interlocked.Exchange(ref _runningTasks, 0);
                bool isCanceled;
                lock (_syncObj) {
                    isCanceled = _isCanceled;
                }

                if (!isCanceled)
                {
                    _analysisCompleteEvent.Set();
                }
            }

            return(remaining);
        }
Esempio n. 9
0
        public bool TryCreateWalker(int version, out IDependencyChainWalker <TKey, TValue> walker)
        {
            DependencyGraphSnapshot <TKey, TValue>            snapshot;
            ImmutableArray <DependencyVertex <TKey, TValue> > changedVertices;

            lock (_syncObj) {
                snapshot = _vertices.Snapshot;
                if (version != snapshot.Version)
                {
                    walker = default;
                    return(false);
                }

                changedVertices = ImmutableArray <DependencyVertex <TKey, TValue> > .Create(_changedVertices.Values);
            }

            walker = CreateDependencyChainWalker(this, snapshot, changedVertices);
            return(true);
        }
        /// <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(IDependencyChainWalker <AnalysisModuleKey, PythonAnalyzerEntry> walker, IDependencyChainNode <PythonAnalyzerEntry> node, Stopwatch stopWatch, CancellationToken cancellationToken)
        {
            IPythonModule module;

            try {
                var entry = node.Value;
                if (!entry.IsValidVersion(walker.Version, out module, out var ast))
                {
                    _log?.Log(TraceEventType.Verbose, $"Analysis of {module.Name}({module.ModuleType}) canceled.");
                    node.Skip();
                    return;
                }
                var startTime = stopWatch.Elapsed;
                AnalyzeEntry(entry, module, ast, walker.Version, cancellationToken);
                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.");
            } finally {
                bool isCanceled;
                lock (_syncObj) {
                    isCanceled = _isCanceled;
                }

                if (!isCanceled)
                {
                    _progress.ReportRemaining(walker.Remaining);
                }
                Interlocked.Decrement(ref _runningTasks);
            }
        }
 private Task StartAnalysis(IDependencyChainWalker <AnalysisModuleKey, PythonAnalyzerEntry> walker, IDependencyChainNode <PythonAnalyzerEntry> node, Stopwatch stopWatch, CancellationToken cancellationToken)
 => Task.Run(() => Analyze(walker, node, stopWatch, cancellationToken), cancellationToken);