Browse Source

Add InvocationResolveResult.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
e51e3a95cb
  1. 14
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs
  2. 32
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs
  3. 24
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs
  4. 8
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs
  5. 37
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs
  6. 3
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs
  7. 12
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs
  8. 2
      ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs
  9. 21
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
  10. 83
      ICSharpCode.NRefactory/CSharp/Resolver/InvocationResolveResult.cs
  11. 9
      ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs
  12. 10
      ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs
  13. 22
      ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs
  14. 43
      ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs
  15. 12
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  16. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

14
ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs

@ -40,18 +40,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public void AttributeConstructor1() public void AttributeConstructor1()
{ {
string program = "using System; [$LoaderOptimization(3)$] class Test { }"; string program = "using System; [$LoaderOptimization(3)$] class Test { }";
var mrr = Resolve<MemberResolveResult>(program); var mrr = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName); Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName);
Assert.AreEqual("System.Byte", (mrr.Member as IMethod).Parameters[0].Type.Resolve(context).FullName); Assert.AreEqual("System.Byte", mrr.Member.Parameters[0].Type.Resolve(context).FullName);
} }
[Test] [Test]
public void AttributeConstructor2() public void AttributeConstructor2()
{ {
string program = "using System; [$LoaderOptimization(LoaderOptimization.NotSpecified)$] class Test { }"; string program = "using System; [$LoaderOptimization(LoaderOptimization.NotSpecified)$] class Test { }";
var mrr = Resolve<MemberResolveResult>(program); var mrr = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName); Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName);
Assert.AreEqual("System.LoaderOptimization", (mrr.Member as IMethod).Parameters[0].Type.Resolve(context).FullName); Assert.AreEqual("System.LoaderOptimization", mrr.Member.Parameters[0].Type.Resolve(context).FullName);
} }
[Test] [Test]
@ -59,7 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{ {
string program = "using System; [$Obsolete$] class Test {}"; string program = "using System; [$Obsolete$] class Test {}";
MemberResolveResult result = Resolve<MemberResolveResult>(program); var result = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("System.ObsoleteAttribute..ctor", result.Member.FullName); Assert.AreEqual("System.ObsoleteAttribute..ctor", result.Member.FullName);
} }
@ -71,7 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public const AttributeTargets XXX = AttributeTargets.All; public const AttributeTargets XXX = AttributeTargets.All;
} }
"; ";
MemberResolveResult result = Resolve<MemberResolveResult>(program); var result = Resolve<MemberResolveResult>(program);
Assert.AreEqual("MyAttribute.XXX", result.Member.FullName); Assert.AreEqual("MyAttribute.XXX", result.Member.FullName);
} }
@ -83,7 +83,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
enum E { A, B } enum E { A, B }
} }
"; ";
MemberResolveResult result = Resolve<MemberResolveResult>(program); var result = Resolve<MemberResolveResult>(program);
Assert.AreEqual("MyNamespace.E.A", result.Member.FullName); Assert.AreEqual("MyNamespace.E.A", result.Member.FullName);
} }

32
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs

@ -33,31 +33,31 @@ namespace XN {
} }
} }
"; ";
MemberResolveResult mrr; InvocationResolveResult mrr;
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$a.F(1)$")); mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$a.F(1)$"));
Assert.AreEqual("XN.XC.F", mrr.Member.FullName); Assert.AreEqual("XN.XC.F", mrr.Member.FullName);
Assert.AreEqual("System.Int32", ((IMethod)mrr.Member).Parameters[1].Type.Resolve(context).FullName); Assert.AreEqual("System.Int32", mrr.Member.Parameters[1].Type.Resolve(context).FullName);
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$a.F(\"text\")$")); mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$a.F(\"text\")$"));
Assert.AreEqual("XN.XC.F", mrr.Member.FullName); Assert.AreEqual("XN.XC.F", mrr.Member.FullName);
Assert.AreEqual("System.String", ((IMethod)mrr.Member).Parameters[1].Type.Resolve(context).FullName); Assert.AreEqual("System.String", mrr.Member.Parameters[1].Type.Resolve(context).FullName);
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$b.F(1)$")); mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$b.F(1)$"));
Assert.AreEqual("B.F", mrr.Member.FullName); Assert.AreEqual("B.F", mrr.Member.FullName);
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$b.F(\"text\")$")); mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$b.F(\"text\")$"));
Assert.AreEqual("XN.XC.F", mrr.Member.FullName); Assert.AreEqual("XN.XC.F", mrr.Member.FullName);
Assert.AreEqual("System.String", ((IMethod)mrr.Member).Parameters[1].Type.Resolve(context).FullName); Assert.AreEqual("System.String", mrr.Member.Parameters[1].Type.Resolve(context).FullName);
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$c.F(1)$")); mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$c.F(1)$"));
Assert.AreEqual("C.F", mrr.Member.FullName); Assert.AreEqual("C.F", mrr.Member.FullName);
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$c.F(\"text\")$")); mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$c.F(\"text\")$"));
Assert.AreEqual("C.F", mrr.Member.FullName); Assert.AreEqual("C.F", mrr.Member.FullName);
} }
[Test, Ignore("Anonymous methods not yet implemented")] [Test]
public void ExtensionMethodsTest2() public void ExtensionMethodsTest2()
{ {
string program = @"using System; using System.Collections.Generic; string program = @"using System; using System.Collections.Generic;
@ -72,18 +72,18 @@ public static class XC {
public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, Predicate<T> predicate) { throw new NotImplementedException(); } public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, Predicate<T> predicate) { throw new NotImplementedException(); }
} }
"; ";
MemberResolveResult mrr; InvocationResolveResult mrr;
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$\"text\".ToInt32()$")); mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$\"text\".ToInt32()$"));
Assert.AreEqual("XC.ToInt32", mrr.Member.FullName); Assert.AreEqual("XC.ToInt32", mrr.Member.FullName);
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$args.Slice(1, 2)$")); mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$args.Slice(1, 2)$"));
Assert.AreEqual("XC.Slice", mrr.Member.FullName); Assert.AreEqual("XC.Slice", mrr.Member.FullName);
Assert.AreEqual("System.String[]", mrr.Type.ReflectionName); Assert.AreEqual("System.String[]", mrr.Type.ReflectionName);
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$args.Filter(delegate { return true; })$")); mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$args.Filter(delegate { return true; })$"));
Assert.AreEqual("XC.Filter", mrr.Member.FullName); Assert.AreEqual("XC.Filter", mrr.Member.FullName);
Assert.AreEqual("System.Collections.Generic.IEnumerable{System.String}", mrr.Type.ReflectionName); Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", mrr.Type.ReflectionName);
} }
} }
} }

