Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Handling dependencies in module persistence #1471

Merged
merged 291 commits into from
Sep 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
291 commits
Select commit Hold shift + click to select a range
663dc8f
Partial
Jun 4, 2019
86544a6
Models and views
Jun 4, 2019
67b06c2
Merge branch 'master' of https://github.com/microsoft/python-language…
Jun 4, 2019
9daf4a9
Merge master
Jun 4, 2019
90318e9
Restore log null checks
Jun 4, 2019
b79d918
Merge master
Jun 4, 2019
a02c6f3
Fix merge conflict
Jun 4, 2019
8a6b055
Merge master
Jun 5, 2019
57358eb
Fix merge issue
Jun 5, 2019
41ef00f
Merge branch 'master' of https://github.com/microsoft/python-language…
Jun 5, 2019
814cd64
Merge master
Jun 6, 2019
6ceb9b8
Null check
Jun 6, 2019
74bb061
Merge branch 'noast5' into db
Jun 6, 2019
478ce37
Partial
Jun 6, 2019
cb46e68
Partial
Jun 6, 2019
ef2981c
Partial
Jun 6, 2019
2164ad5
Fix test
Jun 6, 2019
1a48790
Merge branch 'noast5' into db
Jun 6, 2019
319c416
Partial
Jun 6, 2019
86b0ee6
Partial
Jun 7, 2019
1670c9d
First test
Jun 7, 2019
ab69cfd
Baseline comparison
Jun 7, 2019
e00c197
Builtins
Jun 7, 2019
4e1657c
Partial
Jun 7, 2019
ade00f4
Type fixes
Jun 10, 2019
e2fc221
Fix type names, part I
Jun 11, 2019
aaf40bb
Qualified name
Jun 11, 2019
a5b3b20
Properly write variables
Jun 11, 2019
f23a487
Partial
Jun 11, 2019
e6373a7
Construct module from model
Jun 12, 2019
6f6737d
Test
Jun 12, 2019
081f475
Variable creations
Jun 12, 2019
42fa4dc
Factories
Jun 13, 2019
2f03cb9
Factories
Jun 13, 2019
1dc3339
Split construction
Jun 13, 2019
9535bad
Restore
Jun 13, 2019
bec2a82
Save builtins
Jun 13, 2019
80c9b1c
Test passes
Jun 13, 2019
5b372f7
Qualified name
Jun 13, 2019
3066554
Better export detection
Jun 14, 2019
91491d4
Test fixes
Jun 14, 2019
bc4f587
More consistent qualified names
Jun 14, 2019
af69880
Sys test
Jun 14, 2019
5c1a0c3
Demo
Jun 14, 2019
4146690
Complete sys write/read
Jun 17, 2019
48763aa
Partial
Jun 17, 2019
93bece3
Partial
Jun 18, 2019
55b6a3f
Test staility
Jun 18, 2019
5e9bf8e
Perf bug
Jun 18, 2019
c152e67
Merge master
Jun 18, 2019
eadd622
Baseline, remove debug code, deactivate db
Jun 18, 2019
ba87581
Test fixes
Jun 18, 2019
a797593
Test fix
Jun 18, 2019
db6c7fc
Simplify a bit
Jun 19, 2019
f73fed0
Baselines and use : separator
Jun 19, 2019
4054d5a
Baselines
Jun 19, 2019
4ef96d8
PR feedback
Jun 19, 2019
c7436ed
Merge branch 'master' of https://github.com/microsoft/python-language…
Jun 19, 2019
f3860e6
Merge master
Jun 19, 2019
cab0fce
Remove registry reference
Jun 19, 2019
b9c1e14
PR feedback
Jun 19, 2019
4fbdcb9
Merge master
Jul 11, 2019
c7b1a5d
Merge db
Jul 11, 2019
90d1429
PR feedback
Jul 11, 2019
10289c3
Merge branch 'master' of https://github.com/microsoft/python-language…
Jul 12, 2019
facb062
Restore persistence + update test
Jul 12, 2019
d80604a
Better handle persistent module in dependencies
Jul 14, 2019
0705812
Merge master
Jul 15, 2019
96a5b82
Merge master
Jul 15, 2019
360f922
Undo
Jul 15, 2019
1015c1b
Add location converter abstraction
Jul 15, 2019
2ab07d6
Store member location
Jul 15, 2019
57c24c5
Fix merge issue
Jul 15, 2019
4779813
Basic locations test
Jul 15, 2019
7e6fb63
Navigation
Jul 15, 2019
9ee9bfe
Add test
Jul 16, 2019
fc66756
Update baselines
Jul 16, 2019
3b0fb23
Type restore - initial
Jul 17, 2019
8192ff2
Remove debug code
Jul 17, 2019
e27218f
Partial
Jul 17, 2019
ae4e178
Fix stub merge
Jul 18, 2019
2209ec1
Various model fixes
Jul 19, 2019
73498eb
Improve module handling
Jul 19, 2019
fcfb2bb
Qualified name improvements
Jul 23, 2019
54fa335
Fix unbound case
Jul 23, 2019
bb0b415
Improve stub merge
Jul 23, 2019
3b213bc
Fix qualified names of typing
Jul 23, 2019
eaa9e37
Handle stub-only modules
Jul 23, 2019
05eb692
Merge branch 'db' of https://github.com/microsoft/python-language-ser…
Jul 23, 2019
5193858
Merge branch 'dbloc' into dbtype
Jul 23, 2019
b888b2a
Add tests for io, re and sys
Jul 24, 2019
40554b0
Better handle named tuple
Jul 24, 2019
fcd2bd5
Handle module circular references
Jul 24, 2019
28f5b6c
Handle else in platform and version clauses + handle it in symbol col…
Jul 24, 2019
8fdf769
Formatting
Jul 24, 2019
08b5971
Fix walk of multi-level if statement
Jul 24, 2019
67fed10
Unify package search in imports
Jul 24, 2019
247a8c3
Fix tests
Jul 25, 2019
2bd4749
Undo change
Jul 25, 2019
5ead9ec
Port changes from dbtype
Jul 25, 2019
4090ca0
Merge fixes from upstream
Jul 25, 2019
97f1716
Merge master
Jul 25, 2019
59f4b83
Partial
Jul 26, 2019
91a0bb5
Named tuple support
Jul 29, 2019
362800c
Baseline updates
Jul 29, 2019
32e8bfc
Debug code
Jul 29, 2019
0d65468
Support types
Jul 30, 2019
f42d453
Merge branch 'master' into dbtype
Jul 30, 2019
3a1fd40
Merge upstream
Jul 30, 2019
9e3011d
Properly compare class member declaring type
Jul 30, 2019
eba1f45
Nested classes and functions persistence
Jul 30, 2019
12b0269
Undo debug
Jul 30, 2019
234390d
Fix numpy restore
Jul 30, 2019
263eabf
Baselines
Jul 30, 2019
f065110
Fix tests
Jul 31, 2019
b2b0501
Update AnyStr test reflecting changes to AnyStr behavior
Jul 31, 2019
28fa723
Exclude baselines from git diff
Jul 31, 2019
b58e893
Fix gitattr
Jul 31, 2019
f110a53
Move git setting to root
Jul 31, 2019
21c1660
Try no path
Jul 31, 2019
96d38b2
Test fixes
Jul 31, 2019
7ee6322
Undo change
Jul 31, 2019
db4aab1
Additional stub merge fixes
Aug 2, 2019
f72818e
Baseline updates
Aug 2, 2019
ed1a728
Fix goto def
Aug 4, 2019
8ee1fd0
Protect specific type creation
Aug 5, 2019
0ce7bad
Track documentaton source
Aug 5, 2019
f9aff94
Merge
Aug 5, 2019
088ce1b
More reliable tests + simplification
Aug 5, 2019
c1b93d8
Typo
Aug 5, 2019
62ac1c2
Cleanup
Aug 6, 2019
b719956
Basic classification
Aug 6, 2019
14671ae
Merge #1340
Aug 6, 2019
7983c75
Merge master
Aug 6, 2019
6b207ae
Merge master
Aug 6, 2019
a9b7ff0
Fix merge error
Aug 6, 2019
ac9d1cb
Module unique id fixes
Aug 6, 2019
23a9b81
Stricted check to save analysis
Aug 6, 2019
1d86086
Revert "Fix tests"
Aug 7, 2019
67350e3
Revert "Unify package search in imports"
Aug 7, 2019
01d7f2f
Merge branch '1376' into dbtype
Aug 7, 2019
f687dc8
Don't clear scope variables with inner classes
Aug 7, 2019
68b479b
Fix typo
Aug 7, 2019
eac2d40
Many new tests
Aug 7, 2019
f3261a3
Fix collections test
Aug 7, 2019
9825e3f
Fix CTypes
Aug 8, 2019
570a925
Initial
Aug 10, 2019
318b3cd
Update test
Aug 10, 2019
06112c6
Merge master
Aug 10, 2019
e0a37a9
Merge master
Aug 10, 2019
517a004
Merge master
Aug 11, 2019
f7717ac
Merge issues
Aug 11, 2019
4e4215c
Fix CTypes again
Aug 11, 2019
d6fa183
Merge branch '1231a' into dbsystest
Aug 11, 2019
2cbb89f
Fix null bases
Aug 11, 2019
58ae484
Tell between class members with/without self better
Aug 12, 2019
53f3af4
TypeVar support
Aug 12, 2019
11cb4b5
Add bound/covariant
Aug 12, 2019
9a92494
Fix Enum reassignments
Aug 12, 2019
e72285c
Fix Random
Aug 12, 2019
a26822a
Fix import * over local declarations (Socket)
Aug 13, 2019
c924622
Move interface
Aug 13, 2019
a473a98
Fix reference search
Aug 13, 2019
3c9a912
Enable asyncio test
Aug 13, 2019
8406a62
Merge db
Aug 13, 2019
4853e98
Merge hover fixes
Aug 13, 2019
3eb2f41
More tests
Aug 13, 2019
3d10d45
Merge branch 'db' of https://github.com/microsoft/python-language-ser…
Aug 13, 2019
4dcdb25
Enable dataclasses
Aug 13, 2019
a5c3af6
Add inspect and gzip
Aug 13, 2019
6fff95d
More tests
Aug 13, 2019
7847eb0
Add setting
Aug 13, 2019
e36ede9
Add handling of import position relative to the variable
Aug 13, 2019
2270c3b
Caching level changes
Aug 13, 2019
ffd2c37
Partial
Aug 14, 2019
8c0b1ee
Rework
Aug 14, 2019
f40966d
Fix null
Aug 14, 2019
359329f
Update baselines
Aug 14, 2019
6794e7c
Merge branch 'dbsystest' into functools
Aug 14, 2019
a0b9782
Functools pass
Aug 15, 2019
e99598b
Reverse stub merge
Aug 15, 2019
a5e41d0
Partial
Aug 15, 2019
2c1cbab
Partial ctypes
Aug 16, 2019
f511e64
Update variables post merge
Aug 16, 2019
18e882b
Fix ctypes
Aug 16, 2019
ab35ba6
Merge db/master
Aug 16, 2019
a037a64
Merge branch 'db' of https://github.com/microsoft/python-language-ser…
Aug 16, 2019
2f299cd
Merge issues
Aug 16, 2019
c614ec8
Fix typevar
Aug 17, 2019
97ba31d
Merge db
Aug 17, 2019
1c2968e
Add caching on construction
Aug 17, 2019
3509a55
Assorted fixes
Aug 19, 2019
ef9df9d
Named tuples
Aug 19, 2019
4b06021
Work around os stub oddness
Aug 19, 2019
02c506d
Fix generic qualified names
Aug 19, 2019
17aedd2
Ignore lambdas
Aug 19, 2019
7c5afc0
Support named tuples as bases
Aug 19, 2019
4ae9f42
Baselines
Aug 19, 2019
c3eb060
Test updates
Aug 19, 2019
d5b85ee
Named tuple tests
Aug 19, 2019
b00e157
Merge master
Aug 20, 2019
83c9d10
PR feedback
Aug 20, 2019
4bd56ff
Using
Aug 21, 2019
5130e0d
Separate creation and population for better handling of forward refer…
Aug 21, 2019
1b01feb
Add dependency provider
Aug 21, 2019
69581e3
Merge master
Aug 21, 2019
2d60ddd
Merge issues
Aug 21, 2019
12d3c8b
Better class creation
Aug 22, 2019
d44849c
Partial
Aug 22, 2019
f8eb564
Dependency providers
Aug 22, 2019
c328a18
Add IsPersistent flag
Aug 22, 2019
caebbeb
Merge branch 'db' of https://github.com/microsoft/python-language-ser…
Aug 22, 2019
cb26df5
Make special global scope
Aug 22, 2019
ac91b1a
Move dependency fetch earlier
Aug 23, 2019
5633d3d
Merge master
Aug 23, 2019
f6eb66c
Replace AST walk by interface
Aug 23, 2019
fc2661e
Make analysis sequence closer to master
Aug 23, 2019
afe0385
Undo some
Aug 24, 2019
d737eb2
Undo debug
Aug 24, 2019
97e8b43
Show dependencies in log
Aug 26, 2019
813d463
Merge db
Aug 26, 2019
6672c50
null check
Aug 27, 2019
43e19bf
Update tests
Aug 27, 2019
134c7fd
Make sure factory looks in correct scope
Aug 27, 2019
b867c63
Merge branch 'db' of https://github.com/microsoft/python-language-ser…
Aug 27, 2019
09cc159
Separate stub dependencies
Aug 29, 2019
9eb9423
Don't try and merge from empty stub
Aug 29, 2019
1630259
Match generic parameters by name
Aug 29, 2019
f18fc93
Merge branch 'db' of https://github.com/microsoft/python-language-ser…
Aug 29, 2019
568f79e
Use qualified names in generics
Aug 29, 2019
256174a
Back to names
Aug 29, 2019
7c2f64e
Merge db/master
Aug 30, 2019
7bce4fd
Merge branch 'db' of https://github.com/microsoft/python-language-ser…
Aug 31, 2019
0dd5eb2
Update tests
Sep 3, 2019
b1b7e2a
usings
Sep 3, 2019
68ab337
Fix dependencies for stub
Sep 3, 2019
f821fce
Merge db/master
Sep 3, 2019
7ef2c7e
Merge branch 'db' of https://github.com/microsoft/python-language-ser…
Sep 3, 2019
4967070
Null check
Sep 4, 2019
612e321
PR feedback
Sep 4, 2019
d9a6f38
PR feedback + fix merge issue in generics
Sep 4, 2019
3bdd6e1
Test fixes + PR feedback
Sep 4, 2019
dec8553
Baseline updates
Sep 4, 2019
80dcce5
PR feedback
Sep 4, 2019
68a4bb4
Restore original order
Sep 4, 2019
ea3b267
Order
Sep 4, 2019
1a1ab46
Merge issues
Sep 4, 2019
f230ec5
Make cancellation closer to original
Sep 5, 2019
378a046
Pass cancellation to module walker
Sep 5, 2019
f195956
Simplify
Sep 5, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Analysis/Ast/Impl/Analyzer/Definitions/IAnalyzable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@
// See the Apache Version 2.0 License for specific language governing
// permissions and limitations under the License.

