Skip to content
This repository was archived by the owner on Nov 4, 2024. It is now read-only.

Commit 62f76e1

Browse files
author
Mikhail Arkhipov
authored
Merge pull request microsoft#339 from MikhailArkhipov/15-2
Handle named tuples
2 parents cc4700d + cb0be90 commit 62f76e1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1095
-897
lines changed

src/Analysis/Engine/Impl/AnalysisValueSetExtensions.cs

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,8 @@ public static IAnalysisSet Call(this IAnalysisSet self, Node node, AnalysisUnit
7878
foreach (var ns in self) {
7979
var call = ns.Call(node, unit, args, keywordArgNames);
8080
Debug.Assert(call != null);
81-
8281
res = res.Union(call);
8382
}
84-
8583
return res;
8684
}
8785

@@ -95,7 +93,6 @@ public static IAnalysisSet GetIterator(this IAnalysisSet self, Node node, Analys
9593
foreach (var ns in self) {
9694
res = res.Union(ns.GetIterator(node, unit));
9795
}
98-
9996
return res;
10097
}
10198

@@ -109,7 +106,6 @@ public static IAnalysisSet GetAsyncIterator(this IAnalysisSet self, Node node, A
109106
foreach (var ns in self) {
110107
res = res.Union(ns.GetAsyncIterator(node, unit));
111108
}
112-
113109
return res;
114110
}
115111

@@ -122,7 +118,6 @@ public static IAnalysisSet GetIndex(this IAnalysisSet self, Node node, AnalysisU
122118
foreach (var ns in self) {
123119
res = res.Union(ns.GetIndex(node, unit, index));
124120
}
125-
126121
return res;
127122
}
128123

