This repository was archived by the owner on Apr 14, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 132
Expand file tree
/
Copy pathModuleSymbolTable.cs
More file actions
100 lines (90 loc) · 4.36 KB
/
ModuleSymbolTable.cs
File metadata and controls
100 lines (90 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright(c) Microsoft Corporation
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the License); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABILITY OR NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing
// permissions and limitations under the License.
using System.Collections.Generic;
using System.Linq;
using Microsoft.Python.Analysis.Analyzer.Evaluation;
using Microsoft.Python.Analysis.Types;
using Microsoft.Python.Parsing.Ast;
namespace Microsoft.Python.Analysis.Analyzer.Symbols {
/// <summary>
/// Represents set of function body walkers. Functions are walked after
/// all classes are collected. If function or property return type is unknown,
/// it can be walked, and so on recursively, until return type is determined
/// or there is nothing left to walk.
/// </summary>
internal sealed class ModuleSymbolTable {
private readonly Dictionary<ScopeStatement, MemberEvaluator> _evaluators = new Dictionary<ScopeStatement, MemberEvaluator>();
private readonly HashSet<ScopeStatement> _processed = new HashSet<ScopeStatement>();
public IEnumerable<KeyValuePair<ScopeStatement, MemberEvaluator>> Evaluators => _evaluators.ToArray();
public void Add(MemberEvaluator e) => _evaluators[e.Target] = e;
public bool Contains(ScopeStatement node) => _evaluators.ContainsKey(node) || _processed.Contains(node);
public void Build(ExpressionEval eval)
// This part only adds definition for the function and its overloads
// to the walker list. It does NOT resolve return types or parameters.
// Function body is not walked. For the actual function code walk
// and the type resolution see FunctionWalker class.
=> SymbolCollector.CollectSymbols(this, eval);
public void EvaluateAll() {
// Evaluate top-level functions first.
while (_evaluators.Count > 0) {
var walker = _evaluators.FirstOrDefault(e => e.Value.Target is FunctionDefinition fd && fd.Parent == null).Value;
if (walker == null) {
break;
}
Evaluate(walker);
}
// Evaluate classes.
while (_evaluators.Count > 0) {
var walker = _evaluators.FirstOrDefault(e => e.Value.Target is ClassDefinition).Value;
if (walker == null) {
break;
}
Evaluate(walker);
}
// Do not use foreach since walker list is dynamically modified and walkers are removed
// after processing. Handle __init__ and __new__ first so class variables are initialized.
while (_evaluators.Count > 0) {
var walker = _evaluators.First().Value;
Evaluate(walker);
}
}
public void EvaluateScope(ScopeStatement target) {
// Do not use foreach since walker list is dynamically modified and walkers are removed
// after processing. Handle __init__ and __new__ first so class variables are initialized.
while (_evaluators.Count > 0) {
var member = _evaluators.Keys.FirstOrDefault(w => w.Parent == target);
if (member == null) {
break;
}
Evaluate(_evaluators[member]);
}
}
public IMember Evaluate(ScopeStatement target) {
if (target != null && _evaluators.TryGetValue(target, out var w)) {
Evaluate(w);
return w.Result;
}
return null;
}
public void Evaluate(MemberEvaluator e) {
// Remove walker before processing as to prevent reentrancy.
// NOTE: first add then remove so we don't get moment when
// walker is missing from either set.
_processed.Add(e.Target);
_evaluators.Remove(e.Target);
e.Evaluate();
}
}
}