PageRenderTime 69ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/IronPython_Main/Tools/IronStudio/AnalysisTest/AnalysisTest.cs

#
C# | 2217 lines | 2070 code | 134 blank | 13 comment | 31 complexity | a2a52c28c45f7322f08e23f6dd8250d3 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  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. using System;
  15. using System.Collections.Generic;
  16. using System.IO;
  17. using System.Linq;
  18. using System.Numerics;
  19. using System.Text;
  20. using IronPython.Hosting;
  21. using IronPython.Runtime;
  22. using IronPython.Runtime.Types;
  23. using Microsoft.IronPythonTools.Intellisense;
  24. using Microsoft.PyAnalysis;
  25. using Microsoft.PyAnalysis.Values;
  26. using Microsoft.Scripting;
  27. using Microsoft.Scripting.Hosting;
  28. using Microsoft.Scripting.Hosting.Providers;
  29. using Microsoft.Scripting.Library;
  30. using Microsoft.Scripting.Utils;
  31. using Microsoft.VisualStudio.TestTools.UnitTesting;
  32. using System.Diagnostics;
  33. using IronPython.Runtime.Exceptions;
  34. namespace AnalysisTest {
  35. [TestClass]
  36. public partial class AnalysisTest {
  37. private static ScriptEngine _engine;
  38. private static PythonType PyObjectType, IntType, StringType, FloatType, TypeType, ListType, TupleType, BoolType, FunctionType, ComplexType, GeneratorType;
  39. private static string[] _objectMembers, _objectMembersClr, _functionMembers;
  40. private static string[] _strMembers, _strMembersClr;
  41. private static string[] _listMembers, _intMembers;
  42. public static int Main(string[] args) {
  43. AnalysisTest test = new AnalysisTest();
  44. if (args.Length > 0 && args[0] == "PERF") {
  45. args = ArrayUtils.ShiftLeft(args, 1);
  46. return test.RunTests(args, typeof(PerfMethodAttribute));
  47. }
  48. return test.RunTests(args, typeof(TestMethodAttribute));
  49. }
  50. private int RunTests(string[] args, Type testAttr) {
  51. var fg = Console.ForegroundColor;
  52. int failures = 0;
  53. foreach (var mi in typeof(AnalysisTest).GetMethods()) {
  54. if ((args.Length == 0 || (args.Length > 0 && args.Contains(mi.Name))) &&
  55. mi.IsDefined(testAttr, false)) {
  56. try {
  57. mi.Invoke(this, new object[0]);
  58. Console.ForegroundColor = ConsoleColor.Green;
  59. Console.WriteLine("Test passed: {0}", mi.Name);
  60. } catch (Exception e) {
  61. Console.ForegroundColor = ConsoleColor.Red;
  62. Console.WriteLine("Test failed: {0}", mi.Name);
  63. Console.ForegroundColor = ConsoleColor.Gray;
  64. Console.WriteLine(e);
  65. failures++;
  66. }
  67. }
  68. }
  69. Console.WriteLine();
  70. if (failures == 0) {
  71. Console.ForegroundColor = ConsoleColor.Green;
  72. Console.WriteLine("No failures");
  73. } else {
  74. Console.ForegroundColor = ConsoleColor.Red;
  75. Console.WriteLine("{0} failures", failures);
  76. }
  77. Console.ForegroundColor = fg;
  78. return failures;
  79. }
  80. #region Test Cases
  81. [TestMethod]
  82. public void TestImportStar() {
  83. var entry = ProcessText(@"
  84. from nt import *
  85. ");
  86. var members = entry.GetMembers("", 1).Select(x => x.Name);
  87. AssertContains(members, "abort");
  88. entry = ProcessText(@"");
  89. // make sure abort hasn't become a builtin, if so this test needs to be updated
  90. // with a new name
  91. members = entry.GetMembers("", 1).Select(x => x.Name);
  92. foreach (var member in members) {
  93. if(member == "abort") {
  94. Assert.Fail("abort has become a builtin, or a clean module includes it for some reason");
  95. }
  96. }
  97. }
  98. [TestMethod]
  99. public void TestMutatingReferences() {
  100. var state = new ProjectState(_engine);
  101. var text1 = @"
  102. import mod2
  103. class C(object):
  104. def SomeMethod(self):
  105. pass
  106. mod2.D(C())
  107. ";
  108. var text2 = @"
  109. class D(object):
  110. def __init__(self, value):
  111. self.value = value
  112. self.value.SomeMethod()
  113. ";
  114. var mod1 = ParseText(state, GetSourceUnit(text1, "mod1"), "mod1");
  115. var mod2 = ParseText(state, GetSourceUnit(text2, "mod2"), "mod2");
  116. VerifyReferences(mod1.Analysis.GetVariables("SomeMethod", GetLineNumber(text1, "SomeMethod")),
  117. new VariableLocation(5, 5, VariableType.Definition), new VariableLocation(5, 9, VariableType.Reference));
  118. // mutate 1st file
  119. text1 = text1.Substring(0, text1.IndexOf(" def")) + Environment.NewLine + text1.Substring(text1.IndexOf(" def"));
  120. Prepare(mod1, GetSourceUnit(text1, "mod1"));
  121. mod1.Analyze();
  122. VerifyReferences(mod1.Analysis.GetVariables("SomeMethod", GetLineNumber(text1, "SomeMethod")),
  123. new VariableLocation(6, 5, VariableType.Definition), new VariableLocation(5, 9, VariableType.Reference));
  124. // mutate 2nd file
  125. text2 = Environment.NewLine + text2;
  126. Prepare(mod2, GetSourceUnit(text2, "mod1"));
  127. mod2.Analyze();
  128. VerifyReferences(mod1.Analysis.GetVariables("SomeMethod", GetLineNumber(text1, "SomeMethod")),
  129. new VariableLocation(6, 5, VariableType.Definition), new VariableLocation(6, 9, VariableType.Reference));
  130. }
  131. /// <summary>
  132. /// Verify importing wpf will add a reference to the WPF assemblies
  133. /// </summary>
  134. [TestMethod]
  135. public void TestWpfReferences() {
  136. var entry = ProcessText(@"
  137. import wpf
  138. from System.Windows.Media import Colors
  139. ");
  140. AssertContains(entry.GetMembersFromName("Colors", 1), "Blue");
  141. }
  142. [TestMethod]
  143. public void TestGenerator() {
  144. var entry = ProcessText(@"
  145. def f():
  146. yield 1
  147. yield 2
  148. yield 3
  149. a = f()
  150. b = a.next()
  151. for c in f():
  152. print c
  153. ");
  154. AssertContainsExactly(entry.GetTypesFromName("a", 1), GeneratorType);
  155. AssertContainsExactly(entry.GetTypesFromName("b", 1), IntType);
  156. AssertContainsExactly(entry.GetTypesFromName("c", 1), IntType);
  157. var text = @"
  158. def f():
  159. yield 1
  160. x = yield 2
  161. a = f()
  162. b = a.next()
  163. c = a.send('abc')";
  164. entry = ProcessText(text);
  165. AssertContainsExactly(entry.GetTypesFromName("a", 1), GeneratorType);
  166. AssertContainsExactly(entry.GetTypesFromName("b", 1), IntType);
  167. AssertContainsExactly(entry.GetTypesFromName("c", 1), IntType);
  168. AssertContainsExactly(entry.GetTypesFromName("x", GetLineNumber(text, "yield 2")), StringType);
  169. }
  170. [TestMethod]
  171. public void TestEnum() {
  172. var entry = ProcessText(@"
  173. import System
  174. x = System.StringComparison.OrdinalIgnoreCase
  175. ");
  176. var x = entry.GetValues("x", 1).First();
  177. Assert.AreEqual(x.ResultType, ResultType.EnumInstance);
  178. }
  179. /*
  180. [TestMethod]
  181. public void TestListComprehensions() {
  182. var entry = ProcessText(@"
  183. x = [2,3,4]
  184. y = [a for a in x]
  185. z = y[0]
  186. ");
  187. AssertContainsExactly(entry.GetTypesFromName("z", 0), IntType);
  188. }*/
  189. [TestMethod]
  190. public void TestForSequence() {
  191. var entry = ProcessText(@"
  192. x = [('abc', 42, True), ('abc', 23, False),]
  193. for some_str, some_int, some_bool in x:
  194. print some_str
  195. print some_int
  196. print some_bool
  197. ");
  198. AssertContainsExactly(entry.GetTypesFromName("some_str", 1), StringType);
  199. AssertContainsExactly(entry.GetTypesFromName("some_int", 1), IntType);
  200. AssertContainsExactly(entry.GetTypesFromName("some_bool", 1), BoolType);
  201. }
  202. [TestMethod]
  203. public void TestDynamicAttributes() {
  204. var entry = ProcessText(@"
  205. class x(object):
  206. def __getattr__(self, name):
  207. return 42
  208. def f(self):
  209. return 'abc'
  210. a = x().abc
  211. b = x().f()
  212. class y(object):
  213. def __getattribute__(self, x):
  214. return 'abc'
  215. c = y().abc
  216. ");
  217. AssertContainsExactly(entry.GetTypesFromName("a", 1), IntType);
  218. AssertContainsExactly(entry.GetTypesFromName("b", 1), StringType);
  219. AssertContainsExactly(entry.GetTypesFromName("c", 1), StringType);
  220. }
  221. [TestMethod]
  222. public void TestListAppend() {
  223. var entry = ProcessText(@"
  224. x = []
  225. x.append('abc')
  226. y = x[0]
  227. ");
  228. AssertContainsExactly(entry.GetTypesFromName("y", 1), StringType);
  229. entry = ProcessText(@"
  230. x = []
  231. x.extend(('abc', ))
  232. y = x[0]
  233. ");
  234. AssertContainsExactly(entry.GetTypesFromName("y", 1), StringType);
  235. entry = ProcessText(@"
  236. x = []
  237. x.insert(0, 'abc')
  238. y = x[0]
  239. ");
  240. AssertContainsExactly(entry.GetTypesFromName("y", 1), StringType);
  241. entry = ProcessText(@"
  242. x = []
  243. x.append('abc')
  244. y = x.pop()
  245. ");
  246. AssertContainsExactly(entry.GetTypesFromName("y", 1), StringType);
  247. entry = ProcessText(@"
  248. class ListTest(object):
  249. def reset(self):
  250. self.items = []
  251. self.pushItem(self)
  252. def pushItem(self, item):
  253. self.items.append(item)
  254. a = ListTest()
  255. b = a.items[0]");
  256. AssertContains(entry.GetMembersFromName("b", 1), "pushItem");
  257. }
  258. [TestMethod]
  259. public void TestSlicing() {
  260. var entry = ProcessText(@"
  261. x = [2]
  262. y = x[:-1]
  263. z = y[0]
  264. ");
  265. AssertContainsExactly(entry.GetTypesFromName("z", 1), IntType);
  266. entry = ProcessText(@"
  267. x = (2, 3, 4)
  268. y = x[:-1]
  269. z = y[0]
  270. ");
  271. AssertContainsExactly(entry.GetTypesFromName("z", 1), IntType);
  272. }
  273. [TestMethod]
  274. public void TestColor() {
  275. var entry = ProcessText(@"
  276. import clr
  277. clr.AddReference('PresentationFramework')
  278. clr.AddReference('PresentationCore')
  279. from System.Windows.Media import Colors
  280. class C(object):
  281. def __init__(self):
  282. if False:
  283. self.some_color = Colors.Black
  284. else:
  285. self.some_color = Colors.White
  286. a = C()
  287. b = a.some_color
  288. ");
  289. AssertContainsExactly(entry.GetTypesFromName("b", 1).Select(x => PythonType.Get__name__(x)), "Color");
  290. }
  291. [TestMethod]
  292. public void TestConstantIndex() {
  293. var entry = ProcessText(@"
  294. ZERO = 0
  295. ONE = 1
  296. TWO = 2
  297. x = ['abc', 42, True)]
  298. some_str = x[ZERO]
  299. some_int = x[ONE]
  300. some_bool = x[TWO]
  301. ");
  302. AssertContainsExactly(entry.GetTypesFromName("some_str", 1), StringType);
  303. AssertContainsExactly(entry.GetTypesFromName("some_int", 1), IntType);
  304. AssertContainsExactly(entry.GetTypesFromName("some_bool", 1), BoolType);
  305. }
  306. [TestMethod]
  307. public void TestCtorSignatures() {
  308. var entry = ProcessText(@"
  309. class C: pass
  310. class D(object): pass
  311. class E(object):
  312. def __init__(self): pass
  313. class F(object):
  314. def __init__(self, one): pass
  315. class G(object):
  316. def __new__(cls): pass
  317. class H(object):
  318. def __new__(cls, one): pass
  319. ");
  320. var result = entry.GetSignatures("C", 1).ToArray();
  321. Assert.AreEqual(result.Length, 1);
  322. Assert.AreEqual(result[0].Parameters.Length, 0);
  323. result = entry.GetSignatures("D", 1).ToArray();
  324. Assert.AreEqual(result.Length, 1);
  325. Assert.AreEqual(result[0].Parameters.Length, 0);
  326. result = entry.GetSignatures("E", 1).ToArray();
  327. Assert.AreEqual(result.Length, 1);
  328. Assert.AreEqual(result[0].Parameters.Length, 0);
  329. result = entry.GetSignatures("F", 1).ToArray();
  330. Assert.AreEqual(result.Length, 1);
  331. Assert.AreEqual(result[0].Parameters.Length, 1);
  332. result = entry.GetSignatures("G", 1).ToArray();
  333. Assert.AreEqual(result.Length, 1);
  334. Assert.AreEqual(result[0].Parameters.Length, 0);
  335. result = entry.GetSignatures("H", 1).ToArray();
  336. Assert.AreEqual(result.Length, 1);
  337. Assert.AreEqual(result[0].Parameters.Length, 1);
  338. }
  339. [TestMethod]
  340. public void TestBuiltinTypeSignatures() {
  341. var entry = ProcessText(@"
  342. import System
  343. x = str
  344. x = int
  345. y = str
  346. y = int
  347. ");
  348. var result = entry.GetSignatures("System.Collections.Generic.Dictionary[int, int]", 1).ToArray();
  349. Assert.AreEqual(result.Length, 6);
  350. // 2 possible types
  351. result = entry.GetSignatures("System.Collections.Generic.Dictionary[x, int]", 1).ToArray();
  352. Assert.AreEqual(result.Length, 12);
  353. // 4 possible types
  354. result = entry.GetSignatures("System.Collections.Generic.Dictionary[x, y]", 1).ToArray();
  355. Assert.AreEqual(result.Length, 24);
  356. }
  357. [TestMethod]
  358. public void TestBuiltinMethodSignatures() {
  359. var entry = ProcessText(@"
  360. const = """".capitalize
  361. constructed = str().capitalize
  362. ");
  363. string[] testCapitalize = new[] { "const", "constructed" };
  364. foreach (var test in testCapitalize) {
  365. var result = entry.GetSignatures(test, 1).ToArray();
  366. Assert.AreEqual(result.Length, 1);
  367. Assert.AreEqual(result[0].Parameters.Length, 0);
  368. }
  369. entry = ProcessText(@"
  370. import clr
  371. const = """".Contains
  372. constructed = str().Contains
  373. ");
  374. string[] testContains = new[] { "const", "constructed" };
  375. foreach (var test in testContains) {
  376. var result = entry.GetSignatures(test, 1).ToArray();
  377. Assert.AreEqual(result.Length, 1);
  378. Assert.AreEqual(result[0].Parameters.Length, 1);
  379. Assert.AreEqual(result[0].Parameters[0].Name, "value");
  380. Assert.AreEqual(result[0].Parameters[0].IsOptional, false);
  381. }
  382. }
  383. [TestMethod]
  384. public void TestDel() {
  385. string text = @"
  386. del foo
  387. del foo[2]
  388. del foo.bar
  389. del (foo)
  390. del foo, bar
  391. ";
  392. var entry = ProcessText(text);
  393. // We do no analysis on del statements, nothing to test
  394. }
  395. [TestMethod]
  396. public void TryExcept() {
  397. string text = @"
  398. class MyException(Exception): pass
  399. def f():
  400. try:
  401. except TypeError, e1:
  402. pass
  403. def g():
  404. try:
  405. except MyException, e2:
  406. pass
  407. ";
  408. var entry = ProcessText(text);
  409. AssertContainsExactly(GetTypes(entry.GetValues("e1", GetLineNumber(text, ", e1"))), PythonExceptions.TypeError);
  410. AssertContainsExactly(GetTypeNames(entry.GetValues("e2", GetLineNumber(text, ", e2"))), "MyException instance");
  411. }
  412. private IEnumerable<PythonType> GetTypes(IEnumerable<IAnalysisValue> analysisValues) {
  413. foreach (var value in analysisValues) {
  414. yield return value.PythonType;
  415. }
  416. }
  417. private IEnumerable<string> GetTypeNames(IEnumerable<IAnalysisValue> analysisValues) {
  418. foreach (var value in analysisValues) {
  419. yield return value.ShortDescription;
  420. }
  421. }
  422. class VariableLocation {
  423. public readonly int StartLine;
  424. public readonly int StartCol;
  425. public readonly VariableType Type;
  426. public VariableLocation(int startLine, int startCol, VariableType type) {
  427. StartLine = startLine;
  428. StartCol = startCol;
  429. Type = type;
  430. }
  431. }
  432. [TestMethod]
  433. public void TestReferences() {
  434. // instance variables
  435. var text = @"
  436. # add ref w/o type info
  437. class C(object):
  438. def __init__(self, foo):
  439. self.abc = foo
  440. del self.abc
  441. print self.abc
  442. ";
  443. var entry = ProcessText(text);
  444. 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));
  445. VerifyReferences(entry.GetVariables("foo", GetLineNumber(text, "foo")), new VariableLocation(4, 24, VariableType.Definition), new VariableLocation(5, 20, VariableType.Reference));
  446. text = @"
  447. # add ref w/ type info
  448. class D(object):
  449. def __init__(self, foo):
  450. self.abc = foo
  451. del self.abc
  452. print self.abc
  453. D(42)";
  454. entry = ProcessText(text);
  455. 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));
  456. VerifyReferences(entry.GetVariables("foo", GetLineNumber(text, "foo")), new VariableLocation(4, 24, VariableType.Definition), new VariableLocation(5, 20, VariableType.Reference));
  457. VerifyReferences(entry.GetVariables("D", GetLineNumber(text, "D(42)")), new VariableLocation(9, 1, VariableType.Reference), new VariableLocation(3, 1, VariableType.Definition));
  458. // function definitions
  459. text = @"
  460. def f(): pass
  461. x = f()";
  462. entry = ProcessText(text);
  463. VerifyReferences(entry.GetVariables("f", GetLineNumber(text, "x =")), new VariableLocation(4, 5, VariableType.Reference), new VariableLocation(2, 1, VariableType.Definition));
  464. text = @"
  465. from System import EventHandler
  466. def g():
  467. x = EventHandler(f)
  468. def f(sender, args): pass
  469. ";
  470. entry = ProcessText(text);
  471. VerifyReferences(entry.GetVariables("f", GetLineNumber(text, "x =")), new VariableLocation(4, 22, VariableType.Reference), new VariableLocation(6, 1, VariableType.Definition));
  472. text = @"
  473. from System import EventHandler
  474. def f(sender, args): pass
  475. x = EventHandler(f)";
  476. entry = ProcessText(text);
  477. VerifyReferences(entry.GetVariables("f", GetLineNumber(text, "x =")), new VariableLocation(5, 18, VariableType.Reference), new VariableLocation(3, 1, VariableType.Definition));
  478. // left hand side is unknown, right hand side should still have refs added
  479. text = @"
  480. from System import EventHandler
  481. def f(sender, args): pass
  482. a.foo += EventHandler(f)
  483. ";
  484. entry = ProcessText(text);
  485. VerifyReferences(entry.GetVariables("f", GetLineNumber(text, "a.foo +=")), new VariableLocation(5, 23, VariableType.Reference), new VariableLocation(3, 1, VariableType.Definition));
  486. text = @"
  487. def f(): pass
  488. x = f";
  489. entry = ProcessText(text);
  490. VerifyReferences(entry.GetVariables("f", GetLineNumber(text, "x =")), new VariableLocation(4, 5, VariableType.Reference), new VariableLocation(2, 1, VariableType.Definition));
  491. // class variables
  492. text = @"
  493. class D(object):
  494. abc = 42
  495. print abc
  496. del abc
  497. ";
  498. entry = ProcessText(text);
  499. 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));
  500. // class definition
  501. text = @"
  502. class D(object): pass
  503. a = D
  504. ";
  505. entry = ProcessText(text);
  506. VerifyReferences(entry.GetVariables("D", GetLineNumber(text, "a =")), new VariableLocation(4, 5, VariableType.Reference), new VariableLocation(2, 1, VariableType.Definition));
  507. // method definition
  508. text = @"
  509. class D(object):
  510. def f(self): pass
  511. a = D().f()
  512. ";
  513. entry = ProcessText(text);
  514. VerifyReferences(entry.GetVariables("D().f", GetLineNumber(text, "a =")),
  515. new VariableLocation(5, 5, VariableType.Reference), new VariableLocation(3, 5, VariableType.Definition));
  516. // globals
  517. text = @"
  518. abc = 42
  519. print abc
  520. del abc
  521. ";
  522. entry = ProcessText(text);
  523. 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));
  524. // parameters
  525. text = @"
  526. def f(abc):
  527. print abc
  528. abc = 42
  529. del abc
  530. ";
  531. entry = ProcessText(text);
  532. 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));
  533. // grammer test - statements
  534. text = @"
  535. def f(abc):
  536. try: pass
  537. except abc: pass
  538. try: pass
  539. except TypeError, abc: pass
  540. abc, bar = 42, 23
  541. abc[23] = 42
  542. abc.foo = 42
  543. abc += 2
  544. class D(abc): pass
  545. for x in abc: print x
  546. import abc
  547. from xyz import abc
  548. from xyz import bar as abc
  549. if abc: print 'hi'
  550. elif abc: print 'bye'
  551. else: abc
  552. with abc:
  553. return abc
  554. print abc
  555. assert abc, abc
  556. raise abc
  557. raise abc, abc, abc
  558. while abc:
  559. abc
  560. else:
  561. abc
  562. for x in foo:
  563. print x
  564. else:
  565. print abc
  566. try: pass
  567. except TypeError:
  568. else:
  569. abc
  570. ";
  571. entry = ProcessText(text);
  572. VerifyReferences(entry.GetVariables("abc", GetLineNumber(text, "f(abc)")),
  573. new VariableLocation(2, 7, VariableType.Definition),
  574. new VariableLocation(4, 12, VariableType.Reference),
  575. new VariableLocation(7, 23, VariableType.Definition),
  576. new VariableLocation(9, 5, VariableType.Definition),
  577. new VariableLocation(10, 5, VariableType.Reference),
  578. new VariableLocation(11, 5, VariableType.Reference),
  579. new VariableLocation(12, 5, VariableType.Reference),
  580. new VariableLocation(14, 13, VariableType.Reference),
  581. new VariableLocation(16, 14, VariableType.Reference),
  582. new VariableLocation(18, 5, VariableType.Reference),
  583. new VariableLocation(19, 5, VariableType.Reference),
  584. new VariableLocation(20, 5, VariableType.Reference),
  585. new VariableLocation(22, 8, VariableType.Reference),
  586. new VariableLocation(23, 10, VariableType.Reference),
  587. new VariableLocation(24, 11, VariableType.Reference),
  588. new VariableLocation(26, 10, VariableType.Reference),
  589. new VariableLocation(27, 16, VariableType.Reference),
  590. new VariableLocation(29, 11, VariableType.Reference),
  591. new VariableLocation(30, 12, VariableType.Reference),
  592. new VariableLocation(30, 17, VariableType.Reference),
  593. new VariableLocation(32, 11, VariableType.Reference),
  594. new VariableLocation(33, 11, VariableType.Reference),
  595. new VariableLocation(33, 16, VariableType.Reference),
  596. new VariableLocation(33, 21, VariableType.Reference),
  597. new VariableLocation(35, 11, VariableType.Reference),
  598. new VariableLocation(36, 9, VariableType.Reference),
  599. new VariableLocation(38, 9, VariableType.Reference),
  600. new VariableLocation(43, 15, VariableType.Reference),
  601. new VariableLocation(48, 9, VariableType.Reference)
  602. );
  603. // grammer test - expressions
  604. text = @"
  605. def f(abc):
  606. x = abc + 2
  607. x = 2 + abc
  608. x = l[abc]
  609. x = abc[l]
  610. x = abc.foo
  611. g(abc)
  612. abc if abc else abc
  613. {abc:abc},
  614. [abc, abc]
  615. (abc, abc)
  616. {abc}
  617. yield abc
  618. [x for x in abc]
  619. (x for x in abc)
  620. abc or abc
  621. abc and abc
  622. +abc
  623. x[abc:abc:abc]
  624. abc == abc
  625. not abc
  626. lambda : abc
  627. ";
  628. entry = ProcessText(text);
  629. VerifyReferences(entry.GetVariables("abc", GetLineNumber(text, "f(abc)")),
  630. new VariableLocation(2, 7, VariableType.Definition),
  631. new VariableLocation(3, 9, VariableType.Reference),
  632. new VariableLocation(4, 13, VariableType.Reference),
  633. new VariableLocation(5, 10, VariableType.Reference), // BUGBUG: should be 5,11
  634. new VariableLocation(6, 9, VariableType.Reference),
  635. new VariableLocation(7, 9, VariableType.Reference),
  636. new VariableLocation(9, 7, VariableType.Reference),
  637. new VariableLocation(11, 5, VariableType.Reference),
  638. new VariableLocation(11, 12, VariableType.Reference),
  639. new VariableLocation(11, 21, VariableType.Reference),
  640. new VariableLocation(13, 6, VariableType.Reference),
  641. new VariableLocation(13, 10, VariableType.Reference),
  642. new VariableLocation(14, 6, VariableType.Reference),
  643. new VariableLocation(14, 11, VariableType.Reference),
  644. new VariableLocation(15, 6, VariableType.Reference),
  645. new VariableLocation(15, 11, VariableType.Reference),
  646. new VariableLocation(16, 6, VariableType.Reference),
  647. new VariableLocation(18, 11, VariableType.Reference),
  648. new VariableLocation(19, 17, VariableType.Reference),
  649. new VariableLocation(20, 17, VariableType.Reference),
  650. new VariableLocation(22, 5, VariableType.Reference),
  651. new VariableLocation(22, 12, VariableType.Reference),
  652. new VariableLocation(23, 5, VariableType.Reference),
  653. new VariableLocation(23, 13, VariableType.Reference),
  654. new VariableLocation(25, 6, VariableType.Reference),
  655. new VariableLocation(26, 7, VariableType.Reference),
  656. new VariableLocation(26, 11, VariableType.Reference),
  657. new VariableLocation(26, 15, VariableType.Reference),
  658. new VariableLocation(28, 5, VariableType.Reference),
  659. new VariableLocation(28, 12, VariableType.Reference),
  660. new VariableLocation(29, 9, VariableType.Reference)
  661. //new VariableLocation(30, 14, VariableType.Reference) // BUGBUG: Enable when lambda bodies are walked
  662. );
  663. }
  664. private void VerifyReferences(IEnumerable<IAnalysisVariable> variables, params VariableLocation[] variableType) {
  665. var vars = new List<IAnalysisVariable>(variables);
  666. if (vars.Count == 0) {
  667. Assert.Fail("Got no references");
  668. }
  669. int removed = 0;
  670. bool removedOne = false;
  671. do {
  672. for (int j = 0; j < variableType.Length; j++) {
  673. var expected = variableType[j];
  674. bool found = false;
  675. for (int i = 0; i < vars.Count; i++) {
  676. var have = vars[i];
  677. if (have.Location.Line == expected.StartLine &&
  678. have.Location.Column == expected.StartCol &&
  679. have.Type == expected.Type) {
  680. vars.RemoveAt(i);
  681. removed++;
  682. removedOne = found = true;
  683. break;
  684. }
  685. }
  686. if (!found) {
  687. StringBuilder error = new StringBuilder(String.Format("Failed to find location: {0} {1} {2}" + Environment.NewLine, expected.StartLine, expected.StartCol, expected.Type));
  688. LocationNames(vars, error);
  689. Assert.Fail(error.ToString());
  690. }
  691. }
  692. } while (vars.Count != 0 && removedOne);
  693. if (vars.Count != 0) {
  694. StringBuilder error = new StringBuilder("Didn't use all locations - had " + variables.Count() + Environment.NewLine);
  695. LocationNames(vars, error);
  696. Assert.Fail(error.ToString());
  697. }
  698. }
  699. private static void LocationNames(List<IAnalysisVariable> vars, StringBuilder error) {
  700. foreach (var var in vars) {
  701. error.AppendFormat(" {0} {1} {2}", var.Location.Line, var.Location.Column, var.Type);
  702. error.AppendLine();
  703. }
  704. }
  705. [TestMethod]
  706. public void TestSignatureDefaults() {
  707. var entry = ProcessText(@"
  708. def f(x = None): pass
  709. def g(x = {}): pass
  710. def h(x = {2:3}): pass
  711. def i(x = []): pass
  712. def j(x = [None]): pass
  713. def k(x = ()): pass
  714. def l(x = (2, )): pass
  715. ");
  716. var tests = new[] {
  717. new { FuncName = "f", ParamName="x = None" },
  718. new { FuncName = "g", ParamName="x = {}" },
  719. new { FuncName = "h", ParamName="x = {...}" },
  720. new { FuncName = "i", ParamName="x = []" },
  721. new { FuncName = "j", ParamName="x = [...]" },
  722. new { FuncName = "k", ParamName="x = ()" },
  723. new { FuncName = "l", ParamName="x = (...)" },
  724. };
  725. foreach (var test in tests) {
  726. var result = entry.GetSignatures(test.FuncName, 1).ToArray();
  727. Assert.AreEqual(result.Length, 1);
  728. Assert.AreEqual(result[0].Parameters[0].Name, test.ParamName);
  729. }
  730. }
  731. [TestMethod]
  732. public void TestGetVariablesDictionaryGet() {
  733. var entry = ProcessText(@"
  734. x = {42:'abc'}
  735. ");
  736. foreach (var varRef in entry.GetValues("x.get", 1)) {
  737. Assert.AreEqual("built-in method get", varRef.Description);
  738. }
  739. }
  740. [TestMethod]
  741. public void TestLambdaExpression() {
  742. var entry = ProcessText(@"
  743. x = lambda a: a
  744. y = x(42)
  745. ");
  746. AssertContainsExactly(entry.GetTypesFromName("y", 1), IntType);
  747. entry = ProcessText(@"
  748. def f(a):
  749. return a
  750. x = lambda b: f(b)
  751. y = x(42)
  752. ");
  753. AssertContainsExactly(entry.GetTypesFromName("y", 1), IntType);
  754. }
  755. [TestMethod]
  756. public void TestRecursiveClass() {
  757. var entry = ProcessText(@"
  758. cls = object
  759. class cls(cls):
  760. abc = 42
  761. ");
  762. entry.GetMembersFromName("cls", 1);
  763. AssertContainsExactly(entry.GetMembers("cls().abc.", 1).Select(member => member.Name), _intMembers);
  764. AssertContainsExactly(entry.GetMembers("cls.abc.", 1).Select(member => member.Name), _intMembers);
  765. }
  766. [TestMethod]
  767. public void TestBadMethod() {
  768. var entry = ProcessText(@"
  769. class cls(object):
  770. def f():
  771. return 42
  772. abc = cls()
  773. foo = abc.f()
  774. ");
  775. AssertContainsExactly(entry.GetMembers("foo.", 1).Select(member => member.Name), _intMembers);
  776. }
  777. [TestMethod]
  778. public void TestKeywordArguments() {
  779. var funcDef = "def f(a, b, c): pass";
  780. var classWithInit = @"class f(object):
  781. def __init__(self, a, b, c):
  782. pass";
  783. var classWithNew = @"class f(object):
  784. def __new__(cls, a, b, c):
  785. pass";
  786. var method = @"class x(object):
  787. def g(self, a, b, c):
  788. pass
  789. f = x().g";
  790. var decls = new [] { funcDef, classWithInit, classWithNew, method };
  791. foreach (var decl in decls) {
  792. string[] testCalls = new[] {
  793. "f(c = 'abc', b = 42, a = 3j)", "f(3j, c = 'abc', b = 42)", "f(3j, 42, c = 'abc')",
  794. "f(c = 'abc', b = 42, a = 3j, d = 42)", // extra argument
  795. "f(3j, 42, 'abc', d = 42)",
  796. };
  797. foreach (var testCall in testCalls) {
  798. var text = decl + Environment.NewLine + testCall;
  799. var entry = ProcessText(text);
  800. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "pass")), ComplexType);
  801. AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "pass")), IntType);
  802. AssertContainsExactly(entry.GetTypesFromName("c", GetLineNumber(text, "pass")), StringType);
  803. }
  804. }
  805. }
  806. [TestMethod]
  807. public void TestPositionalSplat() {
  808. var funcDef = "def f(a, b, c): pass";
  809. var classWithInit = @"class f(object):
  810. def __init__(self, a, b, c):
  811. pass";
  812. var classWithNew = @"class f(object):
  813. def __new__(cls, a, b, c):
  814. pass";
  815. var method = @"class x(object):
  816. def g(self, a, b, c):
  817. pass
  818. f = x().g";
  819. var decls = new[] { funcDef, classWithInit, classWithNew, method };
  820. foreach (var decl in decls) {
  821. string[] testCalls = new[] {
  822. "f(*(3j, 42, 'abc'))",
  823. "f(*[3j, 42, 'abc'])",
  824. "f(*(3j, 42, 'abc', 4L))", // extra argument
  825. "f(*[3j, 42, 'abc', 4L])", // extra argument
  826. };
  827. foreach (var testCall in testCalls) {
  828. var text = decl + Environment.NewLine + testCall;
  829. var entry = ProcessText(text);
  830. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "pass")), ComplexType);
  831. AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "pass")), IntType);
  832. AssertContainsExactly(entry.GetTypesFromName("c", GetLineNumber(text, "pass")), StringType);
  833. }
  834. }
  835. }
  836. [TestMethod]
  837. public void TestForwardRef() {
  838. var text = @"
  839. class D(object):
  840. def bar(self, x):
  841. abc = C()
  842. abc.foo(2)
  843. a = abc.foo(2.0)
  844. a.bar(('a', 'b', 'c', 'd'))
  845. class C(object):
  846. def foo(self, x):
  847. D().bar('abc')
  848. D().bar(['a', 'b', 'c'])
  849. return D()
  850. def baz(self): pass
  851. ";
  852. var entry = ProcessText(text);
  853. var fifty = entry.GetVariablesNoBuiltins(GetLineNumber(text, "abc.foo")).ToSet();
  854. AssertContainsExactly(fifty, "C", "D", "a", "abc", "self", "x");
  855. var three = entry.GetVariablesNoBuiltins(GetLineNumber(text, "lass D")).ToSet();
  856. AssertContainsExactly(three, "C", "D", "bar");
  857. var allFifty = entry.GetMembersFromName("abc", GetLineNumber(text, "abc.foo")).ToSet();
  858. AssertContainsExactly(allFifty, GetUnion(_objectMembers, "baz", "foo"));
  859. var xTypes = entry.GetTypesFromName("x", GetLineNumber(text, "abc.foo")).ToSet();
  860. AssertContainsExactly(xTypes, ListType, StringType, TupleType);
  861. var xMembers = entry.GetMembersFromName("x", GetLineNumber(text, "abc.foo")).ToSet();
  862. AssertContainsExactly(xMembers, GetIntersection(_strMembers, _listMembers));
  863. }
  864. private static int GetLineNumber(string text, string substring) {
  865. string[] splitLines = text.Split('\n');
  866. for (int i = 0; i < splitLines.Length; i++) {
  867. if (splitLines[i].IndexOf(substring) != -1) {
  868. return i + 1;
  869. }
  870. }
  871. throw new InvalidOperationException();
  872. }
  873. [TestMethod]
  874. public void TestBuiltins() {
  875. var text = @"
  876. booltypetrue = True
  877. booltypefalse = False
  878. ";
  879. var entry = ProcessText(text);
  880. AssertContainsExactly(entry.GetTypesFromName("booltypetrue", 1), BoolType);
  881. AssertContainsExactly(entry.GetTypesFromName("booltypefalse", 1), BoolType);
  882. }
  883. [TestMethod]
  884. public void TestDictionaryFunctionTable() {
  885. var text = @"
  886. def f(a, b):
  887. print a, b
  888. def g(a, b):
  889. x, y = a, b
  890. x = {'foo': f, 'bar' : g}
  891. x['foo'](42, [])
  892. ";
  893. var entry = ProcessText(text);
  894. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "print")), IntType);
  895. AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "print")), ListType);
  896. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "x, y")), IntType);
  897. AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "x, y")), ListType);
  898. }
  899. [TestMethod]
  900. public void TestDictionaryAssign() {
  901. var text = @"
  902. x = {'abc': 42}
  903. y = x['foo']
  904. ";
  905. var entry = ProcessText(text);
  906. AssertContainsExactly(entry.GetTypesFromName("y", 1), IntType);
  907. }
  908. [TestMethod]
  909. public void TestDictionaryFunctionTableGet2() {
  910. var text = @"
  911. def f(a, b):
  912. print a, b
  913. def g(a, b):
  914. x, y = a, b
  915. x = {'foo': f, 'bar' : g}
  916. x.get('foo')(42, [])
  917. ";
  918. var entry = ProcessText(text);
  919. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "print")), IntType);
  920. AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "print")), ListType);
  921. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "x, y")), IntType);
  922. AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "x, y")), ListType);
  923. }
  924. [TestMethod]
  925. public void TestDictionaryFunctionTableGet() {
  926. var text = @"
  927. def f(a, b):
  928. print a, b
  929. def g(a, b):
  930. x, y = a, b
  931. x = {'foo': f, 'bar' : g}
  932. y = x.get('foo', None)
  933. if y is not None:
  934. y(42, [])
  935. ";
  936. var entry = ProcessText(text);
  937. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "print")), IntType);
  938. AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "print")), ListType);
  939. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "x, y")), IntType);
  940. AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "x, y")), ListType);
  941. }
  942. [TestMethod]
  943. public void TestSimpleGlobals() {
  944. var text = @"
  945. class x(object):
  946. def abc(self):
  947. pass
  948. a = x()
  949. x.abc()
  950. ";
  951. var entry = ProcessText(text);
  952. AssertContainsExactly(entry.GetVariablesNoBuiltins(1), "a", "x");
  953. AssertContainsExactly(entry.GetMembersFromName("x", 1), GetUnion(_objectMembers, "abc"));
  954. }
  955. [TestMethod]
  956. public void TestFuncCallInIf() {
  957. var text = @"
  958. def Method(a, b, c):
  959. print a, b, c
  960. if not Method(42, 'abc', []):
  961. pass
  962. ";
  963. var entry = ProcessText(text);
  964. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "print")), IntType);
  965. AssertContainsExactly(entry.GetTypesFromName("b", GetLineNumber(text, "print")), StringType);
  966. AssertContainsExactly(entry.GetTypesFromName("c", GetLineNumber(text, "print")), ListType);
  967. }
  968. [TestMethod]
  969. public void TestWithStatement() {
  970. var text = @"
  971. class x(object):
  972. def x_method(self):
  973. pass
  974. with x() as foo:
  975. print foo
  976. with x():
  977. pass
  978. ";
  979. var entry = ProcessText(text);
  980. var foo = entry.GetMembersFromName("foo", GetLineNumber(text, "print foo"));
  981. AssertContainsExactly(foo, GetUnion(_objectMembers, "x_method"));
  982. }
  983. [TestMethod]
  984. public void TestOverrideFunction() {
  985. var text = @"
  986. class bar(object):
  987. def Call(self, xvar, yvar):
  988. pass
  989. class baz(bar):
  990. def Call(self, xvar, yvar):
  991. pass
  992. class Cxxxx(object):
  993. def __init__(self):
  994. self.foo = baz()
  995. def Cmeth(self, avar, bvar):
  996. self.foo.Call(avar, bvar)
  997. abc = Cxxxx()
  998. abc.Cmeth(['foo'], 'bar')
  999. ";
  1000. var entry = ProcessText(text);
  1001. AssertContainsExactly(entry.GetTypesFromName("xvar", GetLineNumber(text, "pass")), ListType);
  1002. }
  1003. [TestMethod]
  1004. public void TestSimpleMethodCall() {
  1005. var text = @"
  1006. class x(object):
  1007. def abc(self, foo):
  1008. pass
  1009. a = x()
  1010. a.abc('abc')
  1011. ";
  1012. var entry = ProcessText(text);
  1013. AssertContainsExactly(entry.GetTypesFromName("foo", GetLineNumber(text, "pass")), StringType);
  1014. AssertContainsExactly(entry.GetMembersFromName("self", GetLineNumber(text, "pass")), GetUnion(_objectMembers, "abc"));
  1015. }
  1016. [TestMethod]
  1017. public void TestSystemFromImport() {
  1018. var text = @"
  1019. from System import Environment
  1020. Environment.GetCommandLineArgs()
  1021. ";
  1022. var entry = ProcessText(text);
  1023. Assert.IsTrue(entry.GetMembersFromName("Environment", 1).Any(s => s == "CommandLine"));
  1024. }
  1025. [TestMethod]
  1026. public void TestImportAs() {
  1027. var text = @"
  1028. import System.Collections as coll
  1029. ";
  1030. var entry = ProcessText(text);
  1031. Assert.IsTrue(entry.GetMembersFromName("coll", 1).Any(s => s == "ArrayList"));
  1032. }
  1033. [TestMethod]
  1034. public void TestSystemImport() {
  1035. var text = @"
  1036. import System
  1037. System.Environment.GetCommandLineArgs()
  1038. x = System.Environment
  1039. ";
  1040. var entry = ProcessText(text);
  1041. var system = entry.GetMembersFromName("System", 1).ToSet();
  1042. // defined in mscorlib
  1043. AssertContains(system, "AccessViolationException");
  1044. // defined in System
  1045. AssertContains(system, "CodeDom");
  1046. AssertContains(entry.GetMembersFromName("x", 1), "GetEnvironmentVariables");
  1047. }
  1048. [TestMethod]
  1049. public void TestSystemMembers() {
  1050. var text = @"
  1051. import System
  1052. System.Environment.GetCommandLineArgs()
  1053. x = System.Environment
  1054. args = x.GetCommandLineArgs()
  1055. ";
  1056. var entry = ProcessText(text);
  1057. var args = entry.GetTypesFromName("args", GetLineNumber(text, "args =")).ToSet();
  1058. AssertContainsExactly(args, ClrModule.GetPythonType(typeof(string[])));
  1059. Assert.IsTrue(entry.GetMembersFromName("args", GetLineNumber(text, "args =")).Any(s => s == "AsReadOnly"));
  1060. }
  1061. [TestMethod]
  1062. public void TestNamespaceMembers() {
  1063. var text = @"
  1064. import System
  1065. x = System.Collections
  1066. ";
  1067. var entry = ProcessText(text);
  1068. var x = entry.GetMembersFromName("x", GetLineNumber(text, "x =")).ToSet();
  1069. Assert.IsTrue(x.Contains("Generic"));
  1070. Assert.IsTrue(x.Contains("ArrayList"));
  1071. }
  1072. [TestMethod]
  1073. public void TestBuiltinRetval() {
  1074. var text = @"
  1075. x = [2,3,4]
  1076. a = x.index(2)
  1077. ";
  1078. var entry = ProcessText(text);
  1079. AssertContainsExactly(entry.GetTypesFromName("x", GetLineNumber(text, "x =")).ToSet(), ListType);
  1080. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "a =")).ToSet(), IntType);
  1081. }
  1082. [TestMethod]
  1083. public void TestBuiltinFuncRetval() {
  1084. var text = @"
  1085. x = ord('a')
  1086. y = range(5)
  1087. ";
  1088. var entry = ProcessText(text);
  1089. AssertContainsExactly(entry.GetTypesFromName("x", GetLineNumber(text, "x = ")).ToSet(), IntType);
  1090. AssertContainsExactly(entry.GetTypesFromName("y", GetLineNumber(text, "y = ")).ToSet(), ListType);
  1091. }
  1092. [TestMethod]
  1093. public void TestFunctionMembers() {
  1094. var text = @"
  1095. def f(x): pass
  1096. f.abc = 32
  1097. ";
  1098. var entry = ProcessText(text);
  1099. AssertContains(entry.GetMembersFromName("f", 1), "abc");
  1100. text = @"
  1101. def f(x): pass
  1102. ";
  1103. entry = ProcessText(text);
  1104. AssertDoesntContain(entry.GetMembersFromName("f", 1), "x");
  1105. AssertContainsExactly(entry.GetMembersFromName("f", 1), _functionMembers);
  1106. AssertContainsExactly(entry.GetMembersFromName("f.func_name", 1), _strMembers);
  1107. }
  1108. [TestMethod]
  1109. public void TestRangeIteration() {
  1110. var text = @"
  1111. for i in range(5):
  1112. pass
  1113. ";
  1114. var entry = ProcessText(text);
  1115. AssertContainsExactly(entry.GetTypesFromName("i", GetLineNumber(text, "for i")).ToSet(), IntType);
  1116. }
  1117. [TestMethod]
  1118. public void TestBuiltinImport() {
  1119. var text = @"
  1120. import sys
  1121. ";
  1122. var entry = ProcessText(text);
  1123. AssertContainsExactly(entry.GetVariablesNoBuiltins(1), "sys");
  1124. Assert.IsTrue(entry.GetMembersFromName("sys", 1).Any((s) => s == "winver"));
  1125. }
  1126. [TestMethod]
  1127. public void TestBuiltinImportInFunc() {
  1128. var text = @"
  1129. def f():
  1130. import sys
  1131. ";
  1132. var entry = ProcessText(text);
  1133. AssertContainsExactly(entry.GetVariablesNoBuiltins(GetLineNumber(text, "sys")), "f", "sys");
  1134. AssertContains(entry.GetMembersFromName("sys", GetLineNumber(text, "sys")), "winver");
  1135. }
  1136. [TestMethod]
  1137. public void TestBuiltinImportInClass() {
  1138. var text = @"
  1139. class C:
  1140. import sys
  1141. ";
  1142. var entry = ProcessText(text);
  1143. AssertContainsExactly(entry.GetVariablesNoBuiltins(GetLineNumber(text, "sys")), "C", "sys");
  1144. Assert.IsTrue(entry.GetMembersFromName("sys", GetLineNumber(text, "sys")).Any((s) => s == "winver"));
  1145. }
  1146. [TestMethod]
  1147. public void TestNoImportClr() {
  1148. var text = @"
  1149. x = 'abc'
  1150. ";
  1151. var entry = ProcessText(text);
  1152. AssertContainsExactly(entry.GetTypesFromName("x", 1), StringType);
  1153. AssertContainsExactly(entry.GetMembersFromName("x", 1), _strMembers);
  1154. }
  1155. [TestMethod]
  1156. public void TestImportClr() {
  1157. var text = @"
  1158. import clr
  1159. x = 'abc'
  1160. ";
  1161. var entry = ProcessText(text);
  1162. AssertContainsExactly(entry.GetMembersFromName("x", 1), _strMembersClr);
  1163. }
  1164. [TestMethod]
  1165. public void TestClrAddReference() {
  1166. var text = @"
  1167. import clr
  1168. clr.AddReference('System.Drawing')
  1169. from System.Drawing import Point
  1170. ";
  1171. var entry = ProcessText(text);
  1172. Assert.AreEqual(35, entry.GetMembersFromName("Point", GetLineNumber(text, "from System.")).ToList().Count);
  1173. }
  1174. [TestMethod]
  1175. public void TestClrAddReferenceByName() {
  1176. var text = @"
  1177. import clr
  1178. clr.AddReferenceByName('Microsoft.Scripting')
  1179. from Microsoft.Scripting import SourceUnit
  1180. ";
  1181. var entry = ProcessText(text);
  1182. Assert.AreEqual(40, entry.GetMembersFromName("SourceUnit", GetLineNumber(text, "from Microsoft.")).ToList().Count);
  1183. }
  1184. [TestMethod]
  1185. public void TestMutualRecursion() {
  1186. var text = @"
  1187. class C:
  1188. def f(self, other, depth):
  1189. if depth == 0:
  1190. return 'abc'
  1191. return other.g(self, depth - 1)
  1192. class D:
  1193. def g(self, other, depth):
  1194. if depth == 0:
  1195. return ['d', 'e', 'f']
  1196. return other.f(self, depth - 1)
  1197. x = D().g(C(), 42)
  1198. ";
  1199. var entry = ProcessText(text);
  1200. AssertContainsExactly(entry.GetMembersFromName("other", GetLineNumber(text, "other.g")), "g");
  1201. AssertContainsExactly(entry.GetTypesFromName("x", GetLineNumber(text, "x =")), ListType, StringType);
  1202. AssertContainsExactly(entry.GetMembersFromName("x", GetLineNumber(text, "x =")),
  1203. GetIntersection(_listMembers, _strMembers));
  1204. }
  1205. [TestMethod]
  1206. public void TestForwardRefVars() {
  1207. var text = @"
  1208. class x(object):
  1209. def __init__(self, val):
  1210. self.abc = []
  1211. x(42)
  1212. x('abc')
  1213. x([])
  1214. ";
  1215. var entry = ProcessText(text);
  1216. Assert.AreEqual(1, entry.GetValues("self.abc", GetLineNumber(text, "self.abc")).ToList().Count);
  1217. }
  1218. [TestMethod]
  1219. public void TestReturnFunc() {
  1220. var text = @"
  1221. def g():
  1222. return []
  1223. def f():
  1224. return g
  1225. x = f()()
  1226. ";
  1227. var entry = ProcessText(text);
  1228. AssertContainsExactly(entry.GetTypesFromName("x", 1), ListType);
  1229. }
  1230. [TestMethod]
  1231. public void TestReturnArg() {
  1232. var text = @"
  1233. def g(a):
  1234. return a
  1235. x = g(1)
  1236. ";
  1237. var entry = ProcessText(text);
  1238. AssertContainsExactly(entry.GetTypesFromName("x", 1), IntType);
  1239. }
  1240. [TestMethod]
  1241. public void TestReturnArg2() {
  1242. var text = @"
  1243. def f(a):
  1244. def g():
  1245. return a
  1246. return g
  1247. x = f(2)()
  1248. ";
  1249. var entry = ProcessText(text);
  1250. AssertContainsExactly(entry.GetTypesFromName("x", 1), IntType);
  1251. }
  1252. [TestMethod]
  1253. public void TestMemberAssign() {
  1254. var text = @"
  1255. class C:
  1256. def func(self):
  1257. self.abc = 42
  1258. a = C()
  1259. a.func()
  1260. foo = a.abc
  1261. ";
  1262. var entry = ProcessText(text);
  1263. AssertContainsExactly(entry.GetTypesFromName("foo", 1), IntType);
  1264. AssertContainsExactly(entry.GetMembersFromName("foo", 1), _intMembers);
  1265. AssertContainsExactly(entry.GetMembersFromName("a", 1), "abc", "func");
  1266. }
  1267. [TestMethod]
  1268. public void TestMemberAssign2() {
  1269. var text = @"
  1270. class D:
  1271. def func2(self):
  1272. a = C()
  1273. a.func()
  1274. return a.abc
  1275. class C:
  1276. def func(self):
  1277. self.abc = [2,3,4]
  1278. foo = D().func2()
  1279. ";
  1280. var entry = ProcessText(text);
  1281. // TODO: AssertContainsExactly(entry.GetTypesFromName("foo", 0), ListType);
  1282. }
  1283. [TestMethod]
  1284. public void TestUnfinishedDot() {
  1285. // the partial dot should be ignored and we shouldn't see g as
  1286. // a member of D
  1287. var text = @"
  1288. class D(object):
  1289. def func(self):
  1290. self.
  1291. def g(a, b, c): pass
  1292. ";
  1293. var entry = ProcessText(text);
  1294. AssertContainsExactly(entry.GetMembersFromName("self", GetLineNumber(text, "self")),
  1295. GetUnion(_objectMembers, "func"));
  1296. }
  1297. [TestMethod]
  1298. public void TestCrossModule() {
  1299. var text1 = @"
  1300. import mod2
  1301. ";
  1302. var text2 = @"
  1303. x = 42
  1304. ";
  1305. PermutedTest("mod", new[] { text1, text2 }, (pe) => {
  1306. AssertContainsExactly(pe[0].Analysis.GetMembersFromName("mod2", 1), "x");
  1307. });
  1308. }
  1309. [TestMethod]
  1310. public void TestCrossModuleCall() {
  1311. var text1 = @"
  1312. import mod2
  1313. y = mod2.f('abc')
  1314. ";
  1315. var text2 = @"
  1316. def f(x):
  1317. return x
  1318. ";
  1319. PermutedTest("mod", new[] { text1, text2 }, (pe) => {
  1320. AssertContainsExactly(pe[1].Analysis.GetTypesFromName("x", GetLineNumber(text2, "return x")), StringType);
  1321. AssertContainsExactly(pe[0].Analysis.GetTypesFromName("y", GetLineNumber(text1, "y")), StringType);
  1322. });
  1323. }
  1324. [TestMethod]
  1325. public void TestCrossModuleCallType() {
  1326. var text1 = @"
  1327. import mod2
  1328. y = mod2.c('abc').x
  1329. ";
  1330. var text2 = @"
  1331. class c:
  1332. def __init__(self, x):
  1333. self.x = x
  1334. ";
  1335. PermutedTest("mod", new[] { text1, text2 }, (pe) => {
  1336. AssertContainsExactly(pe[1].Analysis.GetTypesFromName("x", GetLineNumber(text2, "= x")), StringType);
  1337. AssertContainsExactly(pe[0].Analysis.GetTypesFromName("y", GetLineNumber(text1, "y")), StringType);
  1338. });
  1339. }
  1340. [TestMethod]
  1341. public void TestCrossModuleCallType2() {
  1342. var text1 = @"
  1343. from mod2 import c
  1344. class x(object):
  1345. def Foo(self):
  1346. y = c('abc').x
  1347. ";
  1348. var text2 = @"
  1349. class c:
  1350. def __init__(self, x):
  1351. self.x = x
  1352. ";
  1353. PermutedTest("mod", new[] { text1, text2 }, (pe) => {
  1354. AssertContainsExactly(pe[1].Analysis.GetTypesFromName("x", GetLineNumber(text2, "= x")), StringType);
  1355. AssertContainsExactly(pe[0].Analysis.GetTypesFromName("y", GetLineNumber(text1, "y =")), StringType);
  1356. });
  1357. }
  1358. [TestMethod]
  1359. public void TestCrossModuleFuncAndType() {
  1360. var text1 = @"
  1361. class Something(object):
  1362. def f(self): pass
  1363. def g(self): pass
  1364. def SomeFunc():
  1365. x = Something()
  1366. return x
  1367. ";
  1368. var text2 = @"
  1369. from mod1 import SomeFunc
  1370. x = SomeFunc()
  1371. ";
  1372. var text3 = @"
  1373. from mod2 import x
  1374. a = x
  1375. ";
  1376. PermutedTest("mod", new[] { text1, text2, text3 }, (pe) => {
  1377. AssertContainsExactly(pe[2].Analysis.GetMembersFromName("a", GetLineNumber(text3, "a = ")),
  1378. GetUnion(_objectMembers, "f", "g"));
  1379. });
  1380. }
  1381. [TestMethod]
  1382. public void TestMembersAfterError() {
  1383. var text = @"
  1384. class X(object):
  1385. def f(self):
  1386. return self.
  1387. def g(self):
  1388. pass
  1389. def h(self):
  1390. pass
  1391. ";
  1392. var entry = ProcessText(text);
  1393. AssertContainsExactly(entry.GetMembersFromName("self", GetLineNumber(text, "self")),
  1394. GetUnion(_objectMembers, "f", "g", "h"));
  1395. }
  1396. [TestMethod]
  1397. public void TestGenericIndexing() {
  1398. // indexing into a generic type should know how the type info
  1399. // flows through
  1400. var text = @"
  1401. from System.Collections.Generic import List
  1402. x = List[int]()
  1403. ";
  1404. var entry = ProcessText(text);
  1405. // AreEqual(entry.GetMembersFromName('x', len(text) - 1),
  1406. // get_intersect_members_clr(List[int]))
  1407. var self = new List<string>(entry.GetMembersFromName("x", GetLineNumber(text, "x =")));
  1408. Assert.IsTrue(self.Contains("AddRange"));
  1409. }
  1410. [TestMethod]
  1411. public void TestReturnTypesCollapsing() {
  1412. // indexing into a generic type should know how the type info
  1413. // flows through
  1414. var text = @"
  1415. from System import AppDomain
  1416. asm = AppDomain.CurrentDomain.DefineDynamicAssembly()
  1417. mod = asm.DefineDynamicModule()
  1418. mod.
  1419. ";
  1420. var entry = ProcessText(text);
  1421. var tooltips = entry.GetMembers("mod.", GetLineNumber(text, "mod ="))
  1422. .Where(m => m.Name == "CreateGlobalFunctions")
  1423. .Select(m => m.ToolTip)
  1424. .ToArray();
  1425. Assert.AreEqual(1, tooltips.Length);
  1426. var indexes = tooltips[0].FindIndexesOf("CreateGlobalFunctions").ToArray();
  1427. Assert.AreEqual(1, indexes.Length);
  1428. }
  1429. [TestMethod]
  1430. public void TestProperty() {
  1431. var text = @"
  1432. class x(object):
  1433. @property
  1434. def SomeProp(self):
  1435. return 42
  1436. a = x().SomeProp
  1437. ";
  1438. var entry = ProcessText(text);
  1439. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "a =")), IntType);
  1440. }
  1441. [TestMethod]
  1442. public void TestStaticMethod() {
  1443. var text = @"
  1444. class x(object):
  1445. @staticmethod
  1446. def StaticMethod(value):
  1447. return value
  1448. a = x().StaticMethod(4.0)
  1449. ";
  1450. var entry = ProcessText(text);
  1451. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "a = ")), FloatType);
  1452. }
  1453. [TestMethod]
  1454. public void TestClassMethod() {
  1455. var text = @"
  1456. class x(object):
  1457. @classmethod
  1458. def ClassMethod(cls):
  1459. return cls
  1460. a = x().ClassMethod()
  1461. ";
  1462. var entry = ProcessText(text);
  1463. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "a =")), TypeType);
  1464. }
  1465. [TestMethod]
  1466. public void TestAssignSelf() {
  1467. var text = @"
  1468. class x(object):
  1469. def __init__(self):
  1470. self.x = 'abc'
  1471. def f(self):
  1472. pass
  1473. ";
  1474. var entry = ProcessText(text);
  1475. AssertContains(entry.GetMembersFromName("self", GetLineNumber(text, "pass")), "x");
  1476. AssertContainsExactly(entry.GetMembers("self.x.", GetLineNumber(text, "pass")).Select(m => m.Name), _strMembers);
  1477. }
  1478. [TestMethod]
  1479. public void TestAssignEvent() {
  1480. var text = @"
  1481. import System
  1482. def f(sender, args):
  1483. pass
  1484. System.AppDomain.CurrentDomain.AssemblyLoad += f
  1485. ";
  1486. var entry = ProcessText(text);
  1487. Assert.IsTrue(entry.GetMembersFromName("args", GetLineNumber(text, "pass")).Any(s => s == "LoadedAssembly"));
  1488. }
  1489. /*
  1490. [TestMethod]
  1491. public void TestOverrideParams() {
  1492. var text = @"
  1493. import System
  1494. class MyArrayList(System.Collections.ArrayList):
  1495. def AddRange(self, col):
  1496. x = col
  1497. ";
  1498. var entry = ProcessText(text);
  1499. var x = entry.GetMembersFromName("x", text.IndexOf("x = col")).ToSet();
  1500. AssertContainsExactly(x, GetMembers(ClrModule.GetPythonType(typeof(System.Collections.ICollection)), true));
  1501. }*/
  1502. class EmptyAnalysisCookie : IAnalysisCookie {
  1503. public static EmptyAnalysisCookie Instance = new EmptyAnalysisCookie();
  1504. public string GetLine(int lineNo) {
  1505. throw new NotImplementedException();
  1506. }
  1507. }
  1508. [TestMethod]
  1509. public void TestPackage() {
  1510. var src1 = GetSourceUnit("", @"C:\\Test\\Lib\\foo\\__init__.py");
  1511. var src2 = GetSourceUnit(@"
  1512. from foo.y import abc
  1513. import foo.y as y
  1514. ", @"C:\\Test\\Lib\\foo\\x.py");
  1515. var src3 = GetSourceUnit(@"
  1516. abc = 42
  1517. ", @"C:\\Test\\Lib\\foo\\y.py");
  1518. var state = new ProjectState(_engine);
  1519. var package = state.AddModule("foo", src1.Path, EmptyAnalysisCookie.Instance);
  1520. var x = state.AddModule("foo.x", src2.Path, EmptyAnalysisCookie.Instance);
  1521. var y = state.AddModule("foo.y", src3.Path, EmptyAnalysisCookie.Instance);
  1522. Prepare(package, src1);
  1523. Prepare(x, src2);
  1524. Prepare(y, src3);
  1525. package.Analyze();
  1526. x.Analyze();
  1527. y.Analyze();
  1528. Assert.AreEqual(x.Analysis.GetValues("y", 1).First().Description, "Python module foo.y");
  1529. AssertContainsExactly(x.Analysis.GetTypesFromName("abc", 1), IntType);
  1530. }
  1531. private static void Prepare(ProjectEntry entry, SourceUnit sourceUnit) {
  1532. CollectingErrorSink errorSink = new CollectingErrorSink();
  1533. using (var parser = Utils.CreateParser(sourceUnit, errorSink)) {
  1534. entry.UpdateTree(parser.ParseFile(true), null);
  1535. }
  1536. }
  1537. /// <summary>
  1538. /// Verify that the analyzer has the proper algorithm for turning a filename into a package name
  1539. /// </summary>
  1540. [TestMethod]
  1541. public void TestPathToModuleName() {
  1542. string nzmathPath = Path.Combine(Environment.GetEnvironmentVariable("DLR_ROOT"), @"External.LCA_RESTRICTED\Languages\IronPython\Math");
  1543. Assert.AreEqual(PythonAnalyzer.PathToModuleName(Path.Combine(nzmathPath, @"nzmath\factor\__init__.py")), "nzmath.factor");
  1544. Assert.AreEqual(PythonAnalyzer.PathToModuleName(Path.Combine(nzmathPath, @"nzmath\factor\find.py")), "nzmath.factor.find");
  1545. }
  1546. [TestMethod]
  1547. public void TestDefaults() {
  1548. var text = @"
  1549. def f(x = 42):
  1550. return x
  1551. a = f()
  1552. ";
  1553. var entry = ProcessText(text);
  1554. AssertContainsExactly(entry.GetTypesFromName("a", GetLineNumber(text, "a =")), IntType);
  1555. }
  1556. [TestMethod]
  1557. public void TestNegCallProperty() {
  1558. // invalid code, this shouldn't crash us.
  1559. var text = @"
  1560. import System
  1561. x = System.String.Length()
  1562. y = System.Environment.CurrentDirectory()
  1563. ";
  1564. ProcessText(text);
  1565. }
  1566. [TestMethod]
  1567. public void TestClassInit() {
  1568. var text = @"
  1569. class X:
  1570. def __init__(self, value):
  1571. self.value = value
  1572. a = X(2)
  1573. ";
  1574. var entry = ProcessText(text);
  1575. AssertContainsExactly(entry.GetTypesFromName("value", GetLineNumber(text, " = value")), IntType);
  1576. }
  1577. [TestMethod]
  1578. public void TestClassNew() {
  1579. var text = @"
  1580. class X:
  1581. def __new__(cls, value):
  1582. res = object.__new__(cls)
  1583. res.value = value
  1584. return res
  1585. a = X(2)
  1586. ";
  1587. var entry = ProcessText(text);
  1588. AssertContainsExactly(entry.GetTypesFromName("value", GetLineNumber(text, " = value")), IntType);
  1589. }
  1590. private static IEnumerable<string> GetVariableDescriptions(ModuleAnalysis entry, string variable, int position) {
  1591. return entry.GetValues(variable, position).Select(m => m.Description);
  1592. }
  1593. [TestMethod]
  1594. public void TestQuickInfo() {
  1595. var text = @"
  1596. import System
  1597. import sys
  1598. from System.Collections import ArrayList
  1599. a = 41.0
  1600. b = 42L
  1601. c = 'abc'
  1602. x = (2, 3, 4)
  1603. y = [2, 3, 4]
  1604. z = 43
  1605. class foo(object):
  1606. @property
  1607. def f(self): pass
  1608. def g(self): pass
  1609. d = foo()
  1610. e = System.Collections.ArrayList()
  1611. def f():
  1612. print 'hello'
  1613. return 'abc'
  1614. def g():
  1615. return System
  1616. return c.Length
  1617. ";
  1618. var entry = ProcessText(text);
  1619. AssertContainsExactly(GetVariableDescriptions(entry, "foo()", 1), "foo instance");
  1620. AssertContainsExactly(GetVariableDescriptions(entry, "int()", 1), "int");
  1621. AssertContainsExactly(GetVariableDescriptions(entry, "a", 1), "float");
  1622. AssertContainsExactly(GetVariableDescriptions(entry, "a", 1), "float");
  1623. AssertContainsExactly(GetVariableDescriptions(entry, "b", 1), "long");
  1624. AssertContainsExactly(GetVariableDescriptions(entry, "c", 1), "str");
  1625. AssertContainsExactly(entry.GetValues("x", 1).Select(v => v.Description.Substring(0, 5)), "tuple");
  1626. AssertContainsExactly(entry.GetValues("y", 1).Select(v => v.Description.Substring(0, 4)), "list");
  1627. AssertContainsExactly(GetVariableDescriptions(entry, "z", 1), "int");
  1628. AssertContainsExactly(GetVariableDescriptions(entry, "min", 1), "built-in function min");
  1629. AssertContainsExactly(GetVariableDescriptions(entry, "list.append", 1), "built-in method append");
  1630. AssertContainsExactly(GetVariableDescriptions(entry, "System.String.Length", 1), "property of type <type 'int'>");
  1631. AssertContainsExactly(GetVariableDescriptions(entry, "\"abc\".Length", 1), "int");
  1632. AssertContainsExactly(GetVariableDescriptions(entry, "c.Length", 1), "int");
  1633. AssertContainsExactly(GetVariableDescriptions(entry, "System.Environment.CurrentDirectory", 1), "str");
  1634. AssertContainsExactly(GetVariableDescriptions(entry, "d", 1), "foo instance");
  1635. AssertContainsExactly(GetVariableDescriptions(entry, "e", 1), "ArrayList");
  1636. AssertContainsExactly(GetVariableDescriptions(entry, "ArrayList", 1), "type ArrayList");
  1637. AssertContainsExactly(GetVariableDescriptions(entry, "e.Count", 1), "int");
  1638. AssertContainsExactly(GetVariableDescriptions(entry, "sys", 1), "built-in module sys");
  1639. AssertContainsExactly(GetVariableDescriptions(entry, "f", 1), "def f(...)");
  1640. AssertContainsExactly(GetVariableDescriptions(entry, "foo.f", 1), "def f(...)");
  1641. AssertContainsExactly(GetVariableDescriptions(entry, "foo().g", 1), "method g of foo objects ");
  1642. AssertContainsExactly(GetVariableDescriptions(entry, "foo", 1), "class foo");
  1643. AssertContainsExactly(GetVariableDescriptions(entry, "System.DBNull.Value", 1), "DBNull");
  1644. AssertContainsExactly(GetVariableDescriptions(entry, "System.StringSplitOptions", 1), "type StringSplitOptions");
  1645. //AssertContainsExactly(GetVariableDescriptions(entry, "System.StringSplitOptions.RemoveEmptyEntries", 0), "field of type StringSplitOptions");
  1646. AssertContainsExactly(GetVariableDescriptions(entry, "g", 1), "def g(...)"); // return info could be better
  1647. AssertContainsExactly(GetVariableDescriptions(entry, "System.AppDomain.DomainUnload", 1), "event of type System.EventHandler");
  1648. AssertContainsExactly(GetVariableDescriptions(entry, "None", 1), "None");
  1649. }
  1650. [TestMethod]
  1651. public void TestRecurisveDataStructures() {
  1652. var text = @"
  1653. d = {}
  1654. d[0] = d
  1655. ";
  1656. var entry = ProcessText(text);
  1657. AssertContainsExactly(GetVariableDescriptions(entry, "d", 1), "dict({int : dict}");
  1658. }
  1659. /// <summary>
  1660. /// Variable is refered to in the base class, defined in the derived class, we should know the type information.
  1661. /// </summary>
  1662. [TestMethod]
  1663. public void TestBaseReferencedDerivedDefined() {
  1664. var text = @"
  1665. class Base(object):
  1666. def f(self):
  1667. x = self.map
  1668. class Derived(Base):
  1669. def __init__(self):
  1670. self.map = {}
  1671. pass
  1672. ";
  1673. var entry = ProcessText(text);
  1674. var members = entry.GetMembers("Derived().", GetLineNumber(text, "pass")).ToArray();
  1675. var map = members.First(x => x.Name == "map");
  1676. Assert.AreEqual(map.MemberType, ResultType.Field);
  1677. }
  1678. #endregion
  1679. #region Helpers
  1680. static AnalysisTest() {
  1681. _engine = Python.CreateEngine();
  1682. PyObjectType = ClrModule.GetPythonType(typeof(object));
  1683. IntType = ClrModule.GetPythonType(typeof(int));
  1684. ComplexType = ClrModule.GetPythonType(typeof(Complex));
  1685. StringType = ClrModule.GetPythonType(typeof(string));
  1686. FloatType = ClrModule.GetPythonType(typeof(double));
  1687. TypeType = ClrModule.GetPythonType(typeof(PythonType));
  1688. ListType = ClrModule.GetPythonType(typeof(List));
  1689. TupleType = ClrModule.GetPythonType(typeof(PythonTuple));
  1690. BoolType = ClrModule.GetPythonType(typeof(bool));
  1691. FunctionType = ClrModule.GetPythonType(typeof(PythonFunction));
  1692. GeneratorType = ClrModule.GetPythonType(typeof(PythonGenerator));
  1693. _objectMembers = GetMembers(PyObjectType, false);
  1694. _strMembers = GetMembers(StringType, false);
  1695. _listMembers = GetMembers(ListType, false);
  1696. _intMembers = GetMembers(IntType, false);
  1697. _functionMembers = GetMembers(FunctionType, false);
  1698. _objectMembersClr = GetMembers(PyObjectType, true);
  1699. _strMembersClr = GetMembers(StringType, true);
  1700. Assert.IsTrue(_objectMembers.Length < _objectMembersClr.Length);
  1701. Assert.IsTrue(_strMembers.Length < _strMembersClr.Length);
  1702. }
  1703. private static string[] GetMembers(object obj, bool showClr) {
  1704. var dir = showClr ? ClrModule.DirClr(obj) : ClrModule.Dir(obj);
  1705. int len = dir.__len__();
  1706. string[] result = new string[len];
  1707. for (int i = 0; i < len; i++) {
  1708. Assert.IsTrue(dir[i] is string);
  1709. result[i] = dir[i] as string;
  1710. }
  1711. return result;
  1712. }
  1713. private static SourceUnit GetSourceUnit(string text, string name) {
  1714. var textContent = new MyTextContentProvider(text);
  1715. var languageContext = HostingHelpers.GetLanguageContext(_engine);
  1716. return new SourceUnit(languageContext, textContent, name, SourceCodeKind.File);
  1717. }
  1718. private static SourceUnit GetSourceUnit(string text) {
  1719. return GetSourceUnit(text, "foo");
  1720. }
  1721. private static ModuleAnalysis ProcessText(string text) {
  1722. var sourceUnit = GetSourceUnit(text, "foo");
  1723. return ParseText(new ProjectState(_engine), sourceUnit, "foo").Analysis;
  1724. }
  1725. /// <summary>
  1726. /// Returns all the permutations of the set [0 ... n-1]
  1727. /// </summary>
  1728. /// <param name="n"></param>
  1729. /// <returns></returns>
  1730. private static IEnumerable<List<int>> Permutations(int n) {
  1731. if (n <= 0) {
  1732. yield return new List<int>();
  1733. } else {
  1734. foreach (var prev in Permutations(n - 1)) {
  1735. for (int i = n - 1; i >= 0; i--) {
  1736. var result = new List<int>(prev);
  1737. result.Insert(i, n - 1);
  1738. yield return result;
  1739. }
  1740. }
  1741. }
  1742. }
  1743. private IEnumerable<ProjectEntry[]> MakeModulePermutations(string prefix, string[] code) {
  1744. foreach (var p in Permutations(code.Length)) {
  1745. var result = new ProjectEntry[code.Length];
  1746. var state = new ProjectState(_engine);
  1747. for (int i = 0; i < code.Length; i++) {
  1748. result[p[i]] = state.AddModule(prefix + (p[i] + 1).ToString(), "foo", null);
  1749. }
  1750. for (int i = 0; i < code.Length; i++) {
  1751. Prepare(result[p[i]], GetSourceUnit(code[p[i]]));
  1752. }
  1753. for (int i = 0; i < code.Length; i++) {
  1754. result[p[i]].Analyze();
  1755. }
  1756. yield return result;
  1757. }
  1758. }
  1759. /// <summary>
  1760. /// For a given set of module definitions, build analysis info for each unique permutation
  1761. /// of the ordering of the defintions and run the test against each analysis.
  1762. /// </summary>
  1763. /// <param name="prefix">Prefix for the module names. The first source text will become prefix + "1", etc.</param>
  1764. /// <param name="code">The source code for each of the modules</param>
  1765. /// <param name="test">The test to run against the analysis</param>
  1766. private void PermutedTest(string prefix, string[] code, Action<ProjectEntry[]> test) {
  1767. foreach (var pe in MakeModulePermutations(prefix, code)) {
  1768. test(pe);
  1769. }
  1770. }
  1771. private string MakeText<T>(IEnumerable<T> values) {
  1772. var sb = new StringBuilder("{");
  1773. foreach (var value in values) {
  1774. if (sb.Length > 1) {
  1775. sb.Append(", ");
  1776. }
  1777. if (value is PythonType) {
  1778. sb.AppendFormat("Type({0})", PythonType.Get__name__((PythonType)(object)value));
  1779. } else {
  1780. sb.Append(value.ToString());
  1781. }
  1782. }
  1783. sb.Append("}");
  1784. return sb.ToString();
  1785. }
  1786. private void AssertContains<T>(IEnumerable<T> source, T value) {
  1787. foreach (var v in source) {
  1788. if (v.Equals(value)) {
  1789. return;
  1790. }
  1791. }
  1792. Assert.Fail(String.Format("{0} does not contain {1}", MakeText(source), value));
  1793. }
  1794. private void AssertDoesntContain<T>(IEnumerable<T> source, T value) {
  1795. foreach (var v in source) {
  1796. if (v.Equals(value)) {
  1797. Assert.Fail(String.Format("{0} does not contain {1}", MakeText(source), value));
  1798. }
  1799. }
  1800. }
  1801. private void AssertContainsExactly<T>(IEnumerable<T> source, params T[] values) {
  1802. AssertContainsExactly(new HashSet<T>(source), values);
  1803. }
  1804. private void AssertContainsExactly<T>(HashSet<T> set, params T[] values) {
  1805. if (set.ContainsExactly(values)) {
  1806. return;
  1807. }
  1808. Assert.Fail(String.Format("Expected {0}, got {1}", MakeText(values), MakeText(set)));
  1809. }
  1810. private static string[] GetUnion(params object[] objs) {
  1811. var result = new HashSet<string>();
  1812. foreach (var obj in objs) {
  1813. if (obj is string) {
  1814. result.Add((string)obj);
  1815. } else if (obj is IEnumerable<string>) {
  1816. result.UnionWith((IEnumerable<string>)obj);
  1817. } else {
  1818. throw new NotImplementedException("Non-string member");
  1819. }
  1820. }
  1821. return result.ToArray();
  1822. }
  1823. private static string[] GetIntersection(IEnumerable<string> first, params IEnumerable<string>[] remaining) {
  1824. var result = new HashSet<string>(first);
  1825. foreach (var obj in remaining) {
  1826. result.IntersectWith((IEnumerable<string>)obj);
  1827. }
  1828. return result.ToArray();
  1829. }
  1830. #endregion
  1831. }
  1832. }