24
ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
} }
"; ";
MemberResolveResult result = Resolve<MemberResolveResult>(program); InvocationResolveResult result = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("A.TargetMethod", result.Member.FullName); Assert.AreEqual("A.TargetMethod", result.Member.FullName);
Assert.AreEqual("System.Int32", result.Type.ReflectionName); Assert.AreEqual("System.Int32", result.Type.ReflectionName);
} }
@ -66,7 +66,7 @@ class B : A {
} }
} }
"; ";
MemberResolveResult result = Resolve<MemberResolveResult>(program); InvocationResolveResult result = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("B.GetRandomNumber", result.Member.FullName); Assert.AreEqual("B.GetRandomNumber", result.Member.FullName);
} }
@ -87,7 +87,7 @@ class B : A {
} }
} }
"; ";
MemberResolveResult result = Resolve<MemberResolveResult>(program); InvocationResolveResult result = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("B.GetRandomNumber", result.Member.FullName); Assert.AreEqual("B.GetRandomNumber", result.Member.FullName);
} }
@ -104,7 +104,7 @@ class B : A {
} }
} }
"; ";
MemberResolveResult result = Resolve<MemberResolveResult>(program); InvocationResolveResult result = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("A.TargetMethod", result.Member.FullName); Assert.AreEqual("A.TargetMethod", result.Member.FullName);
Assert.AreEqual("System.Int32", result.Type.ReflectionName); Assert.AreEqual("System.Int32", result.Type.ReflectionName);
} }
@ -202,11 +202,11 @@ class Program {
static void T(ref int y) {} static void T(ref int y) {}
}"; }";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program, "T(a)"); InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program, "T(a)");
Assert.IsFalse(((IMethod)mrr.Member).Parameters[0].IsRef); Assert.IsFalse(mrr.Member.Parameters[0].IsRef);
mrr = Resolve<MemberResolveResult>(program, "T(ref a)"); mrr = Resolve<InvocationResolveResult>(program, "T(ref a)");
Assert.IsTrue(((IMethod)mrr.Member).Parameters[0].IsRef); Assert.IsTrue(mrr.Member.Parameters[0].IsRef);
} }
[Test, Ignore("Grouping by declaring type not yet implemented")] [Test, Ignore("Grouping by declaring type not yet implemented")]
@ -221,7 +221,7 @@ class Program {
class DerivedClass : BaseClass { class DerivedClass : BaseClass {
public void Test(object a) { } public void Test(object a) { }
}"; }";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program); InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
} }
@ -237,10 +237,10 @@ class DerivedClass : BaseClass {
class DerivedClass : BaseClass { class DerivedClass : BaseClass {
public void Test(string a) { } public void Test(string a) { }
}"; }";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program); InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); Assert.AreEqual("BaseClass.Test", mrr.Member.FullName);
mrr = Resolve<MemberResolveResult>(program.Replace("(3)", "(\"3\")")); mrr = Resolve<InvocationResolveResult>(program.Replace("(3)", "(\"3\")"));
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
} }
@ -261,7 +261,7 @@ class DerivedClass : MiddleClass {
public override void Test(int a) { } public override void Test(int a) { }
}"; }";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program); InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("MiddleClass.Test", mrr.Member.FullName); Assert.AreEqual("MiddleClass.Test", mrr.Member.FullName);
} }
} }

