From 1363faf7883c0257cc544c269c3fc78dce1e403d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20K=C3=A4ll=C3=A9n?= Date: Mon, 18 Jun 2012 01:36:20 +0200 Subject: [PATCH 1/2] Tests demonstrating issues with parameter identity in accessors. --- .../CSharp/Resolver/MethodTests.cs | 183 ++++++++++++++++++ .../ICSharpCode.NRefactory.Tests.csproj | 1 + 2 files changed, 184 insertions(+) create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Resolver/MethodTests.cs diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MethodTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MethodTests.cs new file mode 100644 index 0000000000..185faa7410 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MethodTests.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver { + [TestFixture] + public class MethodTests : ResolverTestBase { + [Test] + public void ParameterIdentityInNormalMethod() + { + string code = @"using System; +class TestClass { + $int F(int i, int j) { + return i + j; + }$ +}"; + + var prep = PrepareResolver(code); + var md = (MethodDeclaration)prep.Item2; + + var resolver = prep.Item1; + var method = (IMethod)((MemberResolveResult)resolver.Resolve(md)).Member; + IVariable i1 = method.Parameters.Single(p => p.Name == "i"); + IVariable j1 = method.Parameters.Single(p => p.Name == "j"); + + var returnExpr = (BinaryOperatorExpression)md.Body.Children.OfType().Single().Expression; + var returnRR = (OperatorResolveResult)resolver.Resolve(returnExpr); + + IVariable i2 = ((LocalResolveResult)returnRR.Operands[0]).Variable; + IVariable j2 = ((LocalResolveResult)returnRR.Operands[1]).Variable; + + Assert.IsTrue(ReferenceEquals(i1, i2)); + Assert.IsTrue(ReferenceEquals(i1, i2)); + } + + [Test] + public void ParameterIdentityInPropertySetter() + { + string code = @"using System; +class TestClass { + int myField; + $int Prop { + get { return myField; } + set { myField = value; } + }$ +}"; + + var prep = PrepareResolver(code); + var pd = (PropertyDeclaration)prep.Item2; + + var resolver = prep.Item1; + var property = (IProperty)((MemberResolveResult)resolver.Resolve(pd)).Member; + IVariable value1 = property.Setter.Parameters.Single(p => p.Name == "value"); + + var assignExpr = (AssignmentExpression)pd.Setter.Body.Children.OfType().Single().Expression; + var assignRR = (OperatorResolveResult)resolver.Resolve(assignExpr); + + IVariable value2 = ((LocalResolveResult)assignRR.Operands[1]).Variable; + + Assert.IsTrue(ReferenceEquals(value1, value2)); + } + + [Test] + public void ParameterIdentityInIndexerGetter() + { + string code = @"using System; +class TestClass { + int[,] myField; + $int this[int i, int j] { + get { return myField[i, j]; } + set { myField[i, j] = value; } + }$ +}"; + + var prep = PrepareResolver(code); + var id = (IndexerDeclaration)prep.Item2; + + var resolver = prep.Item1; + var property = (IProperty)((MemberResolveResult)resolver.Resolve(id)).Member; + IVariable i1 = property.Getter.Parameters.Single(p => p.Name == "i"); + IVariable j1 = property.Getter.Parameters.Single(p => p.Name == "j"); + + var accessExpr = (IndexerExpression)id.Getter.Body.Children.OfType().Single().Expression; + var accessRR = (ArrayAccessResolveResult)resolver.Resolve(accessExpr); + IVariable i2 = ((LocalResolveResult)accessRR.Indexes[0]).Variable; + IVariable j2 = ((LocalResolveResult)accessRR.Indexes[1]).Variable; + + Assert.IsTrue(ReferenceEquals(i1, i2)); + Assert.IsTrue(ReferenceEquals(j1, j2)); + } + + [Test] + public void ParameterIdentityInIndexerSetter() + { + string code = @"using System; +class TestClass { + int[,] myField; + $int this[int i, int j] { + get { return myField[i, j]; } + set { myField[i, j] = value; } + }$ +}"; + + var prep = PrepareResolver(code); + var id = (IndexerDeclaration)prep.Item2; + + var resolver = prep.Item1; + var property = (IProperty)((MemberResolveResult)resolver.Resolve(id)).Member; + IVariable i1 = property.Setter.Parameters.Single(p => p.Name == "i"); + IVariable j1 = property.Setter.Parameters.Single(p => p.Name == "j"); + IVariable value1 = property.Setter.Parameters.Single(p => p.Name == "value"); + + var assignExpr = (AssignmentExpression)id.Setter.Body.Children.OfType().Single().Expression; + var assignRR = (OperatorResolveResult)resolver.Resolve(assignExpr); + var accessRR = (ArrayAccessResolveResult)assignRR.Operands[0]; + IVariable i2 = ((LocalResolveResult)accessRR.Indexes[0]).Variable; + IVariable j2 = ((LocalResolveResult)accessRR.Indexes[1]).Variable; + IVariable value2 = ((LocalResolveResult)assignRR.Operands[1]).Variable; + + Assert.IsTrue(ReferenceEquals(i1, i2)); + Assert.IsTrue(ReferenceEquals(j1, j2)); + Assert.IsTrue(ReferenceEquals(value1, value2)); + } + + [Test] + public void ParameterIdentityInEventAdder() + { + string code = @"using System; +class TestClass { + EventHandler myField; + $event EventHandler Evt { + add { myField += value; } + remove { myField -= value; } + }$ +}"; + + var prep = PrepareResolver(code); + var ed = (CustomEventDeclaration)prep.Item2; + + var resolver = prep.Item1; + var evt = (IEvent)((MemberResolveResult)resolver.Resolve(ed)).Member; + IVariable value1 = evt.AddAccessor.Parameters.Single(p => p.Name == "value"); + + var assignExpr = (AssignmentExpression)ed.AddAccessor.Body.Children.OfType().Single().Expression; + var assignRR = (OperatorResolveResult)resolver.Resolve(assignExpr); + + IVariable value2 = ((LocalResolveResult)assignRR.Operands[1]).Variable; + + Assert.IsTrue(ReferenceEquals(value1, value2)); + } + + [Test] + public void ParameterIdentityInEventRemover() + { + string code = @"using System; +class TestClass { + EventHandler myField; + $event EventHandler Evt { + add { myField += value; } + remove { myField -= value; } + }$ +}"; + + var prep = PrepareResolver(code); + var ed = (CustomEventDeclaration)prep.Item2; + + var resolver = prep.Item1; + var evt = (IEvent)((MemberResolveResult)resolver.Resolve(ed)).Member; + IVariable value1 = evt.RemoveAccessor.Parameters.Single(p => p.Name == "value"); + + var assignExpr = (AssignmentExpression)ed.RemoveAccessor.Body.Children.OfType().Single().Expression; + var assignRR = (OperatorResolveResult)resolver.Resolve(assignExpr); + + IVariable value2 = ((LocalResolveResult)assignRR.Operands[1]).Variable; + + Assert.IsTrue(ReferenceEquals(value1, value2)); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj index 4d21a8c105..b0db8973ec 100644 --- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj +++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -166,6 +166,7 @@ + From 9476183889738efb8a50a2220bd226e67bad218a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20K=C3=A4ll=C3=A9n?= Date: Mon, 18 Jun 2012 01:24:02 +0200 Subject: [PATCH 2/2] Fix for the parameter identity in accessors issue. --- .../Resolver/ResolveVisitor.cs | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs index f4823ea7ae..884560b128 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs @@ -850,15 +850,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver resolver.CurrentTypeResolveContext, propertyOrIndexerDeclaration.EntityType, name, explicitInterfaceType, parameterTypeReferences: parameterTypeReferences); } - resolver = resolver.WithCurrentMember(member); for (AstNode node = propertyOrIndexerDeclaration.FirstChild; node != null; node = node.NextSibling) { - if (node.Role == PropertyDeclaration.SetterRole && member != null) { + if (node.Role == PropertyDeclaration.GetterRole && member is IProperty) { resolver = resolver.PushBlock(); - resolver = resolver.AddVariable(new DefaultParameter(member.ReturnType, "value")); + resolver = resolver.WithCurrentMember(((IProperty)member).Getter); Scan(node); resolver = resolver.PopBlock(); - } else { + } + else if (node.Role == PropertyDeclaration.SetterRole && member is IProperty) { + resolver = resolver.PushBlock(); + resolver = resolver.WithCurrentMember(((IProperty)member).Setter); + Scan(node); + resolver = resolver.PopBlock(); + } + else { Scan(node); } } @@ -898,16 +904,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver explicitInterfaceAstType.ToTypeReference()); } } - resolver = resolver.WithCurrentMember(member); - - if (member != null) { - resolver = resolver.PushBlock(); - resolver = resolver.AddVariable(new DefaultParameter(member.ReturnType, "value")); - ScanChildren(eventDeclaration); - } else { - ScanChildren(eventDeclaration); + + for (AstNode node = eventDeclaration.FirstChild; node != null; node = node.NextSibling) { + if (node.Role == CustomEventDeclaration.AddAccessorRole && member is IEvent) { + resolver = resolver.PushBlock(); + resolver = resolver.WithCurrentMember(((IEvent)member).AddAccessor); + Scan(node); + resolver = resolver.PopBlock(); + } + else if (node.Role == CustomEventDeclaration.RemoveAccessorRole && member is IEvent) { + resolver = resolver.PushBlock(); + resolver = resolver.WithCurrentMember(((IEvent)member).RemoveAccessor); + Scan(node); + resolver = resolver.PopBlock(); + } + else { + Scan(node); + } } - + if (member != null) return new MemberResolveResult(null, member, false); else