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

Commit 0833135

Browse files
committed
Merge remote-tracking branch 'Microsoft/master'
2 parents 6e9f719 + b29a87f commit 0833135

File tree

15 files changed

+268
-211
lines changed

15 files changed

+268
-211
lines changed

src/.editorconfig

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
root = true
2+
[*.cs]
3+
4+
end_of_line = crlf
5+
6+
indent_size = 4
7+
8+
indent_style = space
9+
10+
insert_final_newline = false
11+
12+
tab_width = 4
13+
14+
csharp_space_between_method_declaration_name_and_open_parenthesis = false
15+
16+
csharp_space_between_method_declaration_parameter_list_parentheses = false
17+
18+
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
19+
20+
csharp_space_between_method_call_name_and_opening_parenthesis = false
21+
22+
csharp_space_between_method_call_parameter_list_parentheses = false
23+
24+
csharp_space_between_method_call_empty_parameter_list_parentheses = false
25+
26+
csharp_space_after_keywords_in_control_flow_statements = true
27+
28+
csharp_space_between_parentheses = None
29+
30+
csharp_space_after_cast = false
31+
32+
csharp_style_inlined_variable_declaration = true:error
33+
34+
csharp_space_before_open_square_brackets = false
35+
36+
csharp_space_between_empty_square_brackets = false
37+
38+
csharp_space_between_square_brackets = false
39+
40+
csharp_space_after_colon_in_inheritance_clause = true
41+
42+
csharp_space_after_comma = true
43+
44+
csharp_space_after_dot = false
45+
46+
csharp_space_after_semicolon_in_for_statement = true
47+
48+
csharp_space_before_colon_in_inheritance_clause = true
49+
50+
csharp_space_before_comma = false
51+
52+
csharp_space_before_dot = false
53+
54+
csharp_space_before_semicolon_in_for_statement = false
55+
56+
csharp_space_around_binary_operators = before_and_after
57+
58+
csharp_indent_braces = false
59+
60+
csharp_indent_block = true
61+
62+
csharp_indent_switch_labels = true
63+
64+
csharp_preserve_single_line_blocks = true
65+
66+
csharp_preserve_single_line_statements = true
67+
68+
csharp_new_line_before_open_brace = none
69+
70+
csharp_new_line_before_catch = false
71+
72+
csharp_new_line_before_else = false
73+
74+
csharp_new_line_before_finally = false
75+
76+
csharp_new_line_before_members_in_anonymous_types = false
77+
78+
csharp_new_line_before_members_in_object_initializers = false

src/Analysis/Engine/Impl/AnalysisVariable.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,18 @@
1616

