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

Commit 80aabe1

Browse files
author
Mikhail Arkhipov
committed
Fix more
1 parent d5774f3 commit 80aabe1

14 files changed

+375
-382
lines changed

src/Analysis/Engine/Impl/Interpreter/Ast/AstAnalysisFunctionWalker.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616

1717
using System;
1818
using System.Collections.Generic;
19+
using System.Diagnostics;
1920
using System.Linq;
2021
using Microsoft.PythonTools.Analysis.Infrastructure;
2122
using Microsoft.PythonTools.Parsing.Ast;
2223

2324
namespace Microsoft.PythonTools.Interpreter.Ast {
25+
[DebuggerDisplay("{Target.Name}")]
2426
class AstAnalysisFunctionWalker : PythonWalker {
2527
private readonly NameLookupContext _scope;
2628
private readonly AstPythonFunctionOverload _overload;
@@ -64,14 +66,24 @@ public void Walk() {
6466
_selfType = (self as AstPythonConstant)?.Type as AstPythonType;
6567

6668
_overload.ReturnTypes.AddRange(_scope.GetTypesFromAnnotation(Target.ReturnAnnotation).ExcludeDefault());
67-
6869
_scope.PushScope();
70+
71+
// Declare self, if any
72+
var skip = 0;
6973
if (self != null) {
7074
var p0 = Target.Parameters.FirstOrDefault();
7175
if (p0 != null && !string.IsNullOrEmpty(p0.Name)) {
7276
_scope.SetInScope(p0.Name, self);
77+
skip++;
7378
}
7479
}
80+
81+
// Declare parameters in scope
82+
foreach(var p in Target.Parameters.Skip(skip).Where(p => !string.IsNullOrEmpty(p.Name))) {
83+
var value = _scope.GetValueFromExpression(p.DefaultValue);
84+
_scope.SetInScope(p.Name, value ?? _scope.UnknownType);
85+
}
86+
7587
Target.Walk(this);
7688
_scope.PopScope();
7789
}
@@ -161,19 +173,28 @@ public override bool Walk(IfStatement node) {
161173
}
162174

163175
public override bool Walk(ReturnStatement node) {
164-
foreach (var type in _scope.GetTypesFromValue(_scope.GetValueFromExpression(node.Expression)).ExcludeDefault()) {
176+
var types = _scope.GetTypesFromValue(_scope.GetValueFromExpression(node.Expression)).ExcludeDefault();
177+
foreach (var type in types) {
165178
_overload.ReturnTypes.Add(type);
166179
}
180+
181+
// Clean up: if there are None or Unknown types along with real ones, remove them.
182+
var realTypes = _overload.ReturnTypes
183+
.Where(t => t.TypeId != BuiltinTypeId.Unknown && t.TypeId != BuiltinTypeId.NoneType)
184+
.ToList();
185+
186+
if (realTypes.Count > 0) {
187+
_overload.ReturnTypes.Clear();
188+
_overload.ReturnTypes.AddRange(realTypes);
189+
}
167190
return true; // We want to evaluate all code so all private variables in __new__ get defined
168191
}
169192

170193
private IMember GetSelf() {
171-
bool classmethod, staticmethod;
172-
GetMethodType(Target, out classmethod, out staticmethod);
194+
GetMethodType(Target, out var classmethod, out var staticmethod);
173195
var self = _scope.LookupNameInScopes("__class__", NameLookupContext.LookupOptions.Local);
174196
if (!staticmethod && !classmethod) {
175-
var cls = self as IPythonType;
176-
if (cls == null) {
197+
if (!(self is IPythonType cls)) {
177198
self = null;
178199
} else {
179200
self = new AstPythonConstant(cls, ((cls as ILocatedMember)?.Locations).MaybeEnumerate().ToArray());

src/Analysis/Engine/Impl/Interpreter/Ast/AstAnalysisFunctionWalkerSet.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
using System.Collections.Generic;
1818
using System.Linq;
19+
using Microsoft.PythonTools.Analysis.Infrastructure;
1920
using Microsoft.PythonTools.Parsing.Ast;
2021

2122
namespace Microsoft.PythonTools.Interpreter.Ast {
@@ -33,8 +34,18 @@ public void Add(AstAnalysisFunctionWalker walker)
3334
=> _functionWalkers[walker.Target] = walker;
3435

3536
public void ProcessSet() {
36-
// Do not use foreach since walker list is dynamically
37-
// modified and walkers are removed as they are done.
37+
// Do not use foreach since walker list is dynamically modified and walkers are removed
38+
// after processing. Handle __init__ and __new__ first so class variables are initialized.
39+
var constructors = _functionWalkers
40+
.Where(kvp => kvp.Key.Name == "__init__" || kvp.Key.Name == "__new__")
41+
.Select(c => c.Value)
42+
.ExcludeDefault()
43+
.ToArray();
44+
45+
foreach (var ctor in constructors) {
46+
ProcessWalker(ctor);
47+
}
48+
3849
while (_functionWalkers.Count > 0) {
3950
var walker = _functionWalkers.First().Value;
4051
ProcessWalker(walker);
@@ -50,6 +61,7 @@ public void ProcessFunction(FunctionDefinition fn) {
5061
private void ProcessWalker(AstAnalysisFunctionWalker walker) {
5162
// Remove walker before processing as to prevent reentrancy.
5263
_functionWalkers.Remove(walker.Target);
64+
var z = walker.Target.Name == "day";
5365
walker.Walk();
5466
}
5567
}

0 commit comments

Comments
 (0)