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

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

@ -33,31 +33,31 @@ namespace XN { @@ -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("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("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);
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("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);
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$c.F(\"text\")$"));
mrr = Resolve<InvocationResolveResult>(program.Replace("$", "$c.F(\"text\")$"));
Assert.AreEqual("C.F", mrr.Member.FullName);
}
[Test, Ignore("Anonymous methods not yet implemented")]
[Test]
public void ExtensionMethodsTest2()
{
string program = @"using System; using System.Collections.Generic;
@ -72,18 +72,18 @@ public static class XC { @@ -72,18 +72,18 @@ public static class XC {
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);
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("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("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 @@ -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("System.Int32", result.Type.ReflectionName);
}
@ -66,7 +66,7 @@ class B : A { @@ -66,7 +66,7 @@ class B : A {
}
}
";
MemberResolveResult result = Resolve<MemberResolveResult>(program);
InvocationResolveResult result = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("B.GetRandomNumber", result.Member.FullName);
}
@ -87,7 +87,7 @@ class B : A { @@ -87,7 +87,7 @@ class B : A {
}
}
";
MemberResolveResult result = Resolve<MemberResolveResult>(program);
InvocationResolveResult result = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("B.GetRandomNumber", result.Member.FullName);
}
@ -104,7 +104,7 @@ class B : A { @@ -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("System.Int32", result.Type.ReflectionName);
}
@ -202,11 +202,11 @@ class Program { @@ -202,11 +202,11 @@ class Program {
static void T(ref int y) {}
}";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program, "T(a)");
Assert.IsFalse(((IMethod)mrr.Member).Parameters[0].IsRef);
InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program, "T(a)");
Assert.IsFalse(mrr.Member.Parameters[0].IsRef);
mrr = Resolve<MemberResolveResult>(program, "T(ref a)");
Assert.IsTrue(((IMethod)mrr.Member).Parameters[0].IsRef);
mrr = Resolve<InvocationResolveResult>(program, "T(ref a)");
Assert.IsTrue(mrr.Member.Parameters[0].IsRef);
}
[Test, Ignore("Grouping by declaring type not yet implemented")]
@ -221,7 +221,7 @@ class Program { @@ -221,7 +221,7 @@ class Program {
class DerivedClass : BaseClass {
public void Test(object a) { }
}";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program);
InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
}
@ -237,10 +237,10 @@ class DerivedClass : BaseClass { @@ -237,10 +237,10 @@ class DerivedClass : BaseClass {
class DerivedClass : BaseClass {
public void Test(string a) { }
}";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program);
InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program);
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);
}
@ -261,7 +261,7 @@ class DerivedClass : MiddleClass { @@ -261,7 +261,7 @@ class DerivedClass : MiddleClass {
public override void Test(int a) { }
}";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program);
InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("MiddleClass.Test", mrr.Member.FullName);
}
}

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

