diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs index 4ac60f28ab..288d3a85e6 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs @@ -137,6 +137,33 @@ class A { Assert.AreEqual("System.Void", Resolve(program).Type.ReflectionName); } + [Test, Ignore("Type references cannot be resolved")] + public void DelegateCallTest() + { + string program = @"using System; +class A { + void Method(ModuleResolveEventHandler eh) { + $eh(this, new ResolveEventArgs())$; + } +} +"; + Assert.AreEqual("System.Reflection.Module", Resolve(program).Type.ReflectionName); + } + + [Test, Ignore("Type references cannot be resolved")] + public void DelegateReturnedFromMethodCallTest() + { + string program = @"using System; +class A { + void Method() { + $GetHandler()(abc)$; + } + abstract Predicate GetHandler(); +} +"; + Assert.AreEqual("System.Boolean", Resolve(program).Type.ReflectionName); + } + /* TODO [Test] public void MethodGroupResolveTest() diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs new file mode 100644 index 0000000000..9bbdb4d330 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs @@ -0,0 +1,26 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class MemberLookupTests : ResolverTestBase + { + [Test] + public void ShortMaxValueTest() + { + string program = @"using System; +class TestClass { + object a = $short.MaxValue$; +} +"; + MemberResolveResult rr = Resolve(program); + Assert.AreEqual("System.Int16", rr.Type.FullName); + Assert.AreEqual("System.Int16.MaxValue", rr.Member.FullName); + Assert.AreEqual(short.MaxValue, rr.ConstantValue); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs index 5b88d2ecd0..81589f9501 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs @@ -52,5 +52,84 @@ class A { Assert.AreEqual("ThisClassDoesNotExist", result.Identifier); Assert.AreSame(SharedTypes.UnknownType, result.Type); } + + [Test, Ignore("Resolving type references is not implemented")] + public void CTorOverloadLookupTest() + { + string program = @"class A { + void Method() { + $; + } + + static A() {} + A() {} + A(int intVal) {} + A(double dblVal) {} +} +"; + MemberResolveResult result = Resolve(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"); + Assert.AreEqual("A", result.Type.FullName); + + result = Resolve(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(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"); + } + + [Test, Ignore("Resolving type references is not implemented")] + public void DefaultCTorOverloadLookupTest() + { + string program = @"class A { + void Method() { + $new A()$; + } +} +"; + MemberResolveResult result = Resolve(program); + IMethod m = (IMethod)result.Member; + Assert.IsNotNull(m); + Assert.AreEqual("A", result.Type.ReflectionName); + Assert.AreEqual(0, m.Parameters.Count); + } + + [Test, Ignore("parser doesn't produce any nodes for base constructor calls")] + public void ChainedConstructorCall() + { + string program = @"using System; +class A { + public A(int a) {} +} +class B : A { + public B(int b) + : base(b) + {} +} +class C : B { + public C(int c) + : base(c) + {} + + public C() + : this(0) + {} +} +"; + MemberResolveResult mrr = Resolve(program, "base(b)"); + Assert.AreEqual("A.#ctor", mrr.Member.FullName); + + mrr = Resolve(program, "base(c)"); + Assert.AreEqual("B.#ctor", mrr.Member.FullName); + + mrr = Resolve(program, "this(0)"); + Assert.AreEqual("C.#ctor", mrr.Member.FullName); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs index d501234923..99fed2d1ac 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs @@ -175,6 +175,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return (T)rr; } + protected T Resolve(string code, string exprToResolve) where T : ResolveResult + { + return Resolve(code.Replace(exprToResolve, "$" + exprToResolve + "$")); + } + sealed class FindNodeVisitor : DomVisitor { readonly DomLocation start; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/SimpleNameLookupTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/SimpleNameLookupTests.cs index caa66e0993..1bf011b282 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/SimpleNameLookupTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/SimpleNameLookupTests.cs @@ -212,5 +212,104 @@ class Color { public static readonly Color Empty = null; } Resolve(program.Replace("$", "Color = $Color$.Empty;")); Resolve(program.Replace("$", "x = $Color$.ToString();")); } + + [Test] + public void ValueInsideSetterTest() + { + string program = @"class A { + public string Property { + set { + var a = $value$; + } + } +} +"; + VariableResolveResult result = Resolve(program); + Assert.AreEqual("System.String", result.Type.FullName); + Assert.AreEqual("value", result.Variable.Name); + } + + [Test, Ignore("type references not supported")] + public void ValueInsideEventTest() + { + string program = @"using System; class A { + public event EventHandler Ev { + add { + var a = $value$; + } + remove {} + } +} +"; + VariableResolveResult result = Resolve(program); + Assert.AreEqual("System.EventHandler", result.Type.FullName); + Assert.AreEqual("value", result.Variable.Name); + } + + [Test] + public void ValueInsideIndexerSetterTest() + { + string program = @"using System; class A { + public string this[int arg] { + set { + var a = $value$; + } + } +} +"; + VariableResolveResult result = Resolve(program); + Assert.AreEqual("System.String", result.Type.FullName); + Assert.AreEqual("value", result.Variable.Name); + } + + [Test, Ignore("type references not supported")] + public void AnonymousMethodParameters() + { + string program = @"using System; +class A { + void Method() { + SomeEvent += delegate(object sender, EventArgs e) { + $e$.ToString(); + }; + } } +"; + VariableResolveResult result = Resolve(program); + Assert.AreEqual("System.EventArgs", result.Type.FullName); + Assert.AreEqual("e", result.Variable.Name); + } + + [Test] + public void DefaultTypeCSharp() + { + string program = @"class A { + void Method() { + $int$ a; + } } +"; + TypeResolveResult result = Resolve(program); + Assert.AreEqual("System.Int32", result.Type.FullName); + } + + [Test] + public void LoopVariableScopeTest() + { + string program = @"using System; +class TestClass { + void Test() { + for (int i = 0; i < 10; i++) { + $1$.ToString(); + } + for (long i = 0; i < 10; i++) { + $2$.ToString(); + } + } +} +"; + VariableResolveResult lr = Resolve(program.Replace("$1$", "$i$").Replace("$2$", "i")); + Assert.AreEqual("System.Int32", lr.Type.ReflectionName); + + lr = Resolve(program.Replace("$1$", "i").Replace("$2$", "$i$")); + Assert.AreEqual("System.Int64", lr.Type.ReflectionName); + } } } diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj index 7edde7853a..ade2063462 100644 --- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj +++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -121,6 +121,7 @@ + diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs index bf7a5adfe1..cfce622458 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs @@ -60,4 +60,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase public class Nested {} } public class Derived : Base {} + + public struct MyStructWithCtor + { + public MyStructWithCtor(int a) {} + } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index 67b15c78c1..ba43e776d6 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -253,5 +253,13 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.AreEqual(new[] { typeof(Base<>.Nested).FullName + "[[System.Int32]]" }, d.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray()); } + + [Test] + public void DefaultConstructorAddedToStruct() + { + var ctors = typeof(MyStructWithCtor).ToTypeReference().Resolve(ctx).GetConstructors(ctx); + Assert.AreEqual(2, ctors.Count()); + Assert.IsFalse(ctors.Any(c => c.IsStatic)); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Dom/CSharpModifierToken.cs b/ICSharpCode.NRefactory/CSharp/Dom/CSharpModifierToken.cs index d6600b25a3..17b41e6d73 100644 --- a/ICSharpCode.NRefactory/CSharp/Dom/CSharpModifierToken.cs +++ b/ICSharpCode.NRefactory/CSharp/Dom/CSharpModifierToken.cs @@ -1,4 +1,4 @@ -// +// // CSharpModifierToken.cs // // Author: @@ -46,7 +46,7 @@ namespace ICSharpCode.NRefactory.CSharp static CSharpModifierToken () { lengthTable[Modifiers.New] = "new".Length; - lengthTable[Modifiers.Public] = "new".Length; + lengthTable[Modifiers.Public] = "public".Length; lengthTable[Modifiers.Protected] = "protected".Length; lengthTable[Modifiers.Private] = "private".Length; lengthTable[Modifiers.Internal] = "internal".Length; diff --git a/ICSharpCode.NRefactory/CSharp/Dom/TypeMembers/Accessor.cs b/ICSharpCode.NRefactory/CSharp/Dom/TypeMembers/Accessor.cs index c6c2d24564..8ec62736c1 100644 --- a/ICSharpCode.NRefactory/CSharp/Dom/TypeMembers/Accessor.cs +++ b/ICSharpCode.NRefactory/CSharp/Dom/TypeMembers/Accessor.cs @@ -1,4 +1,4 @@ -// +// // PropertyDeclaration.cs // // Author: @@ -26,7 +26,7 @@ namespace ICSharpCode.NRefactory.CSharp { - public class Accessor : AbstractMember + public class Accessor : AbstractMemberBase { public static readonly new Accessor Null = new NullAccessor (); class NullAccessor : Accessor diff --git a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs index d8d026356c..538c63abbc 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs @@ -1403,6 +1403,26 @@ namespace ICSharpCode.NRefactory.CSharp result.Keyword = "int"; } else if (typeExpression.Type == TypeManager.object_type) { result.Keyword = "object"; + } else if (typeExpression.Type == TypeManager.float_type) { + result.Keyword = "float"; + } else if (typeExpression.Type == TypeManager.double_type) { + result.Keyword = "double"; + } else if (typeExpression.Type == TypeManager.int64_type) { + result.Keyword = "long"; + } else if (typeExpression.Type == TypeManager.byte_type) { + result.Keyword = "byte"; + } else if (typeExpression.Type == TypeManager.uint32_type) { + result.Keyword = "uint"; + } else if (typeExpression.Type == TypeManager.uint64_type) { + result.Keyword = "ulong"; + } else if (typeExpression.Type == TypeManager.short_type) { + result.Keyword = "short"; + } else if (typeExpression.Type == TypeManager.ushort_type) { + result.Keyword = "ushort"; + } else if (typeExpression.Type == TypeManager.sbyte_type) { + result.Keyword = "sbyte"; + } else if (typeExpression.Type == TypeManager.decimal_type) { + result.Keyword = "decimal"; } else { throw new NotImplementedException(); } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs index c7af0f0235..f5c8f9eea3 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs @@ -222,7 +222,7 @@ 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, firstNonMethod.ReturnType.Resolve(context)); + return new MemberResolveResult(firstNonMethod, context); if (firstNonMethod == null) return new MethodGroupResolveResult(members.ConvertAll(m => (IMethod)m), typeArguments); return new AmbiguousMemberResultResult(firstNonMethod, firstNonMethod.ReturnType.Resolve(context)); diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs index 8026b89bff..f6994ef3a8 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs @@ -12,6 +12,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public class MemberResolveResult : ResolveResult { readonly IMember member; + readonly bool isConstant; + readonly object constantValue; public MemberResolveResult(IMember member, IType returnType) : base(returnType) { @@ -20,10 +22,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.member = member; } + public MemberResolveResult(IMember member, IType returnType, object constantValue) : base(returnType) + { + if (member == null) + throw new ArgumentNullException("member"); + this.member = member; + this.isConstant = true; + this.constantValue = constantValue; + } + + public MemberResolveResult(IMember member, ITypeResolveContext context) : base(member.ReturnType.Resolve(context)) + { + this.member = member; + IField field = member as IField; + if (field != null) { + isConstant = field.IsConst; + if (isConstant) + constantValue = field.ConstantValue.GetValue(context); + } + } + public IMember Member { get { return member; } } + public override bool IsCompileTimeConstant { + get { return isConstant; } + } + + public override object ConstantValue { + get { return constantValue; } + } + public override string ToString() { return string.Format("[{0} {1}]", GetType().Name, member); diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs index 4f06543df4..78259db158 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs @@ -270,7 +270,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ScanChildren(member); if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); + return new MemberResolveResult(resolver.CurrentMember, resolver.Context); else return errorResult; } finally { @@ -317,7 +317,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); + return new MemberResolveResult(resolver.CurrentMember, resolver.Context); else return errorResult; } finally { @@ -352,7 +352,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); + return new MemberResolveResult(resolver.CurrentMember, resolver.Context); else return errorResult; } finally { @@ -388,7 +388,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ScanChildren(enumMemberDeclaration); if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); + return new MemberResolveResult(resolver.CurrentMember, resolver.Context); else return errorResult; } finally { @@ -1132,16 +1132,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override ResolveResult VisitConstraint(Constraint constraint, object data) { + ScanChildren(constraint); return null; } public override ResolveResult VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) { + ScanChildren(constructorInitializer); return null; } public override ResolveResult VisitAccessorDeclaration(Accessor accessorDeclaration, object data) { + ScanChildren(accessorDeclaration); return null; } } diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index 4a7ce81313..5f8272f3d9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -819,6 +819,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } AddAttributes(field, f); + f.ReturnType = ReadTypeReference(field.FieldType, typeAttributes: field, entity: f); RequiredModifierType modreq = field.FieldType as RequiredModifierType; if (modreq != null && modreq.ModifierType.FullName == typeof(IsVolatile).FullName) { f.IsVolatile = true;