PageRenderTime 57ms CodeModel.GetById 15ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 1ms

/Tools/IronStudio/AnalysisTest/AnalysisTest.cs

http://github.com/IronLanguages/main
C# | 1991 lines | 1846 code | 132 blank | 13 comment | 31 complexity | a2a52c28c45f7322f08e23f6dd8250d3 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/* ****************************************************************************
   2 *
   3 * Copyright (c) Microsoft Corporation. 
   4 *
   5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
   6 * copy of the license can be found in the License.html file at the root of this distribution. If 
   7 * you cannot locate the Apache License, Version 2.0, please send an email to 
   8 * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
   9 * by the terms of the Apache License, Version 2.0.
  10 *
  11 * You must not remove this notice, or any other, from this software.
  12 *
  13 * ***************************************************************************/
  14
  15using System;
  16using System.Collections.Generic;
  17using System.IO;
  18using System.Linq;
  19using System.Numerics;
  20using System.Text;
  21using IronPython.Hosting;
  22using IronPython.Runtime;
  23using IronPython.Runtime.Types;
  24using Microsoft.IronPythonTools.Intellisense;
  25using Microsoft.PyAnalysis;
  26using Microsoft.PyAnalysis.Values;
  27using Microsoft.Scripting;
  28using Microsoft.Scripting.Hosting;
  29using Microsoft.Scripting.Hosting.Providers;
  30using Microsoft.Scripting.Library;
  31using Microsoft.Scripting.Utils;
  32using Microsoft.VisualStudio.TestTools.UnitTesting;
  33using System.Diagnostics;
  34using IronPython.Runtime.Exceptions;
  35
  36namespace AnalysisTest {
  37    [TestClass]
  38    public partial class AnalysisTest {
  39        private static ScriptEngine _engine;
  40        private static PythonType PyObjectType, IntType, StringType, FloatType, TypeType, ListType, TupleType, BoolType, FunctionType, ComplexType, GeneratorType;
  41        private static string[] _objectMembers, _objectMembersClr, _functionMembers;
  42        private static string[] _strMembers, _strMembersClr;
  43        private static string[] _listMembers, _intMembers;
  44
  45        public static int Main(string[] args) {
  46            AnalysisTest test = new AnalysisTest();
  47
  48            if (args.Length > 0 && args[0] == "PERF") {
  49                args = ArrayUtils.ShiftLeft(args, 1);
  50                return test.RunTests(args, typeof(PerfMethodAttribute));
  51            }
  52
  53            return test.RunTests(args, typeof(TestMethodAttribute)); 
  54        }
  55
  56        private int RunTests(string[] args, Type testAttr) {            
  57            var fg = Console.ForegroundColor;
  58            int failures = 0;
  59            foreach (var mi in typeof(AnalysisTest).GetMethods()) {
  60                if ((args.Length == 0 || (args.Length > 0 && args.Contains(mi.Name))) &&
  61                    mi.IsDefined(testAttr, false)) {
  62
  63                    try {
  64                        mi.Invoke(this, new object[0]);
  65                        Console.ForegroundColor = ConsoleColor.Green;
  66                        Console.WriteLine("Test passed: {0}", mi.Name);
  67                    } catch (Exception e) {
  68                        Console.ForegroundColor = ConsoleColor.Red;
  69                        Console.WriteLine("Test failed: {0}", mi.Name);
  70                        Console.ForegroundColor = ConsoleColor.Gray;
  71                        Console.WriteLine(e);
  72                        failures++;
  73                    }
  74                }
  75            }
  76
  77            Console.WriteLine();
  78            if (failures == 0) {
  79                Console.ForegroundColor = ConsoleColor.Green;
  80                Console.WriteLine("No failures");
  81            } else {
  82                Console.ForegroundColor = ConsoleColor.Red;
  83                Console.WriteLine("{0} failures", failures);
  84            }
  85            Console.ForegroundColor = fg;
  86            return failures;
  87        }
  88
  89        #region Test Cases
  90
  91        [TestMethod]
  92        public void TestImportStar() {
  93            var entry = ProcessText(@"
  94from nt import *
  95            ");
  96
  97            var members = entry.GetMembers("", 1).Select(x => x.Name);
  98
  99            AssertContains(members, "abort");
 100
 101            entry = ProcessText(@"");
 102
 103            // make sure abort hasn't become a builtin, if so this test needs to be updated
 104            // with a new name
 105            members = entry.GetMembers("", 1).Select(x => x.Name);
 106            foreach (var member in members) {
 107                if(member == "abort") {
 108                    Assert.Fail("abort has become a builtin, or a clean module includes it for some reason");
 109                }
 110            }
 111        }
 112
 113        [TestMethod]
 114        public void TestMutatingReferences() {
 115            var state = new ProjectState(_engine);
 116
 117            var text1 = @"
 118import mod2
 119
 120class C(object):
 121    def SomeMethod(self):
 122        pass
 123
 124mod2.D(C())
 125";
 126
 127            var text2 = @"
 128class D(object):
 129    def __init__(self, value):
 130        self.value = value
 131        self.value.SomeMethod()
 132";
 133
 134            var mod1 = ParseText(state, GetSourceUnit(text1, "mod1"), "mod1");
 135            var mod2 = ParseText(state, GetSourceUnit(text2, "mod2"), "mod2");
 136
 137            VerifyReferences(mod1.Analysis.GetVariables("SomeMethod", GetLineNumber(text1, "SomeMethod")), 
 138                new VariableLocation(5, 5, VariableType.Definition), new VariableLocation(5, 9, VariableType.Reference));
 139
 140            // mutate 1st file
 141            text1 = text1.Substring(0, text1.IndexOf("    def")) + Environment.NewLine + text1.Substring(text1.IndexOf("    def"));
 142            Prepare(mod1, GetSourceUnit(text1, "mod1"));
 143            mod1.Analyze();
 144            
 145            VerifyReferences(mod1.Analysis.GetVariables("SomeMethod", GetLineNumber(text1, "SomeMethod")),
 146                new VariableLocation(6, 5, VariableType.Definition), new VariableLocation(5, 9, VariableType.Reference));
 147
 148            // mutate 2nd file
 149            text2 = Environment.NewLine + text2;
 150            Prepare(mod2, GetSourceUnit(text2, "mod1"));
 151            mod2.Analyze();
 152
 153            VerifyReferences(mod1.Analysis.GetVariables("SomeMethod", GetLineNumber(text1, "SomeMethod")),
 154                new VariableLocation(6, 5, VariableType.Definition), new VariableLocation(6, 9, VariableType.Reference));
 155
 156        }
 157
 158        /// <summary>
 159        /// Verify importing wpf will add a reference to the WPF assemblies
 160        /// </summary>
 161        [TestMethod]
 162        public void TestWpfReferences() {
 163            var entry = ProcessText(@"
 164import wpf
 165from System.Windows.Media import Colors
 166");
 167
 168            AssertContains(entry.GetMembersFromName("Colors", 1), "Blue");
 169        }
 170
 171        [TestMethod]
 172        public void TestGenerator() {
 173            var entry = ProcessText(@"
 174def f():
 175    yield 1
 176    yield 2
 177    yield 3
 178
 179a = f()
 180b = a.next()
 181
 182for c in f():
 183    print c
 184            ");
 185
 186            AssertContainsExactly(entry.GetTypesFromName("a", 1), GeneratorType);
 187            AssertContainsExactly(entry.GetTypesFromName("b", 1), IntType);
 188            AssertContainsExactly(entry.GetTypesFromName("c", 1), IntType);
 189
 190            var text = @"
 191def f():
 192    yield 1
 193    x = yield 2
 194
 195a = f()
 196b = a.next()
 197c = a.send('abc')";
 198            entry = ProcessText(text);
 199
 200            AssertContainsExactly(entry.GetTypesFromName("a", 1), GeneratorType);
 201            AssertContainsExactly(entry.GetTypesFromName("b", 1), IntType);
 202            AssertContainsExactly(entry.GetTypesFromName("c", 1), IntType);
 203            AssertContainsExactly(entry.GetTypesFromName("x", GetLineNumber(text, "yield 2")), StringType);
 204        }
 205
 206        [TestMethod]
 207        public void TestEnum() {
 208            var entry = ProcessText(@"
 209import System
 210x = System.StringComparison.OrdinalIgnoreCase
 211            ");
 212
 213            var x = entry.GetValues("x", 1).First();
 214            Assert.AreEqual(x.ResultType, ResultType.EnumInstance);
 215        }
 216
 217        /*
 218        [TestMethod]
 219        public void TestListComprehensions() {
 220            var entry = ProcessText(@"
 221x = [2,3,4]
 222y = [a for a in x]
 223z = y[0]
 224            ");
 225
 226            AssertContainsExactly(entry.GetTypesFromName("z", 0), IntType);
 227        }*/
 228
 229        [TestMethod]
 230        public void TestForSequence() {
 231            var entry = ProcessText(@"
 232x = [('abc', 42, True), ('abc', 23, False),]
 233for some_str, some_int, some_bool in x:
 234	print some_str		
 235	print some_int		
 236    print some_bool	    
 237");
 238            AssertContainsExactly(entry.GetTypesFromName("some_str", 1), StringType);
 239            AssertContainsExactly(entry.GetTypesFromName("some_int", 1), IntType);
 240            AssertContainsExactly(entry.GetTypesFromName("some_bool", 1), BoolType);
 241        }
 242
 243        [TestMethod]
 244        public void TestDynamicAttributes() {
 245            var entry = ProcessText(@"
 246class x(object):
 247    def __getattr__(self, name):
 248        return 42
 249    def f(self): 
 250        return 'abc'
 251        
 252a = x().abc
 253b = x().f()
 254
 255class y(object):
 256    def __getattribute__(self, x):
 257        return 'abc'
 258        
 259c = y().abc
 260");
 261
 262            AssertContainsExactly(entry.GetTypesFromName("a", 1), IntType);
 263            AssertContainsExactly(entry.GetTypesFromName("b", 1), StringType);
 264            AssertContainsExactly(entry.GetTypesFromName("c", 1), StringType);
 265        }
 266        
 267        [TestMethod]
 268        public void TestListAppend() {
 269            var entry = ProcessText(@"
 270x = []
 271x.append('abc')
 272y = x[0]
 273");
 274
 275            AssertContainsExactly(entry.GetTypesFromName("y", 1), StringType);
 276
 277            entry = ProcessText(@"
 278x = []
 279x.extend(('abc', ))
 280y = x[0]
 281");
 282            AssertContainsExactly(entry.GetTypesFromName("y", 1), StringType);
 283
 284            entry = ProcessText(@"
 285x = []
 286x.insert(0, 'abc')
 287y = x[0]
 288");
 289            AssertContainsExactly(entry.GetTypesFromName("y", 1), StringType);
 290
 291            entry = ProcessText(@"
 292x = []
 293x.append('abc')
 294y = x.pop()
 295");
 296
 297            AssertContainsExactly(entry.GetTypesFromName("y", 1), StringType);
 298
 299            entry = ProcessText(@"
 300class ListTest(object):
 301    def reset(self):
 302        self.items = []
 303        self.pushItem(self)
 304    def pushItem(self, item):
 305        self.items.append(item)
 306
 307a = ListTest()
 308b = a.items[0]");
 309
 310            AssertContains(entry.GetMembersFromName("b", 1), "pushItem");
 311        }
 312
 313        [TestMethod]
 314        public void TestSlicing() {
 315            var entry = ProcessText(@"
 316x = [2]
 317y = x[:-1]
 318z = y[0]
 319");
 320
 321            AssertContainsExactly(entry.GetTypesFromName("z", 1), IntType);
 322
 323            entry = ProcessText(@"
 324x = (2, 3, 4)
 325y = x[:-1]
 326z = y[0]
 327");
 328
 329            AssertContainsExactly(entry.GetTypesFromName("z", 1), IntType);
 330        }
 331
 332        [TestMethod]
 333        public void TestColor() {
 334
 335            var entry = ProcessText(@"
 336import clr
 337clr.AddReference('PresentationFramework')
 338clr.AddReference('PresentationCore')
 339
 340from System.Windows.Media import Colors
 341
 342class C(object):
 343    def __init__(self):
 344        if False:
 345            self.some_color = Colors.Black
 346        else:
 347            self.some_color = Colors.White
 348
 349
 350a = C()
 351b = a.some_color
 352");
 353
 354            AssertContainsExactly(entry.GetTypesFromName("b", 1).Select(x => PythonType.Get__name__(x)), "Color");
 355        }
 356
 357        [TestMethod]
 358        public void TestConstantIndex() {
 359            var entry = ProcessText(@"
 360ZERO = 0
 361ONE = 1
 362TWO = 2
 363x = ['abc', 42, True)]
 364
 365
 366some_str = x[ZERO]
 367some_int = x[ONE]
 368some_bool = x[TWO]
 369");
 370            AssertContainsExactly(entry.GetTypesFromName("some_str", 1), StringType);
 371            AssertContainsExactly(entry.GetTypesFromName("some_int", 1), IntType);
 372            AssertContainsExactly(entry.GetTypesFromName("some_bool", 1), BoolType);
 373        }
 374        [TestMethod]
 375        public void TestCtorSignatures() {
 376            var entry = ProcessText(@"
 377class C: pass
 378
 379class D(object): pass
 380
 381class E(object):
 382    def __init__(self): pass
 383
 384class F(object):
 385    def __init__(self, one): pass
 386
 387class G(object):
 388    def __new__(cls): pass
 389
 390class H(object):
 391    def __new__(cls, one): pass
 392
 393            ");
 394
 395            var result = entry.GetSignatures("C", 1).ToArray();
 396            Assert.AreEqual(result.Length, 1);
 397            Assert.AreEqual(result[0].Parameters.Length, 0);
 398
 399            result = entry.GetSignatures("D", 1).ToArray();
 400            Assert.AreEqual(result.Length, 1);
 401            Assert.AreEqual(result[0].Parameters.Length, 0);
 402
 403            result = entry.GetSignatures("E", 1).ToArray();
 404            Assert.AreEqual(result.Length, 1);
 405            Assert.AreEqual(result[0].Parameters.Length, 0);
 406
 407            result = entry.GetSignatures("F", 1).ToArray();
 408            Assert.AreEqual(result.Length, 1);
 409            Assert.AreEqual(result[0].Parameters.Length, 1);
 410
 411            result = entry.GetSignatures("G", 1).ToArray();
 412            Assert.AreEqual(result.Length, 1);
 413            Assert.AreEqual(result[0].Parameters.Length, 0);
 414
 415            result = entry.GetSignatures("H", 1).ToArray();
 416            Assert.AreEqual(result.Length, 1);
 417            Assert.AreEqual(result[0].Parameters.Length, 1);
 418        }
 419        
 420        [TestMethod]
 421        public void TestBuiltinTypeSignatures() {
 422            var entry = ProcessText(@"
 423import System
 424x = str
 425x = int
 426
 427y = str
 428y = int
 429");
 430
 431            var result = entry.GetSignatures("System.Collections.Generic.Dictionary[int, int]", 1).ToArray();
 432            Assert.AreEqual(result.Length, 6);
 433
 434            // 2 possible types
 435            result = entry.GetSignatures("System.Collections.Generic.Dictionary[x, int]", 1).ToArray();
 436            Assert.AreEqual(result.Length, 12);
 437
 438            // 4 possible types
 439            result = entry.GetSignatures("System.Collections.Generic.Dictionary[x, y]", 1).ToArray();
 440            Assert.AreEqual(result.Length, 24);
 441        }
 442
 443        [TestMethod]
 444        public void TestBuiltinMethodSignatures() {
 445            var entry = ProcessText(@"
 446const = """".capitalize
 447constructed = str().capitalize
 448");
 449
 450            string[] testCapitalize = new[] { "const", "constructed" };
 451            foreach (var test in testCapitalize) {
 452                var result = entry.GetSignatures(test, 1).ToArray();
 453                Assert.AreEqual(result.Length, 1);
 454                Assert.AreEqual(result[0].Parameters.Length, 0);
 455            }
 456
 457            entry = ProcessText(@"
 458import clr
 459const = """".Contains
 460constructed = str().Contains
 461");
 462
 463            string[] testContains = new[] { "const", "constructed" };
 464            foreach (var test in testContains) {
 465                var result = entry.GetSignatures(test, 1).ToArray();
 466                Assert.AreEqual(result.Length, 1);
 467                Assert.AreEqual(result[0].Parameters.Length, 1);
 468                Assert.AreEqual(result[0].Parameters[0].Name, "value");
 469                Assert.AreEqual(result[0].Parameters[0].IsOptional, false);
 470            }
 471        }
 472
 473        [TestMethod]
 474        public void TestDel() {
 475            string text = @"
 476del foo
 477del foo[2]
 478del foo.bar
 479del (foo)
 480del foo, bar
 481";
 482            var entry = ProcessText(text);
 483
 484            // We do no analysis on del statements, nothing to test
 485        }
 486
 487        [TestMethod]
 488        public void TryExcept() {
 489            string text = @"
 490class MyException(Exception): pass
 491
 492def f():
 493    try:
 494    except TypeError, e1:
 495        pass
 496
 497def g():
 498    try:
 499    except MyException, e2:
 500        pass
 501";
 502            var entry = ProcessText(text);
 503
 504            AssertContainsExactly(GetTypes(entry.GetValues("e1", GetLineNumber(text, ", e1"))), PythonExceptions.TypeError);
 505
 506            AssertContainsExactly(GetTypeNames(entry.GetValues("e2", GetLineNumber(text, ", e2"))), "MyException instance");
 507        }
 508
 509        private IEnumerable<PythonType> GetTypes(IEnumerable<IAnalysisValue> analysisValues) {
 510            foreach (var value in analysisValues) {
 511                yield return value.PythonType;
 512            }
 513        }
 514
 515        private IEnumerable<string> GetTypeNames(IEnumerable<IAnalysisValue> analysisValues) {
 516            foreach (var value in analysisValues) {
 517                yield return value.ShortDescription;
 518            }
 519        }
 520
 521        class VariableLocation {
 522            public readonly int StartLine;
 523            public readonly int StartCol;
 524            public readonly VariableType Type;
 525
 526            public VariableLocation(int startLine, int startCol, VariableType type) {
 527                StartLine = startLine;
 528                StartCol = startCol;
 529                Type = type;
 530            }
 531        }
 532
 533        [TestMethod]
 534        public void TestReferences() {
 535            // instance variables
 536            var text = @"
 537# add ref w/o type info
 538class C(object):
 539    def __init__(self, foo):
 540        self.abc = foo
 541        del self.abc
 542        print self.abc
 543
 544";
 545            var entry = ProcessText(text);
 546            VerifyReferences(entry.GetVariables("self.abc", GetLineNumber(text, "self.abc")), new VariableLocation(5, 9, VariableType.Definition), new VariableLocation(6, 13, VariableType.Reference), new VariableLocation(7, 15, VariableType.Reference));
 547            VerifyReferences(entry.GetVariables("foo", GetLineNumber(text, "foo")), new VariableLocation(4, 24, VariableType.Definition), new VariableLocation(5, 20, VariableType.Reference));
 548
 549            text = @"
 550# add ref w/ type info
 551class D(object):
 552    def __init__(self, foo):
 553        self.abc = foo
 554        del self.abc
 555        print self.abc
 556
 557D(42)";
 558            entry = ProcessText(text);
 559
 560            VerifyReferences(entry.GetVariables("self.abc", GetLineNumber(text, "self.abc")), new VariableLocation(5, 9, VariableType.Definition), new VariableLocation(6, 13, VariableType.Reference), new VariableLocation(7, 15, VariableType.Reference));
 561            VerifyReferences(entry.GetVariables("foo", GetLineNumber(text, "foo")), new VariableLocation(4, 24, VariableType.Definition), new VariableLocation(5, 20, VariableType.Reference));
 562            VerifyReferences(entry.GetVariables("D", GetLineNumber(text, "D(42)")), new VariableLocation(9, 1, VariableType.Reference), new VariableLocation(3, 1, VariableType.Definition));
 563
 564            // function definitions
 565            text = @"
 566def f(): pass
 567
 568x = f()";
 569            entry = ProcessText(text);
 570            VerifyReferences(entry.GetVariables("f", GetLineNumber(text, "x =")), new VariableLocation(4, 5, VariableType.Reference), new VariableLocation(2, 1, VariableType.Definition));
 571
 572            text = @"
 573from System import EventHandler
 574def g():
 575    x = EventHandler(f)
 576    
 577def f(sender, args): pass
 578";
 579            entry = ProcessText(text);
 580            VerifyReferences(entry.GetVariables("f", GetLineNumber(text, "x =")), new VariableLocation(4, 22, VariableType.Reference), new VariableLocation(6, 1, VariableType.Definition));
 581
 582            text = @"
 583from System import EventHandler
 584def f(sender, args): pass
 585
 586x = EventHandler(f)";
 587            entry = ProcessText(text);
 588            VerifyReferences(entry.GetVariables("f", GetLineNumber(text, "x =")), new VariableLocation(5, 18, VariableType.Reference), new VariableLocation(3, 1, VariableType.Definition));
 589            
 590            // left hand side is unknown, right hand side should still have refs added
 591            text = @"
 592from System import EventHandler
 593def f(sender, args): pass
 594
 595a.foo += EventHandler(f)
 596";
 597            entry = ProcessText(text);
 598            VerifyReferences(entry.GetVariables("f", GetLineNumber(text, "a.foo +=")), new VariableLocation(5, 23, VariableType.Reference), new VariableLocation(3, 1, VariableType.Definition));
 599            
 600
 601            text = @"
 602def f(): pass
 603
 604x = f";
 605            entry = ProcessText(text);
 606            VerifyReferences(entry.GetVariables("f", GetLineNumber(text, "x =")), new VariableLocation(4, 5, VariableType.Reference), new VariableLocation(2, 1, VariableType.Definition));
 607
 608            // class variables
 609            text = @"
 610
 611class D(object):
 612    abc = 42
 613    print abc
 614    del abc
 615";
 616            entry = ProcessText(text);
 617
 618            VerifyReferences(entry.GetVariables("abc", GetLineNumber(text, "abc =")), new VariableLocation(4, 5, VariableType.Definition), new VariableLocation(5, 11, VariableType.Reference), new VariableLocation(6, 9, VariableType.Reference));
 619
 620            // class definition
 621            text = @"
 622class D(object): pass
 623
 624a = D
 625";
 626            entry = ProcessText(text);
 627            VerifyReferences(entry.GetVariables("D", GetLineNumber(text, "a =")), new VariableLocation(4, 5, VariableType.Reference), new VariableLocation(2, 1, VariableType.Definition));
 628
 629            // method definition
 630            text = @"
 631class D(object): 
 632    def f(self): pass
 633
 634a = D().f()
 635";
 636            entry = ProcessText(text);
 637            VerifyReferences(entry.GetVariables("D().f", GetLineNumber(text, "a =")), 
 638                new VariableLocation(5, 5, VariableType.Reference), new VariableLocation(3, 5, VariableType.Definition));
 639
 640            // globals
 641            text = @"
 642abc = 42
 643print abc
 644del abc
 645";
 646            entry = ProcessText(text);
 647            VerifyReferences(entry.GetVariables("abc", GetLineNumber(text, "abc =")), new VariableLocation(4, 5, VariableType.Reference), new VariableLocation(2, 1, VariableType.Definition), new VariableLocation(3, 7, VariableType.Reference));
 648
 649            // parameters
 650            text = @"
 651def f(abc):
 652    print abc
 653    abc = 42
 654    del abc
 655";
 656            entry = ProcessText(text);
 657            VerifyReferences(entry.GetVariables("abc", GetLineNumber(text, "abc =")), new VariableLocation(2, 7, VariableType.Definition), new VariableLocation(4, 5, VariableType.Definition), new VariableLocation(3, 11, VariableType.Reference), new VariableLocation(5, 9, VariableType.Reference));
 658        
 659        
 660            // grammer test - statements
 661            text = @"
 662def f(abc):
 663    try: pass
 664    except abc: pass
 665
 666    try: pass
 667    except TypeError, abc: pass    
 668
 669    abc, bar = 42, 23
 670    abc[23] = 42
 671    abc.foo = 42
 672    abc += 2
 673
 674    class D(abc): pass
 675
 676    for x in abc: print x
 677
 678    import abc
 679    from xyz import abc
 680    from xyz import bar as abc
 681
 682    if abc: print 'hi'
 683    elif abc: print 'bye'
 684    else: abc
 685
 686    with abc:
 687        return abc
 688
 689    print abc
 690    assert abc, abc
 691
 692    raise abc
 693    raise abc, abc, abc
 694
 695    while abc:
 696        abc
 697    else:
 698        abc
 699
 700    for x in foo: 
 701        print x
 702    else:
 703        print abc
 704
 705    try: pass
 706    except TypeError:
 707    else:
 708        abc
 709";
 710            entry = ProcessText(text);
 711            VerifyReferences(entry.GetVariables("abc", GetLineNumber(text, "f(abc)")), 
 712                new VariableLocation(2, 7, VariableType.Definition), 
 713                new VariableLocation(4, 12, VariableType.Reference), 
 714                new VariableLocation(7, 23, VariableType.Definition),
 715                
 716                new VariableLocation(9, 5, VariableType.Definition),
 717                new VariableLocation(10, 5, VariableType.Reference),
 718                new VariableLocation(11, 5, VariableType.Reference),
 719                new VariableLocation(12, 5, VariableType.Reference),
 720                
 721                new VariableLocation(14, 13, VariableType.Reference),
 722                
 723                new VariableLocation(16, 14, VariableType.Reference),
 724
 725                new VariableLocation(18, 5, VariableType.Reference), 
 726                new VariableLocation(19, 5, VariableType.Reference), 
 727                new VariableLocation(20, 5, VariableType.Reference),
 728
 729                new VariableLocation(22, 8, VariableType.Reference),
 730                new VariableLocation(23, 10, VariableType.Reference),
 731                new VariableLocation(24, 11, VariableType.Reference),
 732
 733                new VariableLocation(26, 10, VariableType.Reference),
 734                new VariableLocation(27, 16, VariableType.Reference),
 735
 736                new VariableLocation(29, 11, VariableType.Reference),
 737                new VariableLocation(30, 12, VariableType.Reference),
 738                new VariableLocation(30, 17, VariableType.Reference),
 739
 740                new VariableLocation(32, 11, VariableType.Reference),
 741                new VariableLocation(33, 11, VariableType.Reference),
 742                new VariableLocation(33, 16, VariableType.Reference),
 743                new VariableLocation(33, 21, VariableType.Reference),
 744
 745                new VariableLocation(35, 11, VariableType.Reference),
 746                new VariableLocation(36, 9, VariableType.Reference),
 747                new VariableLocation(38, 9, VariableType.Reference),
 748
 749                new VariableLocation(43, 15, VariableType.Reference),
 750
 751                new VariableLocation(48, 9, VariableType.Reference) 
 752            );
 753
 754
 755            // grammer test - expressions
 756            text = @"
 757def f(abc):
 758    x = abc + 2
 759    x = 2 + abc
 760    x = l[abc]
 761    x = abc[l]
 762    x = abc.foo
 763    
 764    g(abc)
 765
 766    abc if abc else abc
 767
 768    {abc:abc},
 769    [abc, abc]
 770    (abc, abc)
 771    {abc}
 772
 773    yield abc
 774    [x for x in abc]
 775    (x for x in abc)
 776
 777    abc or abc
 778    abc and abc
 779
 780    +abc
 781    x[abc:abc:abc]
 782
 783    abc == abc
 784    not abc
 785
 786    lambda : abc
 787";
 788            entry = ProcessText(text);
 789            VerifyReferences(entry.GetVariables("abc", GetLineNumber(text, "f(abc)")),
 790                new VariableLocation(2, 7, VariableType.Definition),
 791
 792                new VariableLocation(3, 9, VariableType.Reference),
 793                new VariableLocation(4, 13, VariableType.Reference),
 794
 795                new VariableLocation(5, 10, VariableType.Reference),        // BUGBUG: should be 5,11
 796                new VariableLocation(6, 9, VariableType.Reference),
 797                new VariableLocation(7, 9, VariableType.Reference),
 798                new VariableLocation(9, 7, VariableType.Reference),
 799
 800                new VariableLocation(11, 5, VariableType.Reference),
 801                new VariableLocation(11, 12, VariableType.Reference),
 802                new VariableLocation(11, 21, VariableType.Reference),
 803
 804                new VariableLocation(13, 6, VariableType.Reference),
 805                new VariableLocation(13, 10, VariableType.Reference),
 806                new VariableLocation(14, 6, VariableType.Reference),
 807                new VariableLocation(14, 11, VariableType.Reference),
 808                new VariableLocation(15, 6, VariableType.Reference),
 809                new VariableLocation(15, 11, VariableType.Reference),
 810                new VariableLocation(16, 6, VariableType.Reference),
 811
 812                new VariableLocation(18, 11, VariableType.Reference),
 813                new VariableLocation(19, 17, VariableType.Reference),
 814                new VariableLocation(20, 17, VariableType.Reference),
 815
 816                new VariableLocation(22, 5, VariableType.Reference),
 817                new VariableLocation(22, 12, VariableType.Reference),
 818                new VariableLocation(23, 5, VariableType.Reference),
 819                new VariableLocation(23, 13, VariableType.Reference),
 820
 821                new VariableLocation(25, 6, VariableType.Reference),
 822                new VariableLocation(26, 7, VariableType.Reference),
 823                new VariableLocation(26, 11, VariableType.Reference),
 824                new VariableLocation(26, 15, VariableType.Reference),
 825
 826                new VariableLocation(28, 5, VariableType.Reference),
 827                new VariableLocation(28, 12, VariableType.Reference),
 828                new VariableLocation(29, 9, VariableType.Reference)
 829
 830                //new VariableLocation(30, 14, VariableType.Reference) // BUGBUG: Enable when lambda bodies are walked
 831            );
 832        }
 833
 834        private void VerifyReferences(IEnumerable<IAnalysisVariable> variables, params VariableLocation[] variableType) {
 835            var vars = new List<IAnalysisVariable>(variables);
 836            if (vars.Count == 0) {
 837                Assert.Fail("Got no references");
 838            }
 839
 840            int removed = 0;
 841            bool removedOne = false;
 842            do {
 843                for (int j = 0; j < variableType.Length; j++) {
 844                    var expected = variableType[j];
 845
 846                    bool found = false;
 847                    for (int i = 0; i < vars.Count; i++) {
 848                        var have = vars[i];
 849
 850                        if (have.Location.Line == expected.StartLine &&
 851                            have.Location.Column == expected.StartCol &&
 852                            have.Type == expected.Type) {
 853                            vars.RemoveAt(i);
 854                            removed++;
 855                            removedOne = found = true;
 856                            break;
 857                        }
 858                    }
 859
 860                    if (!found) {
 861                        StringBuilder error = new StringBuilder(String.Format("Failed to find location: {0} {1} {2}" + Environment.NewLine, expected.StartLine, expected.StartCol, expected.Type));
 862                        LocationNames(vars, error);
 863
 864                        Assert.Fail(error.ToString());
 865                    }
 866                }
 867            } while (vars.Count != 0 && removedOne);
 868
 869            if (vars.Count != 0) {
 870                StringBuilder error = new StringBuilder("Didn't use all locations - had " + variables.Count() + Environment.NewLine);
 871                LocationNames(vars, error);
 872                Assert.Fail(error.ToString());
 873            }
 874        }
 875
 876        private static void LocationNames(List<IAnalysisVariable> vars, StringBuilder error) {
 877            foreach (var var in vars) {
 878                error.AppendFormat("   {0} {1} {2}", var.Location.Line, var.Location.Column, var.Type);
 879                error.AppendLine();
 880            }
 881        }
 882
 883        [TestMethod]
 884        public void TestSignatureDefaults() {
 885            var entry = ProcessText(@"
 886def f(x = None): pass
 887
 888def g(x = {}): pass
 889
 890def h(x = {2:3}): pass
 891
 892def i(x = []): pass
 893
 894def j(x = [None]): pass
 895
 896def k(x = ()): pass
 897
 898def l(x = (2, )): pass
 899");
 900
 901            var tests = new[] {
 902                new { FuncName = "f", ParamName="x = None" },
 903                new { FuncName = "g", ParamName="x = {}" },
 904                new { FuncName = "h", ParamName="x = {...}" },
 905                new { FuncName = "i", ParamName="x = []" },
 906                new { FuncName = "j", ParamName="x = [...]" },
 907                new { FuncName = "k", ParamName="x = ()" },
 908                new { FuncName = "l", ParamName="x = (...)" },
 909            };
 910
 911            foreach (var test in tests) {
 912                var result = entry.GetSignatures(test.FuncName, 1).ToArray();
 913                Assert.AreEqual(result.Length, 1);
 914                Assert.AreEqual(result[0].Parameters[0].Name, test.ParamName);
 915            }
 916        }
 917
 918        [TestMethod]
 919        public void TestGetVariablesDictionaryGet() {
 920            var entry = ProcessText(@"
 921x = {42:'abc'}
 922            ");
 923
 924            foreach (var varRef in entry.GetValues("x.get", 1)) {
 925                Assert.AreEqual("built-in method get", varRef.Description);
 926            }
 927        }
 928
 929        [TestMethod]
 930        public void TestLambdaExpression() {
 931            var entry = ProcessText(@"
 932x = lambda a: a
 933y = x(42)
 934");
 935
 936            AssertContainsExactly(entry.GetTypesFromName("y", 1), IntType);
 937
 938            entry = ProcessText(@"
 939def f(a):
 940    return a
 941
 942x = lambda b: f(b)
 943y = x(42)
 944");
 945
 946            AssertContainsExactly(entry.GetTypesFromName("y", 1), IntType);
 947        }
 948
 949        [TestMethod]
 950        public void TestRecursiveClass() {
 951            var entry = ProcessText(@"
 952cls = object
 953
 954class cls(cls): 
 955    abc = 42
 956");
 957
 958            entry.GetMembersFromName("cls", 1);
 959            AssertContainsExactly(entry.GetMembers("cls().abc.", 1).Select(member => member.Name), _intMembers);
 960            AssertContainsExactly(entry.GetMembers("cls.abc.", 1).Select(member => member.Name), _intMembers);
 961        }
 962
 963        [TestMethod]
 964        public void TestBadMethod() {
 965            var entry = ProcessText(@"
 966class cls(object): 
 967    def f(): 
 968        return 42
 969
 970abc = cls()
 971foo = abc.f()
 972");
 973
 974            AssertContainsExactly(entry.GetMembers("foo.", 1).Select(member => member.Name), _intMembers);
 975        }
 976
 977        [TestMethod]
 978        public void TestKeywordArguments() {
 979            var funcDef = "def f(a, b, c): pass";
 980            var classWithInit  = @"class f(object):
 981    def __init__(self, a, b, c):
 982        pass";
 983            var classWithNew = @"class f(object):
 984    def __new__(cls, a, b, c):
 985        pass";
 986            var method = @"class x(object):
 987    def g(self, a, b, c):
 988        pass
 989
 990f = x().g";
 991            var decls = new []  { funcDef, classWithInit, classWithNew, method };
 992
 993            foreach (var decl in decls) {
 994                string[] testCalls = new[] { 
 995                    "f(c = 'abc', b = 42, a = 3j)", "f(3j, c = 'abc', b = 42)", "f(3j, 42, c = 'abc')",
 996                    "f(c = 'abc', b = 42, a = 3j, d = 42)",  // extra argument
 997                    "f(3j, 42, 'abc', d = 42)",
 998                };
 999
1000                foreach (var testCall in testCalls) {
1001                    var text = decl + Environment.NewLine + testCall;
1002                    var entry = ProcessText(text);
1003
1004                    AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "pass")), ComplexType);
1005                    AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "pass")), IntType);
1006                    AssertContainsExactly(entry.GetTypesFromName("c", GetLineNumber(text, "pass")), StringType);
1007                }
1008            }
1009        }
1010
1011        [TestMethod]
1012        public void TestPositionalSplat() {
1013            var funcDef = "def f(a, b, c): pass";            
1014            var classWithInit = @"class f(object):
1015    def __init__(self, a, b, c):
1016        pass";
1017            var classWithNew = @"class f(object):
1018    def __new__(cls, a, b, c):
1019        pass";
1020            var method = @"class x(object):
1021    def g(self, a, b, c):
1022        pass
1023
1024f = x().g";
1025            var decls = new[] { funcDef, classWithInit, classWithNew, method };
1026
1027            foreach (var decl in decls) {
1028                string[] testCalls = new[] { 
1029                    "f(*(3j, 42, 'abc'))", 
1030                    "f(*[3j, 42, 'abc'])", 
1031                    "f(*(3j, 42, 'abc', 4L))",  // extra argument
1032                    "f(*[3j, 42, 'abc', 4L])",  // extra argument
1033                };
1034
1035                foreach (var testCall in testCalls) {
1036                    var text = decl + Environment.NewLine + testCall;
1037                    var entry = ProcessText(text);
1038
1039                    AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "pass")), ComplexType);
1040                    AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "pass")), IntType);
1041                    AssertContainsExactly(entry.GetTypesFromName("c", GetLineNumber(text, "pass")), StringType);
1042                }
1043            }
1044        }
1045        [TestMethod]
1046        public void TestForwardRef() {
1047            var text = @"
1048
1049class D(object):
1050    def bar(self, x):
1051        abc = C()
1052        abc.foo(2)
1053        a = abc.foo(2.0)
1054        a.bar(('a', 'b', 'c', 'd'))
1055
1056class C(object):
1057    def foo(self, x):
1058        D().bar('abc')
1059        D().bar(['a', 'b', 'c'])
1060        return D()
1061    def baz(self): pass
1062";
1063            var entry = ProcessText(text);
1064
1065            var fifty = entry.GetVariablesNoBuiltins(GetLineNumber(text, "abc.foo")).ToSet();
1066            AssertContainsExactly(fifty, "C", "D", "a", "abc", "self", "x");
1067
1068            var three = entry.GetVariablesNoBuiltins(GetLineNumber(text, "lass D")).ToSet();
1069            AssertContainsExactly(three, "C", "D", "bar");
1070
1071            var allFifty = entry.GetMembersFromName("abc", GetLineNumber(text, "abc.foo")).ToSet();
1072            AssertContainsExactly(allFifty, GetUnion(_objectMembers, "baz", "foo"));
1073
1074            var xTypes = entry.GetTypesFromName("x", GetLineNumber(text, "abc.foo")).ToSet();
1075            AssertContainsExactly(xTypes, ListType, StringType, TupleType);
1076
1077            var xMembers = entry.GetMembersFromName("x", GetLineNumber(text, "abc.foo")).ToSet();
1078            AssertContainsExactly(xMembers, GetIntersection(_strMembers, _listMembers));
1079        }
1080
1081        private static int GetLineNumber(string text, string substring) {
1082            string[] splitLines = text.Split('\n');
1083            for (int i = 0; i < splitLines.Length; i++) {
1084                if (splitLines[i].IndexOf(substring) != -1) {
1085                    return i + 1;
1086                }
1087            }
1088
1089            throw new InvalidOperationException();
1090        }
1091
1092        [TestMethod]
1093        public void TestBuiltins() {
1094            var text = @"
1095booltypetrue = True
1096booltypefalse = False
1097";
1098            var entry = ProcessText(text);
1099            AssertContainsExactly(entry.GetTypesFromName("booltypetrue", 1), BoolType);
1100            AssertContainsExactly(entry.GetTypesFromName("booltypefalse", 1), BoolType);
1101        }
1102
1103        [TestMethod]
1104        public void TestDictionaryFunctionTable() {
1105            var text = @"
1106def f(a, b):
1107    print a, b
1108    
1109def g(a, b):
1110    x, y = a, b
1111
1112x = {'foo': f, 'bar' : g}
1113x['foo'](42, [])
1114";
1115            var entry = ProcessText(text);
1116            AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "print")), IntType);
1117            AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "print")), ListType);
1118            AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "x, y")), IntType);
1119            AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "x, y")), ListType);
1120        }
1121
1122        [TestMethod]
1123        public void TestDictionaryAssign() {
1124            var text = @"
1125x = {'abc': 42}
1126y = x['foo']
1127";
1128            var entry = ProcessText(text);
1129            AssertContainsExactly(entry.GetTypesFromName("y", 1), IntType);
1130        }
1131
1132        [TestMethod]
1133        public void TestDictionaryFunctionTableGet2() {
1134            var text = @"
1135def f(a, b):
1136    print a, b
1137    
1138def g(a, b):
1139    x, y = a, b
1140
1141x = {'foo': f, 'bar' : g}
1142x.get('foo')(42, [])
1143";
1144            var entry = ProcessText(text);
1145            AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "print")), IntType);
1146            AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "print")), ListType);
1147            AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "x, y")), IntType);
1148            AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "x, y")), ListType);
1149        }
1150
1151        [TestMethod]
1152        public void TestDictionaryFunctionTableGet() {
1153            var text = @"
1154def f(a, b):
1155    print a, b
1156    
1157def g(a, b):
1158    x, y = a, b
1159
1160x = {'foo': f, 'bar' : g}
1161y = x.get('foo', None)
1162if y is not None:
1163    y(42, [])
1164";
1165            var entry = ProcessText(text);
1166            AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "print")), IntType);
1167            AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "print")), ListType);
1168            AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "x, y")), IntType);
1169            AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "x, y")), ListType);
1170        }
1171
1172        [TestMethod]
1173        public void TestSimpleGlobals() {
1174            var text = @"
1175class x(object):
1176    def abc(self):
1177        pass
1178        
1179a = x()
1180x.abc()
1181";
1182            var entry = ProcessText(text);
1183            AssertContainsExactly(entry.GetVariablesNoBuiltins(1), "a", "x");
1184            AssertContainsExactly(entry.GetMembersFromName("x", 1), GetUnion(_objectMembers, "abc"));
1185        }
1186
1187        [TestMethod]
1188        public void TestFuncCallInIf() {
1189            var text = @"
1190def Method(a, b, c):
1191    print a, b, c
1192    
1193if not Method(42, 'abc', []):
1194    pass
1195";
1196            var entry = ProcessText(text);
1197            AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "print")), IntType);
1198            AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "print")), StringType);
1199            AssertContainsExactly(entry.GetTypesFromName("c", GetLineNumber(text, "print")), ListType);
1200        }
1201
1202        [TestMethod]
1203        public void TestWithStatement() {
1204            var text = @"
1205class x(object):
1206    def x_method(self):
1207        pass
1208        
1209with x() as foo:
1210    print foo
1211    
1212with x():
1213    pass
1214";
1215            var entry = ProcessText(text);
1216            var foo = entry.GetMembersFromName("foo", GetLineNumber(text, "print foo"));
1217            AssertContainsExactly(foo, GetUnion(_objectMembers, "x_method"));
1218        }
1219
1220        [TestMethod]
1221        public void TestOverrideFunction() {
1222            var text = @"
1223class bar(object):
1224    def Call(self, xvar, yvar):
1225        pass
1226
1227class baz(bar):
1228    def Call(self, xvar, yvar):
1229        pass
1230
1231class Cxxxx(object):
1232    def __init__(self):
1233        self.foo = baz()
1234        
1235    def Cmeth(self, avar, bvar):
1236        self.foo.Call(avar, bvar)
1237        
1238
1239
1240abc = Cxxxx()
1241abc.Cmeth(['foo'], 'bar')
1242";
1243            var entry = ProcessText(text);
1244            AssertContainsExactly(entry.GetTypesFromName("xvar", GetLineNumber(text, "pass")), ListType);
1245        }
1246
1247        [TestMethod]
1248        public void TestSimpleMethodCall() {
1249            var text = @"
1250class x(object):
1251    def abc(self, foo):
1252        pass
1253        
1254a = x()
1255a.abc('abc')
1256";
1257            var entry = ProcessText(text);
1258            AssertContainsExactly(entry.GetTypesFromName("foo", GetLineNumber(text, "pass")), StringType);
1259            AssertContainsExactly(entry.GetMembersFromName("self", GetLineNumber(text, "pass")), GetUnion(_objectMembers, "abc"));
1260        }
1261
1262        [TestMethod]
1263        public void TestSystemFromImport() {
1264            var text = @"
1265from System import Environment
1266Environment.GetCommandLineArgs()
1267";
1268            var entry = ProcessText(text);
1269            Assert.IsTrue(entry.GetMembersFromName("Environment", 1).Any(s => s == "CommandLine"));
1270        }
1271
1272        [TestMethod]
1273        public void TestImportAs() {
1274            var text = @"
1275import System.Collections as coll
1276";
1277            var entry = ProcessText(text);
1278            Assert.IsTrue(entry.GetMembersFromName("coll", 1).Any(s => s == "ArrayList"));
1279        }
1280
1281        [TestMethod]
1282        public void TestSystemImport() {
1283            var text = @"
1284import System
1285System.Environment.GetCommandLineArgs()
1286x = System.Environment
1287";
1288            var entry = ProcessText(text);
1289            var system = entry.GetMembersFromName("System", 1).ToSet();
1290            // defined in mscorlib
1291            AssertContains(system, "AccessViolationException");
1292            // defined in System
1293            AssertContains(system, "CodeDom");
1294
1295            AssertContains(entry.GetMembersFromName("x", 1), "GetEnvironmentVariables");
1296        }
1297
1298        [TestMethod]
1299        public void TestSystemMembers() {
1300            var text = @"
1301import System
1302System.Environment.GetCommandLineArgs()
1303x = System.Environment
1304args = x.GetCommandLineArgs()
1305";
1306            var entry = ProcessText(text);
1307
1308            var args = entry.GetTypesFromName("args", GetLineNumber(text, "args =")).ToSet();
1309            AssertContainsExactly(args, ClrModule.GetPythonType(typeof(string[])));
1310
1311            Assert.IsTrue(entry.GetMembersFromName("args", GetLineNumber(text, "args =")).Any(s => s == "AsReadOnly"));
1312        }
1313
1314        [TestMethod]
1315        public void TestNamespaceMembers() {
1316            var text = @"
1317import System
1318x = System.Collections
1319";
1320            var entry = ProcessText(text);
1321            var x = entry.GetMembersFromName("x", GetLineNumber(text, "x =")).ToSet();
1322            Assert.IsTrue(x.Contains("Generic"));
1323            Assert.IsTrue(x.Contains("ArrayList"));
1324        }
1325
1326        [TestMethod]
1327        public void TestBuiltinRetval() {
1328            var text = @"
1329x = [2,3,4]
1330a = x.index(2)
1331";
1332            var entry = ProcessText(text);
1333            AssertContainsExactly(entry.GetTypesFromName("x", GetLineNumber(text, "x =")).ToSet(), ListType);
1334            AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "a =")).ToSet(), IntType);
1335        }
1336
1337        [TestMethod]
1338        public void TestBuiltinFuncRetval() {
1339            var text = @"
1340x = ord('a')
1341y = range(5)
1342";
1343            var entry = ProcessText(text);
1344            AssertContainsExactly(entry.GetTypesFromName("x", GetLineNumber(text, "x = ")).ToSet(), IntType);
1345            AssertContainsExactly(entry.GetTypesFromName("y", GetLineNumber(text, "y = ")).ToSet(), ListType);
1346        }
1347
1348        [TestMethod]
1349        public void TestFunctionMembers() {
1350            var text = @"
1351def f(x): pass
1352f.abc = 32
1353";
1354            var entry = ProcessText(text);
1355            AssertContains(entry.GetMembersFromName("f", 1), "abc");
1356
1357            text = @"
1358def f(x): pass
1359
1360";
1361            entry = ProcessText(text);
1362            AssertDoesntContain(entry.GetMembersFromName("f", 1), "x");
1363            AssertContainsExactly(entry.GetMembersFromName("f", 1), _functionMembers);
1364
1365            AssertContainsExactly(entry.GetMembersFromName("f.func_name", 1), _strMembers);
1366        }
1367
1368
1369        [TestMethod]
1370        public void TestRangeIteration() {
1371            var text = @"
1372for i in range(5):
1373    pass
1374";
1375            var entry = ProcessText(text);
1376            AssertContainsExactly(entry.GetTypesFromName("i", GetLineNumber(text, "for i")).ToSet(), IntType);
1377        }
1378
1379        [TestMethod]
1380        public void TestBuiltinImport() {
1381            var text = @"
1382import sys
1383";
1384            var entry = ProcessText(text);
1385            AssertContainsExactly(entry.GetVariablesNoBuiltins(1), "sys");
1386            Assert.IsTrue(entry.GetMembersFromName("sys", 1).Any((s) => s == "winver"));
1387        }
1388
1389        [TestMethod]
1390        public void TestBuiltinImportInFunc() {
1391            var text = @"
1392def f():
1393    import sys
1394";
1395            var entry = ProcessText(text);
1396            AssertContainsExactly(entry.GetVariablesNoBuiltins(GetLineNumber(text, "sys")), "f", "sys");
1397            AssertContains(entry.GetMembersFromName("sys", GetLineNumber(text, "sys")), "winver");
1398        }
1399
1400        [TestMethod]
1401        public void TestBuiltinImportInClass() {
1402            var text = @"
1403class C:
1404    import sys
1405";
1406            var entry = ProcessText(text);
1407
1408            AssertContainsExactly(entry.GetVariablesNoBuiltins(GetLineNumber(text, "sys")), "C", "sys");
1409            Assert.IsTrue(entry.GetMembersFromName("sys", GetLineNumber(text, "sys")).Any((s) => s == "winver"));
1410        }
1411
1412        [TestMethod]
1413        public void TestNoImportClr() {
1414            var text = @"
1415x = 'abc'
1416";
1417            var entry = ProcessText(text);
1418            AssertContainsExactly(entry.GetTypesFromName("x", 1), StringType);
1419            AssertContainsExactly(entry.GetMembersFromName("x", 1), _strMembers);
1420        }
1421
1422        [TestMethod]
1423        public void TestImportClr() {
1424            var text = @"
1425import clr
1426x = 'abc'
1427";
1428            var entry = ProcessText(text);
1429            AssertContainsExactly(entry.GetMembersFromName("x", 1), _strMembersClr);
1430        }
1431
1432        [TestMethod]
1433        public void TestClrAddReference() {
1434            var text = @"
1435import clr
1436clr.AddReference('System.Drawing')
1437from System.Drawing import Point
1438";
1439            var entry = ProcessText(text);
1440            Assert.AreEqual(35, entry.GetMembersFromName("Point", GetLineNumber(text, "from System.")).ToList().Count);
1441        }
1442
1443        [TestMethod]
1444        public void TestClrAddReferenceByName() {
1445            var text = @"
1446import clr
1447clr.AddReferenceByName('Microsoft.Scripting')
1448from Microsoft.Scripting import SourceUnit
1449";
1450            var entry = ProcessText(text);
1451            Assert.AreEqual(40, entry.GetMembersFromName("SourceUnit", GetLineNumber(text, "from Microsoft.")).ToList().Count);
1452        }
1453
1454        [TestMethod]
1455        public void TestMutualRecursion() {
1456            var text = @"
1457class C:
1458    def f(self, other, depth):
1459        if depth == 0:
1460            return 'abc'
1461        return other.g(self, depth - 1)
1462
1463class D:
1464    def g(self, other, depth):
1465        if depth == 0:
1466            return ['d', 'e', 'f']
1467        
1468        return other.f(self, depth - 1)
1469
1470x = D().g(C(), 42)
1471
1472";
1473            var entry = ProcessText(text);
1474            AssertContainsExactly(entry.GetMembersFromName("other", GetLineNumber(text, "other.g")), "g");
1475            AssertContainsExactly(entry.GetTypesFromName("x", GetLineNumber(text, "x =")), ListType, StringType);
1476            AssertContainsExactly(entry.GetMembersFromName("x", GetLineNumber(text, "x =")),
1477                GetIntersection(_listMembers, _strMembers));
1478        }
1479
1480        [TestMethod]
1481        public void TestForwardRefVars() {
1482            var text = @"
1483class x(object):
1484    def __init__(self, val):
1485        self.abc = []
1486    
1487x(42)
1488x('abc')
1489x([])
1490";
1491            var entry = ProcessText(text);
1492            Assert.AreEqual(1, entry.GetValues("self.abc", GetLineNumber(text, "self.abc")).ToList().Count);
1493   

Large files files are truncated, but you can click here to view the full file