1717
namespace Microsoft.PythonTools.Analysis {
1818
class AnalysisVariable : IAnalysisVariable {
19-
public AnalysisVariable(VariableType type, ILocationInfo location, int? version = null) {
19+
public AnalysisVariable(IVariableDefinition variable, VariableType type, ILocationInfo location, int? version = null) {
20+
Variable = variable;
2021
Location = location;
2122
Type = type;
2223
Version = version;
2324
}
2425

2526
#region IAnalysisVariable Members
26-
2727
public ILocationInfo Location { get; }
28-
2928
public VariableType Type { get; }
30-
3129
public int? Version { get; }
32-
30+
public IVariableDefinition Variable { get; }
3331
#endregion
3432

3533
public override bool Equals(object obj) {

src/Analysis/Engine/Impl/Definitions/IAnalysisVariable.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@ public interface IAnalysisVariable {
2222
ILocationInfo Location { get; }
2323

2424
VariableType Type { get; }
25+
26+
IVariableDefinition Variable { get; }
2527
}
2628
}

src/Analysis/Engine/Impl/Deque.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ public void AppendLeft(T x) {
8282
}
8383

8484
public void Clear() {
85-
AssertScope();
86-
8785
_version++;
8886

8987
_head = _tail = 0;

src/Analysis/Engine/Impl/ModuleAnalysis.cs

Lines changed: 100 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,10 @@ private static IAnalysisSet ResolveAndAdd(AnalysisUnit unit, IAnalysisSet set, A
113113
return set.Union(value.Resolve(unit));
114114
}
115115

116-
internal IEnumerable<AnalysisVariable> ToVariables(IReferenceable referenceable) {
117-
if (referenceable is VariableDef def) {
116+
internal static IEnumerable<AnalysisVariable> ToVariables(IReferenceable referenceable) {
117+
var def = referenceable as VariableDef;
118+
119+
if (def != null) {
118120
foreach (var type in def.Types.WhereNotNull()) {
119121
var varType = VariableType.Value;
120122
if (type.DeclaringModule == null) {
@@ -123,22 +125,22 @@ internal IEnumerable<AnalysisVariable> ToVariables(IReferenceable referenceable)
123125
}
124126

125127
foreach (var loc in type.Locations.WhereNotNull()) {
126-
yield return new AnalysisVariable(varType, loc);
128+
yield return new AnalysisVariable(def, varType, loc);
127129
}
128130
}
129131
}
130132

131133
foreach (var reference in referenceable.Definitions) {
132134
var loc = reference.GetLocationInfo();
133135
if (loc != null) {
134-
yield return new AnalysisVariable(VariableType.Definition, loc);
136+
yield return new AnalysisVariable(def, VariableType.Definition, loc);
135137
}
136138
}
137139

138140
foreach (var reference in referenceable.References) {
139141
var loc = reference.GetLocationInfo();
140142
if (loc != null) {
141-
yield return new AnalysisVariable(VariableType.Reference, loc);
143+
yield return new AnalysisVariable(def, VariableType.Reference, loc);
142144
}
143145
}
144146
}
@@ -208,10 +210,22 @@ public VariablesResult GetVariables(Expression expr, SourceLocation location, st
208210

209211
var unit = GetNearestEnclosingAnalysisUnit(scope);
210212
var tree = unit.Tree;
211-
212213
var eval = new ExpressionEvaluator(unit.CopyForEval(), scope, mergeScopes: true);
213-
var variables = Enumerable.Empty<IAnalysisVariable>();
214214

215+
var result = GetVariablesFromCallExpression(unit, eval, scope, location, originalText);
216+
if (result != null) {
217+
return result;
218+
}
219+
220+
result = GetVariablesFromNameExpression(expr, unit, scope);
221+
if (result != null) {
222+
return result;
223+
}
224+
225+
return GetVariablesFromMemberExpression(expr, unit, eval);
226+
}
227+
228+
private static VariablesResult GetVariablesFromCallExpression(AnalysisUnit unit, ExpressionEvaluator eval, IScope scope, SourceLocation location, string originalText) {
215229
var finder = new ExpressionFinder(unit.Tree, new GetExpressionOptions { Calls = true });
216230
var callNode = finder.GetExpression(location) as CallExpression;
217231
if (callNode != null) {
@@ -229,29 +243,95 @@ public VariablesResult GetVariables(Expression expr, SourceLocation location, st
229243
unit.Tree);
230244
}
231245
}
246+
return null;
247+
}
232248

233-
if (expr is NameExpression name) {
234-
if (!scope.EnumerateTowardsGlobal.Any()) {
235-
variables = _unit.State.BuiltinModule.GetDefinitions(name.Name).SelectMany(ToVariables);
236-
} else {
237-
foreach (var defScope in scope.EnumerateTowardsGlobal
238-
.Where(s => s.ContainsVariable(name.Name) && (s == scope || s.VisibleToChildren || IsFirstLineOfFunction(scope, s, location)))) {
239-
var scopeVariables = GetVariablesInScope(name, defScope).Distinct();
240-
variables = variables.Union(scopeVariables);
241-
}
249+
private class VariableScopePair : Tuple<IAnalysisVariable, int> {
250+
public VariableScopePair(IAnalysisVariable v, int scopeLevel) : base(v, scopeLevel) { }
251+
public IAnalysisVariable Variable => Item1;
252+
public int ScopeLevel => Item2;
253+
public VariableType VariableType => Variable.Type;
254+
public ILocationInfo Location => Variable.Location;
255+
}
256+
257+
private VariablesResult GetVariablesFromNameExpression(Expression expr, AnalysisUnit unit, IScope scope) {
258+
if (!(expr is NameExpression name)) {
259+
return null;
260+
}
261+
262+
if (!scope.EnumerateTowardsGlobal.Any()) {
263+
var v = _unit.State.BuiltinModule.GetDefinitions(name.Name).SelectMany(ToVariables);
264+
return new VariablesResult(v, unit.Tree);
265+
}
266+
267+
var variables = Enumerable.Empty<VariableScopePair>();
268+
VariableScopePair mainDefinition = null;
269+
var scopeLevel = 0;
270+
foreach (var s in scope.EnumerateTowardsGlobal) {
271+
var scopeVariables = GetVariablesInScope(name, s)
272+
.Distinct()
273+
.Select(v => new VariableScopePair(v, scopeLevel))
274+
.ToArray();
275+
276+
variables = variables.Union(scopeVariables);
277+
278+
// If we already have definition and it is a function argument, then stop
279+
// since function argument wins over definitions in the outer scope
280+
mainDefinition = scopeVariables.FirstOrDefault(v => v.VariableType == VariableType.Definition && IsFunctionArgument(s, v.Variable));
281+
if (mainDefinition != null) {
282+
break;
242283
}
243-
} else if (expr is MemberExpression member && !string.IsNullOrEmpty(member.Name)) {
244-
var objects = eval.Evaluate(member.Target);
284+
scopeLevel++;
285+
}
286+
287+
// Now take innermost definition and treat inner ones (such as reassignments) as references
288+
var definitions = variables
289+
.Where(v => v.VariableType == VariableType.Definition)
290+
.OrderBy(v => v.Location.Span.Start)
291+
.Reverse()
292+
.ToArray();
293+
294+
mainDefinition = mainDefinition ?? definitions.FirstOrDefault();
295+
if (mainDefinition != null) {
296+
// Drop definitions in outer scopes and convert those in inner scopes to references.
297+
// Scope levels are numbered in reverse (X == main definition level, x+1 == one up).
298+
var defsToRefs = definitions
299+
.Where(d => d != mainDefinition && d.ScopeLevel <= mainDefinition.ScopeLevel)
300+
.Select(v => new VariableScopePair(new AnalysisVariable(v.Variable.Variable, VariableType.Reference, v.Location), v.ScopeLevel));
301+
302+
var others = variables
303+
.Where(v => (v.VariableType == VariableType.Reference || v.VariableType == VariableType.Value) &&
304+
v.ScopeLevel <= mainDefinition.ScopeLevel);
305+
variables = new[] { mainDefinition }.Concat(others.Concat(defsToRefs));
306+
}
307+
308+
return new VariablesResult(variables.Select(v => v.Variable), unit.Tree);
309+
}
245310

311+
private VariablesResult GetVariablesFromMemberExpression(Expression expr, AnalysisUnit unit, ExpressionEvaluator eval) {
312+
var variables = Enumerable.Empty<IAnalysisVariable>();
313+
if (expr is MemberExpression member && !string.IsNullOrEmpty(member.Name)) {
314+
var objects = eval.Evaluate(member.Target);
246315
foreach (var v in objects.OfType<IReferenceableContainer>()) {
247316
variables = variables.Union(v.GetDefinitions(member.Name).SelectMany(ToVariables));
248317
}
249318
}
250-
251319
return new VariablesResult(variables, unit.Tree);
252320
}
253321

254-
private IEnumerable<IAnalysisVariable> GetVariablesInScope(NameExpression name, IScope scope) {
322+
private bool IsFunctionArgument(IScope scope, IAnalysisVariable v) {
323+
if (v.Variable?.Types?.MaybeEnumerate().FirstOrDefault() is ParameterInfo) {
324+
return true;
325+
}
326+
if (scope is FunctionScope funcScope) {
327+
var funcDef = funcScope.Function.FunctionDefinition;
328+
var varSpan = v.Location.Span.ToLinearSpan(_unit.Tree);
329+
return funcDef.NameExpression.EndIndex <= varSpan.Start && varSpan.End <= funcDef.HeaderIndex;
330+
}
331+
return false;
332+
}
333+
334+
private static IEnumerable<IAnalysisVariable> GetVariablesInScope(NameExpression name, IScope scope) {
255335
var result = new List<IAnalysisVariable>();
256336

257337
result.AddRange(scope.GetMergedVariables(name.Name).SelectMany(ToVariables));
@@ -289,19 +369,6 @@ private IEnumerable<IAnalysisVariable> GetVariablesInScope(NameExpression name,
289369
return result;
290370
}
291371

292-
private static bool IsFirstLineOfFunction(IScope innerScope, IScope outerScope, SourceLocation location) {
293-
if (innerScope.OuterScope == outerScope && innerScope is FunctionScope) {
294-
var funcScope = (FunctionScope)innerScope;
295-
var def = funcScope.Function.FunctionDefinition;
296-
297-
// TODO: Use indexes rather than lines to check location
298-
if (location.Line == def.GetStart(def.GlobalParent).Line) {
299-
return true;
300-
}
301-
}
302-
return false;
303-
}
304-
305372
private class ErrorWalker : PythonWalker {
306373
public bool HasError { get; private set; }
307374

src/Analysis/Engine/Impl/PythonAnalyzer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,7 @@ public void Dispose() {
985985

986986
protected virtual void Dispose(bool disposing) {
987987
if (disposing) {
988+
Queue.Clear();
988989
IDisposable interpreter = _interpreter as IDisposable;
989990
if (_disposeInterpreter && interpreter != null) {
990991
interpreter.Dispose();

0 commit comments

Comments
 (0)