8
ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs

@ -408,7 +408,7 @@ class TestClass {
"; ";
TypeResolveResult trr = Resolve<TypeResolveResult>(program.Replace("COL a", "$COL$ a")); TypeResolveResult trr = Resolve<TypeResolveResult>(program.Replace("COL a", "$COL$ a"));
Assert.AreEqual("System.Collections.ArrayList", trr.Type.FullName, "COL"); Assert.AreEqual("System.Collections.ArrayList", trr.Type.FullName, "COL");
ResolveResult rr = Resolve<ResolveResult>(program.Replace("new COL()", "$new COL()$")); ResolveResult rr = Resolve<InvocationResolveResult>(program.Replace("new COL()", "$new COL()$"));
Assert.AreEqual("System.Collections.ArrayList", rr.Type.FullName, "a"); Assert.AreEqual("System.Collections.ArrayList", rr.Type.FullName, "a");
} }
@ -539,7 +539,7 @@ class TestClass {
trr = Resolve<TypeResolveResult>(program.Replace("$", "$global::XX.XX$")); trr = Resolve<TypeResolveResult>(program.Replace("$", "$global::XX.XX$"));
Assert.AreEqual("XX.XX", trr.Type.FullName); Assert.AreEqual("XX.XX", trr.Type.FullName);
MemberResolveResult mrr = Resolve<MemberResolveResult>(program.Replace("$", "$XX.Test()$")); InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$XX.Test()$"));
Assert.AreEqual("XX.XX.Test", mrr.Member.FullName); Assert.AreEqual("XX.XX.Test", mrr.Member.FullName);
} }
@ -651,7 +651,7 @@ namespace A {
class BaseClass { class BaseClass {
public static string Test() {} public static string Test() {}
}"; }";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program.Replace("$", "$BaseClass.Test()$")); MemberResolveResult mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$BaseClass.Test()$"));
Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); Assert.AreEqual("BaseClass.Test", mrr.Member.FullName);
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$Test$")); mrr = Resolve<MemberResolveResult>(program.Replace("$", "$Test$"));
@ -661,7 +661,7 @@ namespace A {
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
// returns BaseClass.Test because DerivedClass.Test is not invocable // returns BaseClass.Test because DerivedClass.Test is not invocable
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$DerivedClass.Test()$")); mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$DerivedClass.Test()$"));
Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); Assert.AreEqual("BaseClass.Test", mrr.Member.FullName);
} }

37
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs

@ -20,7 +20,7 @@ class A {
} }
} }
"; ";
MemberResolveResult result = Resolve<MemberResolveResult>(program); InvocationResolveResult result = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("System.Collections.Generic.List..ctor", result.Member.FullName); Assert.AreEqual("System.Collections.Generic.List..ctor", result.Member.FullName);
Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", result.Type.ReflectionName); Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", result.Type.ReflectionName);
@ -35,7 +35,7 @@ class A {
} }
} }
"; ";
ResolveResult result = Resolve<ResolveResult>(program); ResolveResult result = Resolve<ErrorResolveResult>(program);
Assert.AreSame(SharedTypes.UnknownType, result.Type); Assert.AreSame(SharedTypes.UnknownType, result.Type);
} }
@ -67,21 +67,18 @@ class A {
A(double dblVal) {} A(double dblVal) {}
} }
"; ";
MemberResolveResult result = Resolve<MemberResolveResult>(program.Replace("$", "$new A()$")); InvocationResolveResult result = Resolve<InvocationResolveResult>(program.Replace("$", "$new A()$"));
IMethod m = (IMethod)result.Member; Assert.IsFalse(result.Member.IsStatic, "new A() is static");
Assert.IsFalse(m.IsStatic, "new A() is static"); Assert.AreEqual(0, result.Member.Parameters.Count, "new A() parameter count");
Assert.AreEqual(0, m.Parameters.Count, "new A() parameter count");
Assert.AreEqual("A", result.Type.FullName); Assert.AreEqual("A", result.Type.FullName);
result = Resolve<MemberResolveResult>(program.Replace("$", "$new A(10)$")); result = Resolve<InvocationResolveResult>(program.Replace("$", "$new A(10)$"));
m = (IMethod)result.Member; Assert.AreEqual(1, result.Member.Parameters.Count, "new A(10) parameter count");
Assert.AreEqual(1, m.Parameters.Count, "new A(10) parameter count"); Assert.AreEqual("intVal", result.Member.Parameters[0].Name, "new A(10) parameter");
Assert.AreEqual("intVal", m.Parameters[0].Name, "new A(10) parameter");
result = Resolve<MemberResolveResult>(program.Replace("$", "$new A(11.1)$")); result = Resolve<InvocationResolveResult>(program.Replace("$", "$new A(11.1)$"));
m = (IMethod)result.Member; Assert.AreEqual(1, result.Member.Parameters.Count, "new A(11.1) parameter count");
Assert.AreEqual(1, m.Parameters.Count, "new A(11.1) parameter count"); Assert.AreEqual("dblVal", result.Member.Parameters[0].Name, "new A(11.1) parameter");
Assert.AreEqual("dblVal", m.Parameters[0].Name, "new A(11.1) parameter");
} }
[Test] [Test]
@ -93,11 +90,9 @@ class A {
} }
} }
"; ";
MemberResolveResult result = Resolve<MemberResolveResult>(program); InvocationResolveResult result = Resolve<InvocationResolveResult>(program);
IMethod m = (IMethod)result.Member;
Assert.IsNotNull(m);
Assert.AreEqual("A", result.Type.ReflectionName); Assert.AreEqual("A", result.Type.ReflectionName);
Assert.AreEqual(0, m.Parameters.Count); Assert.AreEqual(0, result.Member.Parameters.Count);
} }
[Test, Ignore("Parser returns incorrect positions")] [Test, Ignore("Parser returns incorrect positions")]
@ -122,13 +117,13 @@ class C : B {
{} {}
} }
"; ";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program, "base(b)"); InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program, "base(b)");
Assert.AreEqual("A..ctor", mrr.Member.FullName); Assert.AreEqual("A..ctor", mrr.Member.FullName);
mrr = Resolve<MemberResolveResult>(program, "base(c)"); mrr = Resolve<InvocationResolveResult>(program, "base(c)");
Assert.AreEqual("B..ctor", mrr.Member.FullName); Assert.AreEqual("B..ctor", mrr.Member.FullName);
mrr = Resolve<MemberResolveResult>(program, "this(0)"); mrr = Resolve<InvocationResolveResult>(program, "this(0)");
Assert.AreEqual("C..ctor", mrr.Member.FullName); Assert.AreEqual("C..ctor", mrr.Member.FullName);
} }
} }