using Microsoft.Python.Analysis.Dependencies;

namespace Microsoft.Python.Analysis.Analyzer {
/// <summary>
/// Represents document that can be analyzed asynchronously.
/// </summary>
internal interface IAnalyzable {
/// <summary>
/// Returns object that can calculate dependencies of this entry.
/// </summary>
IDependencyProvider DependencyProvider { get; }

/// <summary>
/// Notifies document that analysis is about to begin.
/// </summary>
Expand Down
64 changes: 44 additions & 20 deletions src/Analysis/Ast/Impl/Analyzer/ModuleWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.Python.Analysis.Analyzer.Evaluation;
using Microsoft.Python.Analysis.Documents;
using Microsoft.Python.Analysis.Modules;
Expand All @@ -32,30 +33,36 @@ namespace Microsoft.Python.Analysis.Analyzer {
internal class ModuleWalker : AnalysisWalker {
private const string AllVariableName = "__all__";
private readonly IDocumentAnalysis _stubAnalysis;
private readonly CancellationToken _cancellationToken;

// A hack to use __all__ export in the most simple case.
private int _allReferencesCount;
private bool _allIsUsable = true;

public ModuleWalker(IServiceContainer services, IPythonModule module, PythonAst ast)
public ModuleWalker(IServiceContainer services, IPythonModule module, PythonAst ast, CancellationToken cancellationToken)
: base(new ExpressionEval(services, module, ast)) {
_stubAnalysis = Module.Stub is IDocument doc ? doc.GetAnyAnalysis() : null;
_cancellationToken = cancellationToken;
}

public override bool Walk(NameExpression node) {
if (Eval.CurrentScope == Eval.GlobalScope && node.Name == AllVariableName) {
_allReferencesCount++;
}

_cancellationToken.ThrowIfCancellationRequested();
return base.Walk(node);
}

public override bool Walk(AugmentedAssignStatement node) {
HandleAugmentedAllAssign(node);
_cancellationToken.ThrowIfCancellationRequested();
return base.Walk(node);
}

public override bool Walk(CallExpression node) {
HandleAllAppendExtend(node);
_cancellationToken.ThrowIfCancellationRequested();
return base.Walk(node);
}

Expand Down Expand Up @@ -146,6 +153,7 @@ private bool IsHandleableAll(Node node) {

public override bool Walk(PythonAst node) {
Check.InvalidOperation(() => Ast == node, "walking wrong AST");
_cancellationToken.ThrowIfCancellationRequested();

// Collect basic information about classes and functions in order
// to correctly process forward references. Does not determine
Expand Down Expand Up @@ -181,16 +189,20 @@ public override bool Walk(PythonAst node) {

// Classes and functions are walked by their respective evaluators
public override bool Walk(ClassDefinition node) {
_cancellationToken.ThrowIfCancellationRequested();
SymbolTable.Evaluate(node);
return false;
}

public override bool Walk(FunctionDefinition node) {
_cancellationToken.ThrowIfCancellationRequested();
SymbolTable.Evaluate(node);
return false;
}

public void Complete() {
_cancellationToken.ThrowIfCancellationRequested();

SymbolTable.EvaluateAll();
SymbolTable.ReplacedByStubs.Clear();
MergeStub();
Expand Down Expand Up @@ -220,11 +232,13 @@ public void Complete() {
/// of the definitions. Stub may contains those so we need to merge it in.
/// </remarks>
private void MergeStub() {
if (Module.ModuleType == ModuleType.User) {
_cancellationToken.ThrowIfCancellationRequested();

if (Module.ModuleType == ModuleType.User || Module.ModuleType == ModuleType.Stub) {
return;
}
// No stub, no merge.
if (_stubAnalysis == null) {
if (_stubAnalysis.IsEmpty()) {
return;
}
// TODO: figure out why module is getting analyzed before stub.
Expand All @@ -248,6 +262,18 @@ private void MergeStub() {
if (stubType.DeclaringModule is TypingModule && stubType.Name == "Any") {
continue;
}

if (sourceVar?.Source == VariableSource.Import &&
sourceVar.GetPythonType()?.DeclaringModule.Stub != null) {
// Keep imported types as they are defined in the library. For example,
// 'requests' imports NullHandler as 'from logging import NullHandler'.
// But 'requests' also declares NullHandler in its stub (but not in the main code)
// and that declaration does not have documentation or location. Therefore avoid
// taking types that are stub-only when similar type is imported from another
// module that also has a stub.
continue;
}

TryReplaceMember(v, sourceType, stubType);
}

Expand All @@ -257,7 +283,7 @@ private void MergeStub() {
private void TryReplaceMember(IVariable v, IPythonType sourceType, IPythonType stubType) {
// If type does not exist in module, but exists in stub, declare it unless it is an import.
// If types are the classes, take class from the stub, then add missing members.
// Otherwise, replace type from one from the stub.
// Otherwise, replace type by one from the stub.
switch (sourceType) {
case null:
// Nothing in sources, but there is type in the stub. Declare it.
Expand Down Expand Up @@ -379,28 +405,26 @@ private static void TransferDocumentationAndLocation(IPythonType s, IPythonType
if (s != d && s is PythonType src && d is PythonType dst) {
// If type is a class, then doc can either come from class definition node of from __init__.
// If class has doc from the class definition, don't stomp on it.
var transferDoc = true;
if (src is PythonClassType srcClass && dst is PythonClassType dstClass) {
// Higher lever source wins
if (srcClass.DocumentationSource == PythonClassType.ClassDocumentationSource.Class ||
(srcClass.DocumentationSource == PythonClassType.ClassDocumentationSource.Init && dstClass.DocumentationSource == PythonClassType.ClassDocumentationSource.Base)) {
dstClass.SetDocumentation(srcClass.Documentation);
transferDoc = false;
}
}

// Sometimes destination (stub type) already has documentation. This happens when stub type
// is used to augment more than one type. For example, in threading module RLock stub class
// replaces both RLock function and _RLock class making 'factory' function RLock to look
// like a class constructor. Effectively a single stub type is used for more than one type
// in the source and two source types may have different documentation. Thus transferring doc
// from one source type affects documentation of another type. It may be better to clone stub
// type and separate instances for separate source type, but for now we'll just avoid stomping
// on the existing documentation.
if (transferDoc && string.IsNullOrEmpty(dst.Documentation)) {
var srcDocumentation = src.Documentation;
if (!string.IsNullOrEmpty(srcDocumentation)) {
dst.SetDocumentation(srcDocumentation);
} else {
// Sometimes destination (stub type) already has documentation. This happens when stub type
// is used to augment more than one type. For example, in threading module RLock stub class
// replaces both RLock function and _RLock class making 'factory' function RLock to look
// like a class constructor. Effectively a single stub type is used for more than one type
// in the source and two source types may have different documentation. Thus transferring doc
// from one source type affects documentation of another type. It may be better to clone stub
// type and separate instances for separate source type, but for now we'll just avoid stomping
// on the existing documentation.
if (string.IsNullOrEmpty(dst.Documentation)) {
var srcDocumentation = src.Documentation;
if (!string.IsNullOrEmpty(srcDocumentation)) {
dst.SetDocumentation(srcDocumentation);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Analysis/Ast/Impl/Analyzer/PythonAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ internal void RaiseAnalysisComplete(int moduleCount, double msElapsed)
private void AnalyzeDocument(in AnalysisModuleKey key, in PythonAnalyzerEntry entry, in ImmutableArray<AnalysisModuleKey> dependencies) {
_analysisCompleteEvent.Reset();
ActivityTracker.StartTracking();
_log?.Log(TraceEventType.Verbose, $"Analysis of {entry.Module.Name}({entry.Module.ModuleType}) queued");
_log?.Log(TraceEventType.Verbose, $"Analysis of {entry.Module.Name} ({entry.Module.ModuleType}) queued. Dependencies: {string.Join(", ", dependencies.Select(d => d.IsTypeshed ? $"{d.Name} (stub)" : d.Name))}");

var graphVersion = _dependencyResolver.ChangeValue(key, entry, entry.IsUserOrBuiltin || key.IsNonUserAsDocument, dependencies);

Expand Down
82 changes: 5 additions & 77 deletions src/Analysis/Ast/Impl/Analyzer/PythonAnalyzerEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Python.Analysis.Core.DependencyResolution;
using Microsoft.Python.Analysis.Modules;
using Microsoft.Python.Analysis.Types;
using Microsoft.Python.Core;
using Microsoft.Python.Core.Collections;
using Microsoft.Python.Parsing.Ast;

namespace Microsoft.Python.Analysis.Analyzer {
[DebuggerDisplay("{_module.Name}({_module.ModuleType})")]
[DebuggerDisplay("{_module.Name} : {_module.ModuleType}")]
internal sealed class PythonAnalyzerEntry {
private readonly object _syncObj = new object();
private TaskCompletionSource<IDocumentAnalysis> _analysisTcs;
Expand Down Expand Up @@ -248,20 +246,13 @@ public bool Invalidate(IPythonModule module, PythonAst ast, int bufferVersion, i
}

private HashSet<AnalysisModuleKey> FindDependencies(IPythonModule module, PythonAst ast, int bufferVersion) {
if (_bufferVersion > bufferVersion) {
return new HashSet<AnalysisModuleKey>();
}

var walker = new DependencyWalker(module);
ast.Walk(walker);
var dependencies = walker.Dependencies;
dependencies.Remove(new AnalysisModuleKey(module));
var dependencyProvider = (module as IAnalyzable)?.DependencyProvider;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var dependencies = _bufferVersion <= bufferVersion && module is IAnalyzable analyzable && analyzable.DependencyProvider != null
    ? dependencyProvider.GetDependencies()
    : new HashSet<AnalysisModuleKey>();

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

var dependencies = _bufferVersion <= bufferVersion && module is IAnalyzable analyzable && analyzable.DependencyProvider != null
? dependencyProvider.GetDependencies()
: new HashSet<AnalysisModuleKey>();
return dependencies;
}

private static bool Ignore(IModuleManagement moduleResolution, string fullName, string modulePath)
=> moduleResolution.BuiltinModuleName.EqualsOrdinal(fullName) || moduleResolution.IsSpecializedModule(fullName, modulePath);

private void UpdateAnalysisTcs(int analysisVersion) {
_analysisVersion = analysisVersion;
if (_analysisTcs.Task.Status == TaskStatus.RanToCompletion) {
Expand All @@ -273,69 +264,6 @@ private void UpdateAnalysisTcs(int analysisVersion) {
}
}

private class DependencyWalker : PythonWalker {
private readonly IPythonModule _module;
private readonly bool _isTypeshed;
private readonly IModuleManagement _moduleResolution;
private readonly PathResolverSnapshot _pathResolver;

public HashSet<AnalysisModuleKey> Dependencies { get; }

public DependencyWalker(IPythonModule module) {
_module = module;
_isTypeshed = module is StubPythonModule stub && stub.IsTypeshed;
_moduleResolution = module.Interpreter.ModuleResolution;
_pathResolver = _isTypeshed
? module.Interpreter.TypeshedResolution.CurrentPathResolver
: _moduleResolution.CurrentPathResolver;

Dependencies = new HashSet<AnalysisModuleKey>();

if (module.Stub != null) {
Dependencies.Add(new AnalysisModuleKey(module.Stub));
}
}

public override bool Walk(ImportStatement import) {
var forceAbsolute = import.ForceAbsolute;
foreach (var moduleName in import.Names) {
var importNames = ImmutableArray<string>.Empty;
foreach (var nameExpression in moduleName.Names) {
importNames = importNames.Add(nameExpression.Name);
var imports = _pathResolver.GetImportsFromAbsoluteName(_module.FilePath, importNames, forceAbsolute);
HandleSearchResults(imports);
}
}

return false;
}

public override bool Walk(FromImportStatement fromImport) {
var imports = _pathResolver.FindImports(_module.FilePath, fromImport);
HandleSearchResults(imports);
if (imports is IImportChildrenSource childrenSource) {
foreach (var name in fromImport.Names) {
if (childrenSource.TryGetChildImport(name.Name, out var childImport)) {
HandleSearchResults(childImport);
}
}
}

return false;
}

private void HandleSearchResults(IImportSearchResult searchResult) {
switch (searchResult) {
case ModuleImport moduleImport when !Ignore(_moduleResolution, moduleImport.FullName, moduleImport.ModulePath):
Dependencies.Add(new AnalysisModuleKey(moduleImport.FullName, moduleImport.ModulePath, _isTypeshed));
return;
case PossibleModuleImport possibleModuleImport when !Ignore(_moduleResolution, possibleModuleImport.PrecedingModuleFullName, possibleModuleImport.PrecedingModulePath):
Dependencies.Add(new AnalysisModuleKey(possibleModuleImport.PrecedingModuleFullName, possibleModuleImport.PrecedingModulePath, _isTypeshed));
return;
default:
return;
}
}
}
}
}
Loading