@ -408,7 +408,7 @@ class TestClass { @@ -408,7 +408,7 @@ class TestClass {
";
TypeResolveResult trr = Resolve<TypeResolveResult>(program.Replace("COL a", "$COL$ a"));
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");
}
@ -539,7 +539,7 @@ class TestClass { @@ -539,7 +539,7 @@ class TestClass {
trr = Resolve<TypeResolveResult>(program.Replace("$", "$global::XX.XX$"));
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);
}
@ -651,7 +651,7 @@ namespace A { @@ -651,7 +651,7 @@ namespace A {
class BaseClass {
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);
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$Test$"));
@ -661,7 +661,7 @@ namespace A { @@ -661,7 +661,7 @@ namespace A {
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
// 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);
}

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

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

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

@ -171,7 +171,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -171,7 +171,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
protected T Resolve<T>(string code) where T : ResolveResult
{
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;
}

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

@ -86,7 +86,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -86,7 +86,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ITypeDefinition declType = ctx.GetTypeDefinition(typeof(int));
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;
ti.InferTypeArguments(new [] { A, B }, new [] { argument },
@ -105,7 +105,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -105,7 +105,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ITypeDefinition declType = ctx.GetTypeDefinition(typeof(Console));
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;
Assert.AreEqual(
@ -123,15 +123,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -123,15 +123,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
IType[] expectedParameterTypes;
IType inferredReturnType;
IParameter[] parameters;
public MockImplicitLambda(IType[] expectedParameterTypes, IType inferredReturnType)
{
this.expectedParameterTypes = expectedParameterTypes;
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 {
get { throw new NotImplementedException(); }
get { return parameters; }
}
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 @@ -22,7 +22,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
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 @@ -1555,6 +1555,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
}
// TODO: return implicit/explicit conversion being applied
return new ResolveResult(targetType);
}
@ -1651,7 +1652,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1651,7 +1652,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
MemberLookup lookup = new MemberLookup(context, t, t.ProjectContent);
ResolveResult r;
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 {
r = lookup.LookupType(t, identifier, typeArguments, parameterizeResultType);
}
@ -1785,11 +1786,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1785,11 +1786,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return DynamicResult;
MemberLookup lookup = CreateMemberLookup();
ResolveResult result = lookup.Lookup(target.Type, identifier, typeArguments, isInvocationTarget);
ResolveResult result = lookup.Lookup(target, identifier, typeArguments, isInvocationTarget);
if (result is UnknownMemberResolveResult) {
var extensionMethods = GetExtensionMethods(target.Type, identifier, typeArguments.Count);
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
};
}
@ -1842,6 +1843,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1842,6 +1843,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return extensionMethodGroups;
}
/// <summary>
/// Gets all extension methods available in the current using scope.
/// This list includes unaccessible
/// </summary>
List<List<IMethod>> GetAllExtensionMethods()
{
// TODO: maybe cache the result?
@ -1873,7 +1878,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1873,7 +1878,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
return
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
where m.IsExtensionMethod
select m;
@ -1894,9 +1899,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1894,9 +1899,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (mgrr != null) {
OverloadResolution or = mgrr.PerformOverloadResolution(context, arguments, argumentNames);
if (or.BestCandidate != null) {
IType returnType = or.BestCandidate.ReturnType.Resolve(context);
returnType = returnType.AcceptVisitor(new MethodTypeParameterSubstitution(or.InferredTypeArguments));
return new MemberResolveResult(or.BestCandidate, returnType);
return new InvocationResolveResult(mgrr.TargetResult, or, context);
} else {
// No candidate found at all (not even an inapplicable one).
// This can happen with empty method groups (as sometimes used with extension methods)
@ -2019,7 +2022,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2019,7 +2022,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
or.AddCandidate(p);
}
if (or.BestCandidate != null) {
return new MemberResolveResult(or.BestCandidate, or.BestCandidate.ReturnType.Resolve(context));
return new InvocationResolveResult(target, or, context);
} else {
return ErrorResult;
}
@ -2039,7 +2042,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2039,7 +2042,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
or.AddCandidate(ctor);
}
if (or.BestCandidate != null) {
return new MemberResolveResult(or.BestCandidate, type);
return new InvocationResolveResult(new TypeResolveResult(type), or, context);
} else {
return new ErrorResolveResult(type);
}

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

@ -0,0 +1,83 @@ @@ -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 @@ -162,8 +162,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <summary>
/// Performs a member lookup.
/// </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;
List<IType> types = new List<IType>();
@ -259,10 +260,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -259,10 +260,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return new UnknownMemberResolveResult(type, name, typeArguments);
IMember firstNonMethod = members.FirstOrDefault(m => !(m is IMethod));
if (members.Count == 1 && firstNonMethod != null)
return new MemberResolveResult(firstNonMethod, context);
return new MemberResolveResult(targetResolveResult, firstNonMethod, context);
if (firstNonMethod == null)
return new MethodGroupResolveResult(type, name, members.ConvertAll(m => (IMethod)m), typeArguments);
return new AmbiguousMemberResultResult(firstNonMethod, firstNonMethod.ReturnType.Resolve(context));
return new MethodGroupResolveResult(targetResolveResult, name, members.ConvertAll(m => (IMethod)m), typeArguments);
return new AmbiguousMemberResultResult(targetResolveResult, firstNonMethod, firstNonMethod.ReturnType.Resolve(context));
}
static bool IsNonInterfaceType(ITypeDefinition def)

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

@ -14,25 +14,29 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -14,25 +14,29 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
readonly IMember member;
readonly bool isConstant;
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)
throw new ArgumentNullException("member");
this.targetResult = targetResult;
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)
throw new ArgumentNullException("member");
this.targetResult = targetResult;
this.member = member;
this.isConstant = true;
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;
IField field = member as IField;
if (field != null) {

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

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

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

@ -114,12 +114,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -114,12 +114,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#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>
/// Gets/Sets whether expanding 'params' into individual elements is allowed.
/// The default value is true.
/// </summary>
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
public OverloadResolutionErrors AddCandidate(IParameterizedMember member)
{
@ -348,10 +364,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -348,10 +364,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (candidate.Parameters[parameterIndex].IsOut || candidate.Parameters[parameterIndex].IsRef)
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;
if (!c)
candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch);
if (IsExtensionMethodInvocation && parameterIndex == 0) {
// 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
@ -576,5 +599,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -576,5 +599,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
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 @@ -332,7 +332,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (resolverEnabled) {
if (variableInitializer.Parent is FieldDeclaration) {
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 {
string identifier = variableInitializer.Name;
foreach (IVariable v in resolver.LocalVariables) {
@ -353,7 +353,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -353,7 +353,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ScanChildren(fixedVariableInitializer);
if (resolverEnabled) {
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
return errorResult;
} else {
@ -371,7 +371,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -371,7 +371,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ScanChildren(member);
if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.Context);
return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context);
else
return errorResult;
} finally {
@ -418,7 +418,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -418,7 +418,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.Context);
return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context);
else
return errorResult;
} finally {
@ -453,7 +453,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -453,7 +453,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.Context);
return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context);
else
return errorResult;
} finally {
@ -522,7 +522,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -522,7 +522,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ScanChildren(enumMemberDeclaration);
if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.Context);
return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context);
else
return errorResult;
} finally {

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

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

Loading…
Cancel
Save