|
|
|
@ -10,6 +10,7 @@ using System.Collections; |
|
|
|
using System.Reflection; |
|
|
|
using System.Reflection; |
|
|
|
using NUnit.Framework; |
|
|
|
using NUnit.Framework; |
|
|
|
using ICSharpCode.Core; |
|
|
|
using ICSharpCode.Core; |
|
|
|
|
|
|
|
using ICSharpCode.SharpDevelop; |
|
|
|
using ICSharpCode.SharpDevelop.Dom; |
|
|
|
using ICSharpCode.SharpDevelop.Dom; |
|
|
|
using ICSharpCode.SharpDevelop.Project; |
|
|
|
using ICSharpCode.SharpDevelop.Project; |
|
|
|
using Grunwald.BooBinding.CodeCompletion; |
|
|
|
using Grunwald.BooBinding.CodeCompletion; |
|
|
|
@ -19,434 +20,434 @@ namespace Grunwald.BooBinding.Tests |
|
|
|
[TestFixture] |
|
|
|
[TestFixture] |
|
|
|
public class ResolverTests |
|
|
|
public class ResolverTests |
|
|
|
{ |
|
|
|
{ |
|
|
|
// #region Helper
|
|
|
|
#region Helper
|
|
|
|
// T Resolve<T>(string code) where T : ResolveResult
|
|
|
|
T Resolve<T>(string code) where T : ResolveResult |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// return Resolve<T>(code, "/*1*/");
|
|
|
|
return Resolve<T>(code, "/*1*/"); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// T Resolve<T>(string code, string marker) where T : ResolveResult
|
|
|
|
T Resolve<T>(string code, string marker) where T : ResolveResult |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// return Resolve<T>(normalProg, code, marker);
|
|
|
|
return Resolve<T>(normalProg, code, marker); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// T Resolve<T>(string prog, string code, string marker) where T : ResolveResult
|
|
|
|
T Resolve<T>(string prog, string code, string marker) where T : ResolveResult |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// ResolveResult rr = Resolve(prog, new ExpressionResult(code), marker);
|
|
|
|
ResolveResult rr = Resolve(prog, new ExpressionResult(code), marker); |
|
|
|
// Assert.IsNotNull(rr, "Resolve must not return null");
|
|
|
|
Assert.IsNotNull(rr, "Resolve must not return null"); |
|
|
|
// Assert.IsInstanceOfType(typeof(T), rr, "Resolve must return instance of type " + typeof(T).Name);
|
|
|
|
Assert.IsInstanceOfType(typeof(T), rr, "Resolve must return instance of type " + typeof(T).Name); |
|
|
|
// return (T)rr;
|
|
|
|
return (T)rr; |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// IProjectContent booLangPC;
|
|
|
|
IProjectContent booLangPC; |
|
|
|
//
|
|
|
|
|
|
|
|
// public ResolverTests() {
|
|
|
|
public ResolverTests() { |
|
|
|
// booLangPC = new ReflectionProjectContent(Assembly.Load("Boo.Lang"), "Boo.Lang.dll");
|
|
|
|
booLangPC = new ReflectionProjectContent(Assembly.Load("Boo.Lang"), "Boo.Lang.dll", ParserService.DefaultProjectContentRegistry); |
|
|
|
// booLangPC.ReferencedContents.Add(ProjectContentRegistry.Mscorlib);
|
|
|
|
booLangPC.ReferencedContents.Add(ParserService.DefaultProjectContentRegistry.Mscorlib); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// const string fileName = "tempFile.boo";
|
|
|
|
const string fileName = "tempFile.boo"; |
|
|
|
// DefaultProjectContent lastPC;
|
|
|
|
DefaultProjectContent lastPC; |
|
|
|
//
|
|
|
|
|
|
|
|
// void Register(string prog)
|
|
|
|
void Register(string prog) |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// DefaultProjectContent pc = new DefaultProjectContent();
|
|
|
|
DefaultProjectContent pc = new DefaultProjectContent(); |
|
|
|
// lastPC = pc;
|
|
|
|
lastPC = pc; |
|
|
|
// HostCallback.GetCurrentProjectContent = delegate { return pc; };
|
|
|
|
HostCallback.GetCurrentProjectContent = delegate { return pc; }; |
|
|
|
// pc.ReferencedContents.Add(ProjectContentRegistry.Mscorlib);
|
|
|
|
pc.ReferencedContents.Add(ParserService.DefaultProjectContentRegistry.Mscorlib); |
|
|
|
// pc.ReferencedContents.Add(ProjectContentRegistry.GetProjectContentForReference("System.Windows.Forms", "System.Windows.Forms"));
|
|
|
|
pc.ReferencedContents.Add(ParserService.DefaultProjectContentRegistry.GetProjectContentForReference("System.Windows.Forms", "System.Windows.Forms")); |
|
|
|
// pc.ReferencedContents.Add(booLangPC);
|
|
|
|
pc.ReferencedContents.Add(booLangPC); |
|
|
|
// ICompilationUnit cu = new BooParser().Parse(pc, fileName, prog);
|
|
|
|
ICompilationUnit cu = new BooParser().Parse(pc, fileName, prog); |
|
|
|
// ParserService.UpdateParseInformation(cu, fileName, false, false);
|
|
|
|
ParserService.UpdateParseInformation(cu, fileName, false, false); |
|
|
|
// cu.Classes.ForEach(pc.AddClassToNamespaceList);
|
|
|
|
cu.Classes.ForEach(pc.AddClassToNamespaceList); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// void GetPos(string prog, string marker, out int line, out int column)
|
|
|
|
void GetPos(string prog, string marker, out int line, out int column) |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// int index = prog.IndexOf(marker);
|
|
|
|
int index = prog.IndexOf(marker); |
|
|
|
// line = 1;
|
|
|
|
line = 1; |
|
|
|
// column = 0;
|
|
|
|
column = 0; |
|
|
|
// for (int i = 0; i < index; i++) {
|
|
|
|
for (int i = 0; i < index; i++) { |
|
|
|
// column++;
|
|
|
|
column++; |
|
|
|
// if (prog[i]=='\n') {
|
|
|
|
if (prog[i]=='\n') { |
|
|
|
// line++;
|
|
|
|
line++; |
|
|
|
// column = 0;
|
|
|
|
column = 0; |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// ResolveResult Resolve(string prog, ExpressionResult er, string marker)
|
|
|
|
ResolveResult Resolve(string prog, ExpressionResult er, string marker) |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// Register(prog);
|
|
|
|
Register(prog); |
|
|
|
// int line, column;
|
|
|
|
int line, column; |
|
|
|
// GetPos(prog, marker, out line, out column);
|
|
|
|
GetPos(prog, marker, out line, out column); |
|
|
|
//
|
|
|
|
|
|
|
|
// BooResolver r = new BooResolver();
|
|
|
|
BooResolver r = new BooResolver(); |
|
|
|
// return r.Resolve(er, line, column, fileName, prog);
|
|
|
|
return r.Resolve(er, line, column, fileName, prog); |
|
|
|
// }
|
|
|
|
} |
|
|
|
// #endregion
|
|
|
|
#endregion
|
|
|
|
//
|
|
|
|
|
|
|
|
// #region Basic tests
|
|
|
|
#region Basic tests
|
|
|
|
// const string normalProg =
|
|
|
|
const string normalProg = |
|
|
|
// "import System\n" +
|
|
|
|
"import System\n" + |
|
|
|
// "def MyMethod(arg as string):\n" +
|
|
|
|
"def MyMethod(arg as string):\n" + |
|
|
|
// "\tlocalVar = arg\n" +
|
|
|
|
"\tlocalVar = arg\n" + |
|
|
|
// "\t/*1*/\n" +
|
|
|
|
"\t/*1*/\n" + |
|
|
|
// "\tclosure = { e as string | arg.IndexOf(e) /*inClosure*/ }\n" +
|
|
|
|
"\tclosure = { e as string | arg.IndexOf(e) /*inClosure*/ }\n" + |
|
|
|
// "\tindex = closure('.')\n" +
|
|
|
|
"\tindex = closure('.')\n" + |
|
|
|
// "\t/*2*/\n" +
|
|
|
|
"\t/*2*/\n" + |
|
|
|
// "\tclosure2 = def(e as DateTime):\n" +
|
|
|
|
"\tclosure2 = def(e as DateTime):\n" + |
|
|
|
// "\t\treturn e.Year\n" +
|
|
|
|
"\t\treturn e.Year\n" + |
|
|
|
// "\trecursiveClosure = def(myObject):/*inRecursiveClosure*/\n" +
|
|
|
|
"\trecursiveClosure = def(myObject):/*inRecursiveClosure*/\n" + |
|
|
|
// "\t\treturn recursiveClosure(myObject)\n" +
|
|
|
|
"\t\treturn recursiveClosure(myObject)\n" + |
|
|
|
// "\t/*3*/\n";
|
|
|
|
"\t/*3*/\n"; |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void MethodParameter()
|
|
|
|
public void MethodParameter() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>("arg");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>("arg"); |
|
|
|
// Assert.IsTrue(rr.IsParameter);
|
|
|
|
Assert.IsTrue(rr.IsParameter); |
|
|
|
// Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void LocalVariable()
|
|
|
|
public void LocalVariable() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>("localVar");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>("localVar"); |
|
|
|
// Assert.IsFalse(rr.IsParameter);
|
|
|
|
Assert.IsFalse(rr.IsParameter); |
|
|
|
// Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void NullCoalescing()
|
|
|
|
public void NullCoalescing() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// ResolveResult rr = Resolve<ResolveResult>("localVar or arg");
|
|
|
|
ResolveResult rr = Resolve<ResolveResult>("localVar or arg"); |
|
|
|
// Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void InnerClassEnum()
|
|
|
|
public void InnerClassEnum() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// TypeResolveResult trr = Resolve<TypeResolveResult>("Environment.SpecialFolder");
|
|
|
|
TypeResolveResult trr = Resolve<TypeResolveResult>("Environment.SpecialFolder"); |
|
|
|
// Assert.AreEqual("System.Environment.SpecialFolder", trr.ResolvedClass.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Environment.SpecialFolder", trr.ResolvedClass.FullyQualifiedName); |
|
|
|
//
|
|
|
|
|
|
|
|
// MemberResolveResult mrr = Resolve<MemberResolveResult>("Environment.SpecialFolder.Desktop");
|
|
|
|
MemberResolveResult mrr = Resolve<MemberResolveResult>("Environment.SpecialFolder.Desktop"); |
|
|
|
// Assert.AreEqual("System.Environment.SpecialFolder.Desktop", mrr.ResolvedMember.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Environment.SpecialFolder.Desktop", mrr.ResolvedMember.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void ClosureParameter()
|
|
|
|
public void ClosureParameter() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>("e", "/*inClosure*/");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>("e", "/*inClosure*/"); |
|
|
|
// Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName); |
|
|
|
//
|
|
|
|
|
|
|
|
// Assert.IsNull(Resolve(normalProg, new ExpressionResult("e"), "/*1*/"));
|
|
|
|
Assert.IsNull(Resolve(normalProg, new ExpressionResult("e"), "/*1*/")); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void ClosureCall()
|
|
|
|
public void ClosureCall() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>("closure('.')", "/*2*/");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>("closure('.')", "/*2*/"); |
|
|
|
// Assert.IsFalse(rr.IsParameter);
|
|
|
|
Assert.IsFalse(rr.IsParameter); |
|
|
|
// Assert.AreEqual("closure", rr.Field.Name);
|
|
|
|
Assert.AreEqual("closure", rr.Field.Name); |
|
|
|
// Assert.AreEqual("System.Int32", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Int32", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void ClosureCall2()
|
|
|
|
public void ClosureCall2() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>("closure2(DateTime.Now)", "/*3*/");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>("closure2(DateTime.Now)", "/*3*/"); |
|
|
|
// Assert.IsFalse(rr.IsParameter);
|
|
|
|
Assert.IsFalse(rr.IsParameter); |
|
|
|
// Assert.AreEqual("closure2", rr.Field.Name);
|
|
|
|
Assert.AreEqual("closure2", rr.Field.Name); |
|
|
|
// Assert.AreEqual("System.Int32", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Int32", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void RecursiveClosure()
|
|
|
|
public void RecursiveClosure() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// // Code-completion cannot work here, test if SharpDevelop is correctly
|
|
|
|
// Code-completion cannot work here, test if SharpDevelop is correctly
|
|
|
|
// // preventing the StackOverflow.
|
|
|
|
// preventing the StackOverflow.
|
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>("recursiveClosure", "/*3*/");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>("recursiveClosure", "/*3*/"); |
|
|
|
// Assert.IsFalse(rr.IsParameter);
|
|
|
|
Assert.IsFalse(rr.IsParameter); |
|
|
|
// Assert.AreEqual("delegate(myObject:Object):?", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("delegate(myObject:Object):?", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void ClosureTypelessArgument()
|
|
|
|
public void ClosureTypelessArgument() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>("myObject", "/*inRecursiveClosure*/");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>("myObject", "/*inRecursiveClosure*/"); |
|
|
|
// Assert.AreEqual("System.Object", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Object", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void EqualityOperator()
|
|
|
|
public void EqualityOperator() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// ResolveResult rr = Resolve<ResolveResult>("0 == 0");
|
|
|
|
ResolveResult rr = Resolve<ResolveResult>("0 == 0"); |
|
|
|
// Assert.AreEqual("System.Boolean", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Boolean", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// rr = Resolve<ResolveResult>("0 != 1");
|
|
|
|
rr = Resolve<ResolveResult>("0 != 1"); |
|
|
|
// Assert.AreEqual("System.Boolean", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Boolean", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// rr = Resolve<ResolveResult>("null is null");
|
|
|
|
rr = Resolve<ResolveResult>("null is null"); |
|
|
|
// Assert.AreEqual("System.Boolean", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Boolean", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// rr = Resolve<ResolveResult>("object() is not null");
|
|
|
|
rr = Resolve<ResolveResult>("object() is not null"); |
|
|
|
// Assert.AreEqual("System.Boolean", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Boolean", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void ClassMethodAmbiguity()
|
|
|
|
public void ClassMethodAmbiguity() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// string prog =
|
|
|
|
string prog = |
|
|
|
// "class Test:\n" +
|
|
|
|
"class Test:\n" + |
|
|
|
// "\tdef constructor():\n" +
|
|
|
|
"\tdef constructor():\n" + |
|
|
|
// "\t\tpass\n" +
|
|
|
|
"\t\tpass\n" + |
|
|
|
// "class OtherClass:\n" +
|
|
|
|
"class OtherClass:\n" + |
|
|
|
// "\tdef Test():\n" +
|
|
|
|
"\tdef Test():\n" + |
|
|
|
// "\t\t/*mark*/\n" +
|
|
|
|
"\t\t/*mark*/\n" + |
|
|
|
// "\t\tpass\n";
|
|
|
|
"\t\tpass\n"; |
|
|
|
// MemberResolveResult rr = Resolve<MemberResolveResult>(prog, "Test()", "/*mark*/");
|
|
|
|
MemberResolveResult rr = Resolve<MemberResolveResult>(prog, "Test()", "/*mark*/"); |
|
|
|
// Assert.AreEqual("OtherClass.Test", rr.ResolvedMember.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("OtherClass.Test", rr.ResolvedMember.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
// #endregion
|
|
|
|
#endregion
|
|
|
|
//
|
|
|
|
|
|
|
|
// #region Regression
|
|
|
|
#region Regression
|
|
|
|
// const string regressionProg =
|
|
|
|
const string regressionProg = |
|
|
|
// "import System\n" +
|
|
|
|
"import System\n" + |
|
|
|
// "import System.Reflection\n" +
|
|
|
|
"import System.Reflection\n" + |
|
|
|
// "def MyMethod(arg as string):\n" +
|
|
|
|
"def MyMethod(arg as string):\n" + |
|
|
|
// "\tif true:\n" +
|
|
|
|
"\tif true:\n" + |
|
|
|
// "\t\tboo629 = 'hello'\n" +
|
|
|
|
"\t\tboo629 = 'hello'\n" + |
|
|
|
// "\tfor boo640a in [1, 2, 3]:\n" +
|
|
|
|
"\tfor boo640a in [1, 2, 3]:\n" + |
|
|
|
// "\t\tif boo640b = boo640a as FieldInfo: /*640*/\n" +
|
|
|
|
"\t\tif boo640b = boo640a as FieldInfo: /*640*/\n" + |
|
|
|
// "\t\t\tprint boo640b\n" +
|
|
|
|
"\t\t\tprint boo640b\n" + |
|
|
|
// "\t\n" +
|
|
|
|
"\t\n" + |
|
|
|
// "\tprint 'end of method'\n" +
|
|
|
|
"\tprint 'end of method'\n" + |
|
|
|
// "\t/*1*/\n";
|
|
|
|
"\t/*1*/\n"; |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void MyMethodCompletion()
|
|
|
|
public void MyMethodCompletion() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// MethodResolveResult rr = Resolve<MethodResolveResult>(regressionProg, "MyMethod", "/*1*/");
|
|
|
|
MethodResolveResult rr = Resolve<MethodResolveResult>(regressionProg, "MyMethod", "/*1*/"); |
|
|
|
// ArrayList arr = rr.GetCompletionData(lastPC);
|
|
|
|
ArrayList arr = rr.GetCompletionData(lastPC); |
|
|
|
// Assert.IsNotNull(arr);
|
|
|
|
Assert.IsNotNull(arr); |
|
|
|
// bool beginInvoke = false;
|
|
|
|
bool beginInvoke = false; |
|
|
|
// bool invoke = false;
|
|
|
|
bool invoke = false; |
|
|
|
// foreach (IMember m in arr) {
|
|
|
|
foreach (IMember m in arr) { |
|
|
|
// if (m.Name == "BeginInvoke") beginInvoke = true;
|
|
|
|
if (m.Name == "BeginInvoke") beginInvoke = true; |
|
|
|
// if (m.Name == "Invoke") invoke = true;
|
|
|
|
if (m.Name == "Invoke") invoke = true; |
|
|
|
// }
|
|
|
|
} |
|
|
|
// Assert.IsTrue(beginInvoke, "beginInvoke");
|
|
|
|
Assert.IsTrue(beginInvoke, "beginInvoke"); |
|
|
|
// Assert.IsTrue(invoke, "invoke");
|
|
|
|
Assert.IsTrue(invoke, "invoke"); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void Boo629VariableScope()
|
|
|
|
public void Boo629VariableScope() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>(regressionProg, "boo629", "/*1*/");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>(regressionProg, "boo629", "/*1*/"); |
|
|
|
// Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void Boo640ConditionalAssignment()
|
|
|
|
public void Boo640ConditionalAssignment() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>(regressionProg, "boo640b", "/*1*/");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>(regressionProg, "boo640b", "/*1*/"); |
|
|
|
// Assert.AreEqual("System.Reflection.FieldInfo", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Reflection.FieldInfo", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// rr = Resolve<LocalResolveResult>(regressionProg, "boo640a", "/*640*/");
|
|
|
|
rr = Resolve<LocalResolveResult>(regressionProg, "boo640a", "/*640*/"); |
|
|
|
// Assert.AreEqual("System.Object", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Object", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// Assert.IsNull(Resolve(regressionProg, new ExpressionResult("boo640a"), "/*1*/"));
|
|
|
|
Assert.IsNull(Resolve(regressionProg, new ExpressionResult("boo640a"), "/*1*/")); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void IndexerRecognition()
|
|
|
|
public void IndexerRecognition() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// string prog =
|
|
|
|
string prog = |
|
|
|
// "class Foo:\n" +
|
|
|
|
"class Foo:\n" + |
|
|
|
// "\tself[index as int]:\n" +
|
|
|
|
"\tself[index as int]:\n" + |
|
|
|
// "\t\tget:\n" +
|
|
|
|
"\t\tget:\n" + |
|
|
|
// "\t\t\treturn true\n" +
|
|
|
|
"\t\t\treturn true\n" + |
|
|
|
// "def example():\n" +
|
|
|
|
"def example():\n" + |
|
|
|
// "\tfoo = Foo()\n" +
|
|
|
|
"\tfoo = Foo()\n" + |
|
|
|
// "\tmybool = foo[1] /*mark*/\n" +
|
|
|
|
"\tmybool = foo[1] /*mark*/\n" + |
|
|
|
// "\tprint mybool\n";
|
|
|
|
"\tprint mybool\n"; |
|
|
|
// MemberResolveResult rr = Resolve<MemberResolveResult>(prog, "foo[1]", "/*mark*/");
|
|
|
|
MemberResolveResult rr = Resolve<MemberResolveResult>(prog, "foo[1]", "/*mark*/"); |
|
|
|
// Assert.IsTrue(((IProperty)rr.ResolvedMember).IsIndexer);
|
|
|
|
Assert.IsTrue(((IProperty)rr.ResolvedMember).IsIndexer); |
|
|
|
// Assert.AreEqual("System.Boolean", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Boolean", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// LocalResolveResult rr2 = Resolve<LocalResolveResult>(prog, "mybool", "/*mark*/");
|
|
|
|
LocalResolveResult rr2 = Resolve<LocalResolveResult>(prog, "mybool", "/*mark*/"); |
|
|
|
// Assert.AreEqual("System.Boolean", rr2.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Boolean", rr2.ResolvedType.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void InfiniteRecursionGenerator()
|
|
|
|
public void InfiniteRecursionGenerator() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// string prog =
|
|
|
|
string prog = |
|
|
|
// "class Test:\n" +
|
|
|
|
"class Test:\n" + |
|
|
|
// "\t_testList = []\n" +
|
|
|
|
"\t_testList = []\n" + |
|
|
|
// "\tTestProperty:\n" +
|
|
|
|
"\tTestProperty:\n" + |
|
|
|
// "\t\tget:\n" +
|
|
|
|
"\t\tget:\n" + |
|
|
|
// "\t\t\tfor testobj as Test in _testList:\n" +
|
|
|
|
"\t\t\tfor testobj as Test in _testList:\n" + |
|
|
|
// "\t\t\t\tyield testobj.TestProperty /*mark*/\n";
|
|
|
|
"\t\t\t\tyield testobj.TestProperty /*mark*/\n"; |
|
|
|
// MemberResolveResult rr = Resolve<MemberResolveResult>(prog, "testobj.TestProperty", "/*mark*/");
|
|
|
|
MemberResolveResult rr = Resolve<MemberResolveResult>(prog, "testobj.TestProperty", "/*mark*/"); |
|
|
|
// Assert.AreEqual("Test.TestProperty", rr.ResolvedMember.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("Test.TestProperty", rr.ResolvedMember.FullyQualifiedName); |
|
|
|
// Assert.AreEqual("System.Collections.Generic.IEnumerable", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("System.Collections.Generic.IEnumerable", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// // prevent creating self-referring ConstructedReturnType
|
|
|
|
// prevent creating self-referring ConstructedReturnType
|
|
|
|
// Assert.AreEqual("?", rr.ResolvedType.CastToConstructedReturnType().TypeArguments[0].FullyQualifiedName);
|
|
|
|
Assert.AreEqual("?", rr.ResolvedType.CastToConstructedReturnType().TypeArguments[0].FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
// #endregion
|
|
|
|
#endregion
|
|
|
|
//
|
|
|
|
|
|
|
|
// #region Nested Classes
|
|
|
|
#region Nested Classes
|
|
|
|
// const string nestedClassProg =
|
|
|
|
const string nestedClassProg = |
|
|
|
// "class Outer:\n" +
|
|
|
|
"class Outer:\n" + |
|
|
|
// "\tpublic static outerField = 1\n" +
|
|
|
|
"\tpublic static outerField = 1\n" + |
|
|
|
// "\tpublic class Inner:\n/*inner*/" +
|
|
|
|
"\tpublic class Inner:\n/*inner*/" + |
|
|
|
// "\t\tpublic innerField = 2\n" +
|
|
|
|
"\t\tpublic innerField = 2\n" + |
|
|
|
// "class Derived(Outer):\n/*derived*/" +
|
|
|
|
"class Derived(Outer):\n/*derived*/" + |
|
|
|
// "\tpublic static derivedField = 3\n" +
|
|
|
|
"\tpublic static derivedField = 3\n" + |
|
|
|
// "def Method():\n" +
|
|
|
|
"def Method():\n" + |
|
|
|
// "\ti as Outer.Inner\n" +
|
|
|
|
"\ti as Outer.Inner\n" + |
|
|
|
// "\ti2 as Derived.Inner\n" +
|
|
|
|
"\ti2 as Derived.Inner\n" + |
|
|
|
// "\t/*1*/";
|
|
|
|
"\t/*1*/"; |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void NestedClassTypeResolution()
|
|
|
|
public void NestedClassTypeResolution() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// TypeResolveResult trr;
|
|
|
|
TypeResolveResult trr; |
|
|
|
// trr = Resolve<TypeResolveResult>(nestedClassProg, "Outer.Inner", "/*1*/");
|
|
|
|
trr = Resolve<TypeResolveResult>(nestedClassProg, "Outer.Inner", "/*1*/"); |
|
|
|
// Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName); |
|
|
|
// trr = Resolve<TypeResolveResult>(nestedClassProg, "Inner", "/*inner*/");
|
|
|
|
trr = Resolve<TypeResolveResult>(nestedClassProg, "Inner", "/*inner*/"); |
|
|
|
// Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName); |
|
|
|
// trr = Resolve<TypeResolveResult>(nestedClassProg, "Inner", "/*derived*/");
|
|
|
|
trr = Resolve<TypeResolveResult>(nestedClassProg, "Inner", "/*derived*/"); |
|
|
|
// Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName); |
|
|
|
// trr = Resolve<TypeResolveResult>(nestedClassProg, "Derived.Inner", "/*1*/");
|
|
|
|
trr = Resolve<TypeResolveResult>(nestedClassProg, "Derived.Inner", "/*1*/"); |
|
|
|
// Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void NestedClassCtrlSpace()
|
|
|
|
public void NestedClassCtrlSpace() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// CtrlSpace(nestedClassProg.Replace("/*inner*/", "/*mark*/"), "outerField", "innerField", "Inner", "Outer", "Derived");
|
|
|
|
CtrlSpace(nestedClassProg.Replace("/*inner*/", "/*mark*/"), "outerField", "innerField", "Inner", "Outer", "Derived"); |
|
|
|
// CtrlSpace(nestedClassProg.Replace("/*derived*/", "/*mark*/"), "outerField", "derivedField", "Inner", "Outer", "Derived");
|
|
|
|
CtrlSpace(nestedClassProg.Replace("/*derived*/", "/*mark*/"), "outerField", "derivedField", "Inner", "Outer", "Derived"); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void NestedClassParentStaticField()
|
|
|
|
public void NestedClassParentStaticField() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// MemberResolveResult mrr = Resolve<MemberResolveResult>(nestedClassProg, "outerField", "/*inner*/");
|
|
|
|
MemberResolveResult mrr = Resolve<MemberResolveResult>(nestedClassProg, "outerField", "/*inner*/"); |
|
|
|
// Assert.AreEqual("Outer.outerField", mrr.ResolvedMember.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("Outer.outerField", mrr.ResolvedMember.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void NestedClassCC()
|
|
|
|
public void NestedClassCC() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>(nestedClassProg, "i", "/*1*/");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>(nestedClassProg, "i", "/*1*/"); |
|
|
|
// Assert.AreEqual("Outer.Inner", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("Outer.Inner", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// bool ok = false;
|
|
|
|
bool ok = false; |
|
|
|
// foreach (object o in rr.GetCompletionData(lastPC)) {
|
|
|
|
foreach (object o in rr.GetCompletionData(lastPC)) { |
|
|
|
// IMember m = o as IMember;
|
|
|
|
IMember m = o as IMember; |
|
|
|
// if (m != null && m.Name == "innerField")
|
|
|
|
if (m != null && m.Name == "innerField") |
|
|
|
// ok = true;
|
|
|
|
ok = true; |
|
|
|
// }
|
|
|
|
} |
|
|
|
// Assert.IsTrue(ok);
|
|
|
|
Assert.IsTrue(ok); |
|
|
|
// MemberResolveResult mrr = Resolve<MemberResolveResult>(nestedClassProg, "i.innerField", "/*1*/");
|
|
|
|
MemberResolveResult mrr = Resolve<MemberResolveResult>(nestedClassProg, "i.innerField", "/*1*/"); |
|
|
|
// Assert.AreEqual("Outer.Inner.innerField", mrr.ResolvedMember.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("Outer.Inner.innerField", mrr.ResolvedMember.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void NestedClassCC2()
|
|
|
|
public void NestedClassCC2() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// LocalResolveResult rr = Resolve<LocalResolveResult>(nestedClassProg, "i2", "/*1*/");
|
|
|
|
LocalResolveResult rr = Resolve<LocalResolveResult>(nestedClassProg, "i2", "/*1*/"); |
|
|
|
// Assert.AreEqual("Outer.Inner", rr.ResolvedType.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("Outer.Inner", rr.ResolvedType.FullyQualifiedName); |
|
|
|
// bool ok = false;
|
|
|
|
bool ok = false; |
|
|
|
// foreach (object o in rr.GetCompletionData(lastPC)) {
|
|
|
|
foreach (object o in rr.GetCompletionData(lastPC)) { |
|
|
|
// IMember m = o as IMember;
|
|
|
|
IMember m = o as IMember; |
|
|
|
// if (m != null && m.Name == "innerField")
|
|
|
|
if (m != null && m.Name == "innerField") |
|
|
|
// ok = true;
|
|
|
|
ok = true; |
|
|
|
// }
|
|
|
|
} |
|
|
|
// Assert.IsTrue(ok);
|
|
|
|
Assert.IsTrue(ok); |
|
|
|
// MemberResolveResult mrr = Resolve<MemberResolveResult>(nestedClassProg, "i2.innerField", "/*1*/");
|
|
|
|
MemberResolveResult mrr = Resolve<MemberResolveResult>(nestedClassProg, "i2.innerField", "/*1*/"); |
|
|
|
// Assert.AreEqual("Outer.Inner.innerField", mrr.ResolvedMember.FullyQualifiedName);
|
|
|
|
Assert.AreEqual("Outer.Inner.innerField", mrr.ResolvedMember.FullyQualifiedName); |
|
|
|
// }
|
|
|
|
} |
|
|
|
// #endregion
|
|
|
|
#endregion
|
|
|
|
//
|
|
|
|
|
|
|
|
// #region CtrlSpace
|
|
|
|
#region CtrlSpace
|
|
|
|
// void CtrlSpace(string prog, params string[] expected)
|
|
|
|
void CtrlSpace(string prog, params string[] expected) |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// CtrlSpace(new string[0], prog, expected);
|
|
|
|
CtrlSpace(new string[0], prog, expected); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// void CtrlSpace(string[] unExpected, string prog, params string[] expected)
|
|
|
|
void CtrlSpace(string[] unExpected, string prog, params string[] expected) |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// Register(prog);
|
|
|
|
Register(prog); |
|
|
|
// int line, column;
|
|
|
|
int line, column; |
|
|
|
// GetPos(prog, "/*mark*/", out line, out column);
|
|
|
|
GetPos(prog, "/*mark*/", out line, out column); |
|
|
|
// BooResolver r = new BooResolver();
|
|
|
|
BooResolver r = new BooResolver(); |
|
|
|
// System.Collections.ArrayList ar;
|
|
|
|
System.Collections.ArrayList ar; |
|
|
|
// ar = r.CtrlSpace(line, column, fileName, prog, ExpressionContext.Default);
|
|
|
|
ar = r.CtrlSpace(line, column, fileName, prog, ExpressionContext.Default); |
|
|
|
// foreach (string e in unExpected) {
|
|
|
|
foreach (string e in unExpected) { |
|
|
|
// foreach (object o in ar) {
|
|
|
|
foreach (object o in ar) { |
|
|
|
// if (e.Equals(o))
|
|
|
|
if (e.Equals(o)) |
|
|
|
// Assert.Fail("Didn't expect " + e);
|
|
|
|
Assert.Fail("Didn't expect " + e); |
|
|
|
// if (o is IMember && (o as IMember).Name == e) {
|
|
|
|
if (o is IMember && (o as IMember).Name == e) { |
|
|
|
// Assert.Fail("Didn't expect " + e);
|
|
|
|
Assert.Fail("Didn't expect " + e); |
|
|
|
// }
|
|
|
|
} |
|
|
|
// if (o is IClass && (o as IClass).Name == e) {
|
|
|
|
if (o is IClass && (o as IClass).Name == e) { |
|
|
|
// Assert.Fail("Didn't expect " + e);
|
|
|
|
Assert.Fail("Didn't expect " + e); |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
// foreach (string e in expected) {
|
|
|
|
foreach (string e in expected) { |
|
|
|
// bool ok = false;
|
|
|
|
bool ok = false; |
|
|
|
// foreach (object o in ar) {
|
|
|
|
foreach (object o in ar) { |
|
|
|
// if (e.Equals(o)) {
|
|
|
|
if (e.Equals(o)) { |
|
|
|
// if (ok) Assert.Fail("double entry " + e);
|
|
|
|
if (ok) Assert.Fail("double entry " + e); |
|
|
|
// ok = true;
|
|
|
|
ok = true; |
|
|
|
// }
|
|
|
|
} |
|
|
|
// if (o is IMember && (o as IMember).Name == e) {
|
|
|
|
if (o is IMember && (o as IMember).Name == e) { |
|
|
|
// if (ok) Assert.Fail("double entry " + e);
|
|
|
|
if (ok) Assert.Fail("double entry " + e); |
|
|
|
// ok = true;
|
|
|
|
ok = true; |
|
|
|
// }
|
|
|
|
} |
|
|
|
// if (o is IClass && (o as IClass).Name == e) {
|
|
|
|
if (o is IClass && (o as IClass).Name == e) { |
|
|
|
// if (ok) Assert.Fail("double entry " + e);
|
|
|
|
if (ok) Assert.Fail("double entry " + e); |
|
|
|
// ok = true;
|
|
|
|
ok = true; |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
// if (!ok)
|
|
|
|
if (!ok) |
|
|
|
// Assert.Fail("Expected " + e);
|
|
|
|
Assert.Fail("Expected " + e); |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void CtrlSpaceScopeExtension()
|
|
|
|
public void CtrlSpaceScopeExtension() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// string prog =
|
|
|
|
string prog = |
|
|
|
// "def Foo():\n" +
|
|
|
|
"def Foo():\n" + |
|
|
|
// "\tbar = def():\n" +
|
|
|
|
"\tbar = def():\n" + |
|
|
|
// "\t\tx = 0\n" +
|
|
|
|
"\t\tx = 0\n" + |
|
|
|
// "\t\t/*mark*/\n";
|
|
|
|
"\t\t/*mark*/\n"; |
|
|
|
// CtrlSpace(prog, "bar", "x");
|
|
|
|
CtrlSpace(prog, "bar", "x"); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void DoubleEntryTest()
|
|
|
|
public void DoubleEntryTest() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// string prog =
|
|
|
|
string prog = |
|
|
|
// "class MyClass:\n" +
|
|
|
|
"class MyClass:\n" + |
|
|
|
// "\t_myInt = 0\n" +
|
|
|
|
"\t_myInt = 0\n" + |
|
|
|
// "\tdef Foo():\n" +
|
|
|
|
"\tdef Foo():\n" + |
|
|
|
// "\t\t_myInt = 5\n" +
|
|
|
|
"\t\t_myInt = 5\n" + |
|
|
|
// "\t\t/*mark*/\n";
|
|
|
|
"\t\t/*mark*/\n"; |
|
|
|
// CtrlSpace(prog, "_myInt");
|
|
|
|
CtrlSpace(prog, "_myInt"); |
|
|
|
// }
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
// [Test]
|
|
|
|
[Test] |
|
|
|
// public void LoopInClosureTest()
|
|
|
|
public void LoopInClosureTest() |
|
|
|
// {
|
|
|
|
{ |
|
|
|
// string prog =
|
|
|
|
string prog = |
|
|
|
// "def Foo():\n" +
|
|
|
|
"def Foo():\n" + |
|
|
|
// "\tfor i in range(5):\n" +
|
|
|
|
"\tfor i in range(5):\n" + |
|
|
|
// "\t\tbar = def():\n" +
|
|
|
|
"\t\tbar = def():\n" + |
|
|
|
// "\t\t\tx = 0\n" +
|
|
|
|
"\t\t\tx = 0\n" + |
|
|
|
// "\t\t\t/*mark*/\n" +
|
|
|
|
"\t\t\t/*mark*/\n" + |
|
|
|
// "\t\t\tprint x";
|
|
|
|
"\t\t\tprint x"; |
|
|
|
// CtrlSpace(prog, "x", "bar", "i");
|
|
|
|
CtrlSpace(prog, "x", "bar", "i"); |
|
|
|
// }
|
|
|
|
} |
|
|
|
// #endregion
|
|
|
|
#endregion
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|