@@ -140,8 +135,7 @@ public static void SetIndex(this IAnalysisSet self, Node node, AnalysisUnit unit
140135
/// Performs a delete index operation propagating the index types into
141136
/// the provided object.
142137
/// </summary>
143-
public static void DeleteIndex(this IAnalysisSet self, Node node, AnalysisUnit unit, IAnalysisSet index) {
144-
}
138+
public static void DeleteIndex(this IAnalysisSet self, Node node, AnalysisUnit unit, IAnalysisSet index) { }
145139

146140
/// <summary>
147141
/// Performs an augmented assignment propagating the value into the
@@ -163,7 +157,6 @@ public static IAnalysisSet GetEnumeratorTypes(this IAnalysisSet self, Node node,
163157
foreach (var ns in self) {
164158
res = res.Union(ns.GetEnumeratorTypes(node, unit));
165159
}
166-
167160
return res;
168161
}
169162
/// <summary>
@@ -176,7 +169,6 @@ public static IAnalysisSet GetAsyncEnumeratorTypes(this IAnalysisSet self, Node
176169
foreach (var ns in self) {
177170
res = res.Union(ns.GetAsyncEnumeratorTypes(node, unit));
178171
}
179-
180172
return res;
181173
}
182174

@@ -188,7 +180,6 @@ public static IAnalysisSet GetDescriptor(this IAnalysisSet self, Node node, Anal
188180
foreach (var ns in self) {
189181
res = res.Union(ns.GetDescriptor(node, instance, context, unit));
190182
}
191-
192183
return res;
193184
}
194185

@@ -200,7 +191,6 @@ public static IAnalysisSet BinaryOperation(this IAnalysisSet self, Node node, An
200191
foreach (var ns in self) {
201192
res = res.Union(ns.BinaryOperation(node, unit, operation, rhs));
202193
}
203-
204194
return res;
205195
}
206196

@@ -212,7 +202,6 @@ public static IAnalysisSet UnaryOperation(this IAnalysisSet self, Node node, Ana
212202
foreach (var ns in self) {
213203
res = res.Union(ns.UnaryOperation(node, unit, operation));
214204
}
215-
216205
return res;
217206
}
218207

@@ -228,9 +217,8 @@ internal static AnalysisValue GetUnionType(this IAnalysisSet types) {
228217
/// <summary>
229218
/// Gets instance representations of all members of the set.
230219
/// </summary>
231-
public static IAnalysisSet GetInstanceType(this IAnalysisSet types) {
232-
return AnalysisSet.Create(types.SelectMany(ns => ns.GetInstanceType()));
233-
}
220+
public static IAnalysisSet GetInstanceType(this IAnalysisSet types)
221+
=> AnalysisSet.Create(types.SelectMany(ns => (ns.PythonType as IPythonType2)?.IsClass == true ? ns : ns.GetInstanceType()));
234222

235223
public static bool IsUnknown(this IAnalysisSet res) {
236224
return res == null ||
@@ -241,17 +229,15 @@ public static bool IsUnknown(this IAnalysisSet res) {
241229
/// <summary>
242230
/// Returns true if the set contains no or only the object or unknown types
243231
/// </summary>
244-
public static bool IsObjectOrUnknown(this IAnalysisSet res) {
245-
return res.IsUnknown() || res.All(v => v.TypeId == BuiltinTypeId.Object);
246-
}
232+
public static bool IsObjectOrUnknown(this IAnalysisSet res)
233+
=> res.IsUnknown() || res.All(v => v.TypeId == BuiltinTypeId.Object);
247234

248235
/// <summary>
249236
/// Returns true if the set contains no types, only the object or unknown
250237
/// types, or None.
251238
/// </summary>
252-
public static bool IsObjectOrUnknownOrNone(this IAnalysisSet res) {
253-
return res.IsObjectOrUnknown() || res.All(v => v.TypeId == BuiltinTypeId.NoneType);
254-
}
239+
public static bool IsObjectOrUnknownOrNone(this IAnalysisSet res)
240+
=> res.IsObjectOrUnknown() || res.All(v => v.TypeId == BuiltinTypeId.NoneType);
255241

256242
/// <summary>
257243
/// Returns a sequence of all recognized string values in the set.

src/Analysis/Engine/Impl/Analyzer/ExpressionEvaluator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ internal void AssignTo(Node assignStmt, Expression left, IAnalysisSet values) {
530530
// list/tuple
531531
var l = (SequenceExpression)left;
532532
var valuesArr = values.ToArray();
533-
for (int i = 0; i < l.Items.Count; i++) {
533+
for (var i = 0; i < l.Items.Count; i++) {
534534
if (valuesArr.Length > 0) {
535535
foreach (var value in valuesArr) {
536536
AssignTo(assignStmt, l.Items[i], value.GetIndex(assignStmt, _unit, ProjectState.GetConstant(i)));

src/Analysis/Engine/Impl/Analyzer/FunctionAnalysisUnit.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@
99
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
1010
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
1111
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
12-
// MERCHANTABLITY OR NON-INFRINGEMENT.
12+
// MERCHANTABILITY OR NON-INFRINGEMENT.
1313
//
1414
// See the Apache Version 2.0 License for specific language governing
1515
// permissions and limitations under the License.
1616

1717
using System.Collections.Generic;
18-
using System.Diagnostics;
1918
using System.Linq;
2019
using System.Threading;
2120
using Microsoft.PythonTools.Analysis.Infrastructure;

src/Analysis/Engine/Impl/Interpreter/AnalysisOnlyInterpreterFactory.cs

Lines changed: 0 additions & 110 deletions
This file was deleted.

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

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,21 @@
99
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
1010
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
1111
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
12-
// MERCHANTABLITY OR NON-INFRINGEMENT.
12+
// MERCHANTABILITY OR NON-INFRINGEMENT.
1313
//
1414
// See the Apache Version 2.0 License for specific language governing
1515
// permissions and limitations under the License.
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 {
25-
private readonly FunctionDefinition _target;
2627
private readonly NameLookupContext _scope;
2728
private readonly AstPythonFunctionOverload _overload;
2829
private AstPythonType _selfType;
@@ -33,12 +34,11 @@ public AstAnalysisFunctionWalker(
3334
AstPythonFunctionOverload overload
3435
) {
3536
_scope = scope ?? throw new ArgumentNullException(nameof(scope));
36-
_target = targetFunction ?? throw new ArgumentNullException(nameof(targetFunction));
37+
Target = targetFunction ?? throw new ArgumentNullException(nameof(targetFunction));
3738
_overload = overload ?? throw new ArgumentNullException(nameof(overload));
3839
}
3940

40-
public IList<IPythonType> ReturnTypes => _overload.ReturnTypes;
41-
public IPythonFunctionOverload Overload => _overload;
41+
public FunctionDefinition Target { get; }
4242

4343
private void GetMethodType(FunctionDefinition node, out bool classmethod, out bool staticmethod) {
4444
classmethod = false;
@@ -51,7 +51,7 @@ private void GetMethodType(FunctionDefinition node, out bool classmethod, out bo
5151

5252
var classmethodObj = _scope.Interpreter.GetBuiltinType(BuiltinTypeId.ClassMethod);
5353
var staticmethodObj = _scope.Interpreter.GetBuiltinType(BuiltinTypeId.StaticMethod);
54-
foreach (var d in (_target.Decorators?.Decorators).MaybeEnumerate().ExcludeDefault()) {
54+
foreach (var d in (Target.Decorators?.Decorators).MaybeEnumerate().ExcludeDefault()) {
5555
var m = _scope.GetValueFromExpression(d);
5656
if (m == classmethodObj) {
5757
classmethod = true;
@@ -65,21 +65,31 @@ public void Walk() {
6565
var self = GetSelf();
6666
_selfType = (self as AstPythonConstant)?.Type as AstPythonType;
6767

68-
_overload.ReturnTypes.AddRange(_scope.GetTypesFromAnnotation(_target.ReturnAnnotation).ExcludeDefault());
69-
68+
_overload.ReturnTypes.AddRange(_scope.GetTypesFromAnnotation(Target.ReturnAnnotation).ExcludeDefault());
7069
_scope.PushScope();
70+
71+
// Declare self, if any
72+
var skip = 0;
7173
if (self != null) {
72-
var p0 = _target.Parameters.FirstOrDefault();
74+
var p0 = Target.Parameters.FirstOrDefault();
7375
if (p0 != null && !string.IsNullOrEmpty(p0.Name)) {
7476
_scope.SetInScope(p0.Name, self);
77+
skip++;
7578
}
7679
}
77-
_target.Walk(this);
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+
87+
Target.Walk(this);
7888
_scope.PopScope();
7989
}
8090

8191
public override bool Walk(FunctionDefinition node) {
82-
if (node != _target) {
92+
if (node != Target) {
8393
// Do not walk nested functions (yet)
8494
return false;
8595
}
@@ -163,19 +173,28 @@ public override bool Walk(IfStatement node) {
163173
}
164174

165175
public override bool Walk(ReturnStatement node) {
166-
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) {
167178
_overload.ReturnTypes.Add(type);
168179
}
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+
}
169190
return true; // We want to evaluate all code so all private variables in __new__ get defined
170191
}
171192

172193
private IMember GetSelf() {
173-
bool classmethod, staticmethod;
174-
GetMethodType(_target, out classmethod, out staticmethod);
194+
GetMethodType(Target, out var classmethod, out var staticmethod);
175195
var self = _scope.LookupNameInScopes("__class__", NameLookupContext.LookupOptions.Local);
176196
if (!staticmethod && !classmethod) {
177-
var cls = self as IPythonType;
178-
if (cls == null) {
197+
if (!(self is IPythonType cls)) {
179198
self = null;
180199
} else {
181200
self = new AstPythonConstant(cls, ((cls as ILocatedMember)?.Locations).MaybeEnumerate().ToArray());

0 commit comments

Comments
 (0)