3
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs

@ -171,7 +171,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
protected T Resolve<T>(string code) where T : ResolveResult protected T Resolve<T>(string code) where T : ResolveResult
{ {
ResolveResult rr = Resolve(code); ResolveResult rr = Resolve(code);
Assert.IsTrue(rr is T, "Resolve should be " + typeof(T).Name + ", but was " + (rr != null ? rr.GetType().Name : "null")); Assert.IsNotNull(rr);
Assert.IsTrue(rr.GetType() == typeof(T), "Resolve should be " + typeof(T).Name + ", but was " + rr.GetType().Name);
return (T)rr; return (T)rr;
} }

12
ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs

@ -86,7 +86,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ITypeDefinition declType = ctx.GetTypeDefinition(typeof(int)); ITypeDefinition declType = ctx.GetTypeDefinition(typeof(int));
var methods = declType.Methods.Where(m => m.Name == "Parse").ToList(); var methods = declType.Methods.Where(m => m.Name == "Parse").ToList();
var argument = new MethodGroupResolveResult(declType, "Parse", methods, new IType[0]); var argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "Parse", methods, new IType[0]);
bool success; bool success;
ti.InferTypeArguments(new [] { A, B }, new [] { argument }, ti.InferTypeArguments(new [] { A, B }, new [] { argument },
@ -105,7 +105,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ITypeDefinition declType = ctx.GetTypeDefinition(typeof(Console)); ITypeDefinition declType = ctx.GetTypeDefinition(typeof(Console));
var methods = declType.Methods.Where(m => m.Name == "ReadKey").ToList(); var methods = declType.Methods.Where(m => m.Name == "ReadKey").ToList();
var argument = new MethodGroupResolveResult(declType, "ReadKey", methods, new IType[0]); var argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "ReadKey", methods, new IType[0]);
bool success; bool success;
Assert.AreEqual( Assert.AreEqual(
@ -123,15 +123,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{ {
IType[] expectedParameterTypes; IType[] expectedParameterTypes;
IType inferredReturnType; IType inferredReturnType;
IParameter[] parameters;
public MockImplicitLambda(IType[] expectedParameterTypes, IType inferredReturnType) public MockImplicitLambda(IType[] expectedParameterTypes, IType inferredReturnType)
{ {
this.expectedParameterTypes = expectedParameterTypes; this.expectedParameterTypes = expectedParameterTypes;
this.inferredReturnType = inferredReturnType; this.inferredReturnType = inferredReturnType;
this.parameters = new IParameter[expectedParameterTypes.Length];
for (int i = 0; i < parameters.Length; i++) {
// UnknownType because this lambda is implicitly typed
parameters[i] = new DefaultParameter(SharedTypes.UnknownType, "X" + i);
}
} }
public override IList<IParameter> Parameters { public override IList<IParameter> Parameters {
get { throw new NotImplementedException(); } get { return parameters; }
} }
public override Conversion IsValid(IType[] parameterTypes, IType returnType, Conversions conversions) public override Conversion IsValid(IType[] parameterTypes, IType returnType, Conversions conversions)

2
ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs

@ -22,7 +22,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public class AmbiguousMemberResultResult : MemberResolveResult public class AmbiguousMemberResultResult : MemberResolveResult
{ {
public AmbiguousMemberResultResult(IMember member, IType returnType) : base(member, returnType) public AmbiguousMemberResultResult(ResolveResult targetResult, IMember member, IType returnType) : base(targetResult, member, returnType)
{ {
} }

21
ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs

@ -1555,6 +1555,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
} }
} }
// TODO: return implicit/explicit conversion being applied
return new ResolveResult(targetType); return new ResolveResult(targetType);
} }
@ -1651,7 +1652,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
MemberLookup lookup = new MemberLookup(context, t, t.ProjectContent); MemberLookup lookup = new MemberLookup(context, t, t.ProjectContent);
ResolveResult r; ResolveResult r;
if (lookupMode == SimpleNameLookupMode.Expression || lookupMode == SimpleNameLookupMode.InvocationTarget) { if (lookupMode == SimpleNameLookupMode.Expression || lookupMode == SimpleNameLookupMode.InvocationTarget) {
r = lookup.Lookup(t, identifier, typeArguments, lookupMode == SimpleNameLookupMode.InvocationTarget); r = lookup.Lookup(new TypeResolveResult(t), identifier, typeArguments, lookupMode == SimpleNameLookupMode.InvocationTarget);
} else { } else {
r = lookup.LookupType(t, identifier, typeArguments, parameterizeResultType); r = lookup.LookupType(t, identifier, typeArguments, parameterizeResultType);
} }
@ -1785,11 +1786,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return DynamicResult; return DynamicResult;
MemberLookup lookup = CreateMemberLookup(); MemberLookup lookup = CreateMemberLookup();
ResolveResult result = lookup.Lookup(target.Type, identifier, typeArguments, isInvocationTarget); ResolveResult result = lookup.Lookup(target, identifier, typeArguments, isInvocationTarget);
if (result is UnknownMemberResolveResult) { if (result is UnknownMemberResolveResult) {
var extensionMethods = GetExtensionMethods(target.Type, identifier, typeArguments.Count); var extensionMethods = GetExtensionMethods(target.Type, identifier, typeArguments.Count);
if (extensionMethods.Count > 0) { if (extensionMethods.Count > 0) {
return new MethodGroupResolveResult(target.Type, identifier, EmptyList<IMethod>.Instance, typeArguments) { return new MethodGroupResolveResult(target, identifier, EmptyList<IMethod>.Instance, typeArguments) {
extensionMethods = extensionMethods extensionMethods = extensionMethods
}; };
} }
@ -1842,6 +1843,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return extensionMethodGroups; return extensionMethodGroups;
} }
/// <summary>
/// Gets all extension methods available in the current using scope.
/// This list includes unaccessible
/// </summary>
List<List<IMethod>> GetAllExtensionMethods() List<List<IMethod>> GetAllExtensionMethods()
{ {
// TODO: maybe cache the result? // TODO: maybe cache the result?
@ -1873,7 +1878,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{ {
return return
from c in context.GetTypes(namespaceName, StringComparer.Ordinal) from c in context.GetTypes(namespaceName, StringComparer.Ordinal)
where c.IsStatic && c.HasExtensionMethods where c.IsStatic && c.HasExtensionMethods && c.TypeParameters.Count == 0
from m in c.Methods from m in c.Methods
where m.IsExtensionMethod where m.IsExtensionMethod
select m; select m;
@ -1894,9 +1899,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (mgrr != null) { if (mgrr != null) {
OverloadResolution or = mgrr.PerformOverloadResolution(context, arguments, argumentNames); OverloadResolution or = mgrr.PerformOverloadResolution(context, arguments, argumentNames);
if (or.BestCandidate != null) { if (or.BestCandidate != null) {
IType returnType = or.BestCandidate.ReturnType.Resolve(context); return new InvocationResolveResult(mgrr.TargetResult, or, context);
returnType = returnType.AcceptVisitor(new MethodTypeParameterSubstitution(or.InferredTypeArguments));
return new MemberResolveResult(or.BestCandidate, returnType);
} else { } else {
// No candidate found at all (not even an inapplicable one). // No candidate found at all (not even an inapplicable one).
// This can happen with empty method groups (as sometimes used with extension methods) // This can happen with empty method groups (as sometimes used with extension methods)
@ -2019,7 +2022,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
or.AddCandidate(p); or.AddCandidate(p);
} }
if (or.BestCandidate != null) { if (or.BestCandidate != null) {
return new MemberResolveResult(or.BestCandidate, or.BestCandidate.ReturnType.Resolve(context)); return new InvocationResolveResult(target, or, context);
} else { } else {
return ErrorResult; return ErrorResult;
} }
@ -2039,7 +2042,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
or.AddCandidate(ctor); or.AddCandidate(ctor);
} }
if (or.BestCandidate != null) { if (or.BestCandidate != null) {
return new MemberResolveResult(or.BestCandidate, type); return new InvocationResolveResult(new TypeResolveResult(type), or, context);
} else { } else {
return new ErrorResolveResult(type); return new ErrorResolveResult(type);
} }

83
ICSharpCode.NRefactory/CSharp/Resolver/InvocationResolveResult.cs

@ -0,0 +1,83 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the MIT license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// Represents the result of a method invocation.
/// </summary>
public class InvocationResolveResult : MemberResolveResult
{
public readonly OverloadResolutionErrors OverloadResolutionErrors;
public readonly IList<IType> TypeArguments;
public readonly IList<ResolveResult> Arguments;
public readonly IList<Conversion> ArgumentConversions;
/// <summary>
/// Gets whether this invocation is calling an extension method using extension method syntax.
/// </summary>
public readonly bool IsExtensionMethodInvocation;
/// <summary>
/// Gets whether a params-Array is being used in its expanded form.
/// </summary>
public readonly bool IsExpandedForm;
readonly IList<int> argumentToParameterMap;
public InvocationResolveResult(ResolveResult targetResult, OverloadResolution or, ITypeResolveContext context)
: base(
or.IsExtensionMethodInvocation ? new TypeResolveResult(or.BestCandidate.DeclaringType) : targetResult,
or.BestCandidate,
GetReturnType(or, context))
{
this.OverloadResolutionErrors = or.BestCandidateErrors;
this.TypeArguments = or.InferredTypeArguments;
this.Arguments = or.Arguments;
this.ArgumentConversions = or.ArgumentConversions;
this.IsExtensionMethodInvocation = or.IsExtensionMethodInvocation;
this.IsExpandedForm = or.BestCandidateIsExpandedForm;
this.argumentToParameterMap = or.GetArgumentToParameterMap();
}
static IType GetReturnType(OverloadResolution or, ITypeResolveContext context)
{
IType returnType;
if (or.BestCandidate.EntityType == EntityType.Constructor)
returnType = or.BestCandidate.DeclaringType;
else
returnType = or.BestCandidate.ReturnType.Resolve(context);
var typeArguments = or.InferredTypeArguments;
if (typeArguments.Count > 0)
return returnType.AcceptVisitor(new MethodTypeParameterSubstitution(typeArguments));
else
return returnType;
}
public override bool IsError {
get { return this.OverloadResolutionErrors != OverloadResolutionErrors.None; }
}
/// <summary>
/// Gets an array that maps argument indices to parameter indices.
/// For arguments that could not be mapped to any parameter, the value will be -1.
///
/// parameterIndex = ArgumentToParameterMap[argumentIndex]
/// </summary>
public IList<int> GetArgumentToParameterMap()
{
return argumentToParameterMap;
}
public new IParameterizedMember Member {
get { return (IParameterizedMember)base.Member; }
}
}
}

9
ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs

@ -162,8 +162,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <summary> /// <summary>
/// Performs a member lookup. /// Performs a member lookup.
/// </summary> /// </summary>
public ResolveResult Lookup(IType type, string name, IList<IType> typeArguments, bool isInvocation) public ResolveResult Lookup(ResolveResult targetResolveResult, string name, IList<IType> typeArguments, bool isInvocation)
{ {
IType type = targetResolveResult.Type;
int typeArgumentCount = typeArguments.Count; int typeArgumentCount = typeArguments.Count;
List<IType> types = new List<IType>(); List<IType> types = new List<IType>();
@ -259,10 +260,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return new UnknownMemberResolveResult(type, name, typeArguments); return new UnknownMemberResolveResult(type, name, typeArguments);
IMember firstNonMethod = members.FirstOrDefault(m => !(m is IMethod)); IMember firstNonMethod = members.FirstOrDefault(m => !(m is IMethod));
if (members.Count == 1 && firstNonMethod != null) if (members.Count == 1 && firstNonMethod != null)
return new MemberResolveResult(firstNonMethod, context); return new MemberResolveResult(targetResolveResult, firstNonMethod, context);
if (firstNonMethod == null) if (firstNonMethod == null)
return new MethodGroupResolveResult(type, name, members.ConvertAll(m => (IMethod)m), typeArguments); return new MethodGroupResolveResult(targetResolveResult, name, members.ConvertAll(m => (IMethod)m), typeArguments);
return new AmbiguousMemberResultResult(firstNonMethod, firstNonMethod.ReturnType.Resolve(context)); return new AmbiguousMemberResultResult(targetResolveResult, firstNonMethod, firstNonMethod.ReturnType.Resolve(context));
} }
static bool IsNonInterfaceType(ITypeDefinition def) static bool IsNonInterfaceType(ITypeDefinition def)

10
ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs

@ -14,25 +14,29 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
readonly IMember member; readonly IMember member;
readonly bool isConstant; readonly bool isConstant;
readonly object constantValue; readonly object constantValue;
readonly ResolveResult targetResult;
public MemberResolveResult(IMember member, IType returnType) : base(returnType) public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType) : base(returnType)
{ {
if (member == null) if (member == null)
throw new ArgumentNullException("member"); throw new ArgumentNullException("member");
this.targetResult = targetResult;
this.member = member; this.member = member;
} }
public MemberResolveResult(IMember member, IType returnType, object constantValue) : base(returnType) public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType, object constantValue) : base(returnType)
{ {
if (member == null) if (member == null)
throw new ArgumentNullException("member"); throw new ArgumentNullException("member");
this.targetResult = targetResult;
this.member = member; this.member = member;
this.isConstant = true; this.isConstant = true;
this.constantValue = constantValue; this.constantValue = constantValue;
} }
public MemberResolveResult(IMember member, ITypeResolveContext context) : base(member.ReturnType.Resolve(context)) public MemberResolveResult(ResolveResult targetResult, IMember member, ITypeResolveContext context) : base(member.ReturnType.Resolve(context))
{ {
this.targetResult = targetResult;
this.member = member; this.member = member;
IField field = member as IField; IField field = member as IField;
if (field != null) { if (field != null) {

22
ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs

@ -17,26 +17,33 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{ {
readonly ReadOnlyCollection<IMethod> methods; readonly ReadOnlyCollection<IMethod> methods;
readonly ReadOnlyCollection<IType> typeArguments; readonly ReadOnlyCollection<IType> typeArguments;
readonly IType targetType; readonly ResolveResult targetResult;
readonly string methodName; readonly string methodName;
public MethodGroupResolveResult(IType targetType, string methodName, IList<IMethod> methods, IList<IType> typeArguments) : base(SharedTypes.UnknownType) public MethodGroupResolveResult(ResolveResult targetResult, string methodName, IList<IMethod> methods, IList<IType> typeArguments) : base(SharedTypes.UnknownType)
{ {
if (targetType == null) if (targetResult == null)
throw new ArgumentNullException("targetType"); throw new ArgumentNullException("targetResult");
if (methods == null) if (methods == null)
throw new ArgumentNullException("methods"); throw new ArgumentNullException("methods");
this.targetType = targetType; this.targetResult = targetResult;
this.methodName = methodName; this.methodName = methodName;
this.methods = new ReadOnlyCollection<IMethod>(methods); this.methods = new ReadOnlyCollection<IMethod>(methods);
this.typeArguments = typeArguments != null ? new ReadOnlyCollection<IType>(typeArguments) : EmptyList<IType>.Instance; this.typeArguments = typeArguments != null ? new ReadOnlyCollection<IType>(typeArguments) : EmptyList<IType>.Instance;
} }
/// <summary>
/// Gets the resolve result for the target object.
/// </summary>
public ResolveResult TargetResult {
get { return targetResult; }
}
/// <summary> /// <summary>
/// Gets the type of the reference to the target object. /// Gets the type of the reference to the target object.
/// </summary> /// </summary>
public IType TargetType { public IType TargetType {
get { return targetType; } get { return targetResult.Type; }
} }
/// <summary> /// <summary>
@ -81,7 +88,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
UsingScope oldUsingScope = resolver.UsingScope; UsingScope oldUsingScope = resolver.UsingScope;
try { try {
resolver.UsingScope = usingScope; resolver.UsingScope = usingScope;
extensionMethods = resolver.GetExtensionMethods(targetType, methodName, typeArguments.Count); extensionMethods = resolver.GetExtensionMethods(this.TargetType, methodName, typeArguments.Count);
} finally { } finally {
resolver.UsingScope = oldUsingScope; resolver.UsingScope = oldUsingScope;
resolver = null; resolver = null;
@ -121,6 +128,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
var extOr = new OverloadResolution(context, extArguments, extArgumentNames, typeArgumentArray); var extOr = new OverloadResolution(context, extArguments, extArgumentNames, typeArgumentArray);
extOr.AllowExpandingParams = allowExpandingParams; extOr.AllowExpandingParams = allowExpandingParams;
extOr.IsExtensionMethodInvocation = true;
foreach (var g in extensionMethods) { foreach (var g in extensionMethods) {
foreach (var m in g) { foreach (var m in g) {

43
ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs

@ -114,12 +114,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
#endregion #endregion
/// <summary>
/// Gets/Sets whether the methods are extension methods that are being called using extension method syntax.
/// </summary>
/// <remarks>
/// Setting this property to true restricts the possible conversions on the first argument to
/// implicit identity, reference, or boxing conversions.
/// </remarks>
public bool IsExtensionMethodInvocation { get; set; }
/// <summary> /// <summary>
/// Gets/Sets whether expanding 'params' into individual elements is allowed. /// Gets/Sets whether expanding 'params' into individual elements is allowed.
/// The default value is true. /// The default value is true.
/// </summary> /// </summary>
public bool AllowExpandingParams { get; set; } public bool AllowExpandingParams { get; set; }
/// <summary>
/// Gets the arguments for which this OverloadResolution instance was created.
/// </summary>
public IList<ResolveResult> Arguments {
get { return arguments; }
}
#region AddCandidate #region AddCandidate
public OverloadResolutionErrors AddCandidate(IParameterizedMember member) public OverloadResolutionErrors AddCandidate(IParameterizedMember member)
{ {
@ -348,10 +364,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (candidate.Parameters[parameterIndex].IsOut || candidate.Parameters[parameterIndex].IsRef) if (candidate.Parameters[parameterIndex].IsOut || candidate.Parameters[parameterIndex].IsRef)
candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch);
} }
Conversion c = conversions.ImplicitConversion(arguments[i], candidate.ParameterTypes[parameterIndex]); IType parameterType = candidate.ParameterTypes[parameterIndex];
Conversion c = conversions.ImplicitConversion(arguments[i], parameterType);
candidate.ArgumentConversions[i] = c; candidate.ArgumentConversions[i] = c;
if (!c) if (IsExtensionMethodInvocation && parameterIndex == 0) {
candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch); // First parameter to extension method must be an identity, reference or boxing conversion
if (!(c == Conversion.IdentityConversion || c == Conversion.ImplicitReferenceConversion || c == Conversion.BoxingConversion))
candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch);
} else {
if (!c)
candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch);
}
} }
} }
#endregion #endregion
@ -576,5 +599,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return new Conversion[arguments.Length]; return new Conversion[arguments.Length];
} }
} }
/// <summary>
/// Gets an array that maps argument indices to parameter indices.
/// For arguments that could not be mapped to any parameter, the value will be -1.
///
/// parameterIndex = GetArgumentToParameterMap()[argumentIndex]
/// </summary>
public IList<int> GetArgumentToParameterMap()
{
if (bestCandidate != null)
return bestCandidate.ArgumentToParameterMap;
else
return null;
}
} }
} }

12
ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs

@ -332,7 +332,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (resolverEnabled) { if (resolverEnabled) {
if (variableInitializer.Parent is FieldDeclaration) { if (variableInitializer.Parent is FieldDeclaration) {
if (resolver.CurrentMember != null) if (resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); return new MemberResolveResult(null, resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context));
} else { } else {
string identifier = variableInitializer.Name; string identifier = variableInitializer.Name;
foreach (IVariable v in resolver.LocalVariables) { foreach (IVariable v in resolver.LocalVariables) {
@ -353,7 +353,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ScanChildren(fixedVariableInitializer); ScanChildren(fixedVariableInitializer);
if (resolverEnabled) { if (resolverEnabled) {
if (resolver.CurrentMember != null) if (resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); return new MemberResolveResult(null, resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context));
else else
return errorResult; return errorResult;
} else { } else {
@ -371,7 +371,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ScanChildren(member); ScanChildren(member);
if (resolverEnabled && resolver.CurrentMember != null) if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.Context); return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context);
else else
return errorResult; return errorResult;
} finally { } finally {
@ -418,7 +418,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
} }
if (resolverEnabled && resolver.CurrentMember != null) if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.Context); return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context);
else else
return errorResult; return errorResult;
} finally { } finally {
@ -453,7 +453,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
if (resolverEnabled && resolver.CurrentMember != null) if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.Context); return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context);
else else
return errorResult; return errorResult;
} finally { } finally {
@ -522,7 +522,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ScanChildren(enumMemberDeclaration); ScanChildren(enumMemberDeclaration);
if (resolverEnabled && resolver.CurrentMember != null) if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.Context); return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context);
else else
return errorResult; return errorResult;
} finally { } finally {

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -104,6 +104,7 @@
<Compile Include="CSharp\Refactoring\TypeSystemAstBuilder.cs" /> <Compile Include="CSharp\Refactoring\TypeSystemAstBuilder.cs" />
<Compile Include="CSharp\Resolver\CSharpAttribute.cs" /> <Compile Include="CSharp\Resolver\CSharpAttribute.cs" />
<Compile Include="CSharp\Resolver\ConstantValues.cs" /> <Compile Include="CSharp\Resolver\ConstantValues.cs" />
<Compile Include="CSharp\Resolver\InvocationResolveResult.cs" />
<Compile Include="CSharp\Resolver\LambdaResolveResult.cs" /> <Compile Include="CSharp\Resolver\LambdaResolveResult.cs" />
<Compile Include="CSharp\Resolver\MapTypeIntoNewContext.cs" /> <Compile Include="CSharp\Resolver\MapTypeIntoNewContext.cs" />
<Compile Include="CSharp\Resolver\SimpleNameLookupMode.cs" /> <Compile Include="CSharp\Resolver\SimpleNameLookupMode.cs" />

Loading…
Cancel
Save