Browse Source

Fixed forum-17917: Overriding properties that have get/set accessors with different visibility as the property does not insert the visibility modifier in the overriding code.

Overriding abstract members now inserts "throw new NotImplementedException();" instead of a call to the base method.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2613 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 18 years ago
parent
commit
a65659b0d3
  1. 88
      src/Main/Base/Test/GenerateOverrideMethodTests.cs
  2. 1
      src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj
  3. 2
      src/Main/Base/Test/NRefactoryResolverTests.cs
  4. 12
      src/Main/Base/Test/Utils/MockProperty.cs
  5. 31
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultProperty.cs
  6. 8
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IProperty.cs
  7. 2
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs
  8. 57
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs
  9. 16
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/DomPersistence.cs

88
src/Main/Base/Test/GenerateOverrideMethodTests.cs

@ -0,0 +1,88 @@ @@ -0,0 +1,88 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.Refactoring;
using NUnit.Framework;
using System.Text;
namespace ICSharpCode.SharpDevelop.Tests
{
/// <summary>
/// Description of GenerateOverrideMethod.
/// </summary>
[TestFixture]
public class GenerateOverrideMethodTests
{
NRefactoryResolverTests helper = new NRefactoryResolverTests();
void Run(string input, string expectedOutput)
{
ICompilationUnit cu = helper.Parse("a.cs", input + "\nclass DerivedClass {\n \n}");
Assert.AreEqual(2, cu.Classes.Count);
Assert.AreEqual(1, cu.Classes[0].Methods.Count + cu.Classes[0].Properties.Count);
IMember virtualMember;
if (cu.Classes[0].Methods.Count > 0)
virtualMember = cu.Classes[0].Methods[0];
else //if (cu.Classes[0].Properties.Count > 0)
virtualMember = cu.Classes[0].Properties[0];
CSharpCodeGenerator ccg = new CSharpCodeGenerator();
AttributedNode result = ccg.GetOverridingMethod(virtualMember, new ClassFinder(cu.Classes[1], 3, 1));
Assert.IsNotNull(result);
string output = ccg.GenerateCode(result, "");
Assert.AreEqual(expectedOutput, NormalizeWhitespace(output));
}
string NormalizeWhitespace(string t)
{
StringBuilder b = new StringBuilder();
bool wasWhitespace = true;
foreach (char c in t) {
if (char.IsWhiteSpace(c)) {
if (!wasWhitespace) {
wasWhitespace = true;
b.Append(' ');
}
} else {
b.Append(c);
wasWhitespace = false;
}
}
return b.ToString().Trim();
}
[Test]
public void ReadonlyVirtualProperty()
{
Run("class BaseClass { public virtual int Prop { get { return 0; } } }",
"public override int Prop { get { return base.Prop; } }");
}
[Test]
public void ReadonlyAbstractProperty()
{
Run("class BaseClass { public abstract int Prop { get; } }",
"public override int Prop { get { throw new NotImplementedException(); } }");
}
[Test]
public void ReadWriteProperty()
{
Run("class BaseClass { public virtual int Prop { get { return 0; } set { } } }",
"public override int Prop { get { return base.Prop; } set { base.Prop = value; } }");
}
[Test]
public void PublicReadProtectedWriteProperty()
{
Run("class BaseClass { public virtual int Prop { get { return 0; } protected set { } } }",
"public override int Prop { get { return base.Prop; } protected set { base.Prop = value; } }");
}
}
}

1
src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj

@ -56,6 +56,7 @@ @@ -56,6 +56,7 @@
<Compile Include="FindNextWithCursorAtEndTestFixture.cs" />
<Compile Include="ForwardIteratorWithEmptyTextBufferTestFixture.cs" />
<Compile Include="ForwardTextIteratorPositionIsEndOffsetTestFixture.cs" />
<Compile Include="GenerateOverrideMethodTests.cs" />
<Compile Include="NRefactoryResolverTests.cs" />
<Compile Include="CollectionClassOverridesTestFixture.cs" />
<Compile Include="OverridableMethodsTestFixture.cs" />

2
src/Main/Base/Test/NRefactoryResolverTests.cs

@ -23,7 +23,7 @@ namespace ICSharpCode.SharpDevelop.Tests @@ -23,7 +23,7 @@ namespace ICSharpCode.SharpDevelop.Tests
ProjectContentRegistry projectContentRegistry = ParserService.DefaultProjectContentRegistry;
#region Test helper methods
ICompilationUnit Parse(string fileName, string fileContent)
public ICompilationUnit Parse(string fileName, string fileContent)
{
ICSharpCode.NRefactory.IParser p = ICSharpCode.NRefactory.ParserFactory.CreateParser(ICSharpCode.NRefactory.SupportedLanguage.CSharp, new StringReader(fileContent));
p.ParseMethodBodies = false;

12
src/Main/Base/Test/Utils/MockProperty.cs

@ -36,6 +36,18 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils @@ -36,6 +36,18 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils
}
}
public ModifierEnum GetterModifiers {
get {
throw new NotImplementedException();
}
}
public ModifierEnum SetterModifiers {
get {
throw new NotImplementedException();
}
}
public bool CanGet {
get {
throw new NotImplementedException();

31
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultProperty.cs

@ -21,6 +21,7 @@ namespace ICSharpCode.SharpDevelop.Dom { @@ -21,6 +21,7 @@ namespace ICSharpCode.SharpDevelop.Dom {
const byte getterFlag = 0x02;
const byte setterFlag = 0x04;
const byte extensionFlag = 0x08;
ModifierEnum getterModifiers, setterModifiers;
public bool IsIndexer {
get { return (accessFlags & indexerFlag) == indexerFlag; }
@ -70,23 +71,25 @@ namespace ICSharpCode.SharpDevelop.Dom { @@ -70,23 +71,25 @@ namespace ICSharpCode.SharpDevelop.Dom {
parameters = value;
}
}
public DomRegion GetterRegion {
get {
return getterRegion;
}
set {
getterRegion = value;
}
get { return getterRegion; }
set { getterRegion = value; }
}
public DomRegion SetterRegion {
get {
return setterRegion;
}
set {
setterRegion = value;
}
get { return setterRegion; }
set { setterRegion = value; }
}
public ModifierEnum GetterModifiers {
get { return getterModifiers; }
set { getterModifiers = value; }
}
public ModifierEnum SetterModifiers {
get { return setterModifiers; }
set { setterModifiers = value; }
}
public DefaultProperty(IClass declaringType, string name) : base(declaringType, name)

8
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IProperty.cs

@ -30,5 +30,13 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -30,5 +30,13 @@ namespace ICSharpCode.SharpDevelop.Dom
bool IsIndexer {
get;
}
ModifierEnum GetterModifiers {
get;
}
ModifierEnum SetterModifiers {
get;
}
}
}

2
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs

@ -569,10 +569,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -569,10 +569,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
if (propertyDeclaration.HasGetRegion) {
property.GetterRegion = GetRegion(propertyDeclaration.GetRegion.StartLocation, propertyDeclaration.GetRegion.EndLocation);
property.CanGet = true;
property.GetterModifiers = ConvertModifier(propertyDeclaration.GetRegion.Modifier, ModifierEnum.None);
}
if (propertyDeclaration.HasSetRegion) {
property.SetterRegion = GetRegion(propertyDeclaration.SetRegion.StartLocation, propertyDeclaration.SetRegion.EndLocation);
property.CanSet = true;
property.SetterModifiers = ConvertModifier(propertyDeclaration.SetRegion.Modifier, ModifierEnum.None);
}
property.Documentation = GetDocumentation(region.BeginLine, propertyDeclaration.Attributes);
ConvertAttributes(propertyDeclaration, property);

57
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs

@ -223,8 +223,14 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -223,8 +223,14 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
p.Name,
ConvertParameters(p.Parameters, targetContext));
md.TypeReference = ConvertType(p.ReturnType, targetContext);
if (p.CanGet) md.GetRegion = new PropertyGetRegion(CreateNotImplementedBlock(), null);
if (p.CanSet) md.SetRegion = new PropertySetRegion(CreateNotImplementedBlock(), null);
if (p.CanGet) {
md.GetRegion = new PropertyGetRegion(CreateNotImplementedBlock(), null);
md.GetRegion.Modifier = ConvertModifier(p.GetterModifiers, null);
}
if (p.CanSet) {
md.SetRegion = new PropertySetRegion(CreateNotImplementedBlock(), null);
md.SetRegion.Modifier = ConvertModifier(p.SetterModifiers, null);
}
return md;
}
}
@ -593,29 +599,32 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -593,29 +599,32 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
node.Modifier &= ~(Modifiers.Virtual | Modifiers.Abstract);
node.Modifier |= Modifiers.Override;
MethodDeclaration method = node as MethodDeclaration;
if (method != null) {
method.Body.Children.Clear();
if (method.TypeReference.SystemType == "System.Void") {
method.Body.AddChild(new ExpressionStatement(CreateForwardingMethodCall(method)));
} else {
method.Body.AddChild(new ReturnStatement(CreateForwardingMethodCall(method)));
}
}
PropertyDeclaration property = node as PropertyDeclaration;
if (property != null) {
Expression field = new FieldReferenceExpression(new BaseReferenceExpression(),
property.Name);
if (!property.GetRegion.Block.IsNull) {
property.GetRegion.Block.Children.Clear();
property.GetRegion.Block.AddChild(new ReturnStatement(field));
if (!baseMember.IsAbstract) {
// replace the method/property body with a call to the base method/property
MethodDeclaration method = node as MethodDeclaration;
if (method != null) {
method.Body.Children.Clear();
if (method.TypeReference.SystemType == "System.Void") {
method.Body.AddChild(new ExpressionStatement(CreateForwardingMethodCall(method)));
} else {
method.Body.AddChild(new ReturnStatement(CreateForwardingMethodCall(method)));
}
}
if (!property.SetRegion.Block.IsNull) {
property.SetRegion.Block.Children.Clear();
Expression expr = new AssignmentExpression(field,
AssignmentOperatorType.Assign,
new IdentifierExpression("value"));
property.SetRegion.Block.AddChild(new ExpressionStatement(expr));
PropertyDeclaration property = node as PropertyDeclaration;
if (property != null) {
Expression field = new FieldReferenceExpression(new BaseReferenceExpression(),
property.Name);
if (!property.GetRegion.Block.IsNull) {
property.GetRegion.Block.Children.Clear();
property.GetRegion.Block.AddChild(new ReturnStatement(field));
}
if (!property.SetRegion.Block.IsNull) {
property.SetRegion.Block.Children.Clear();
Expression expr = new AssignmentExpression(field,
AssignmentOperatorType.Assign,
new IdentifierExpression("value"));
property.SetRegion.Block.AddChild(new ExpressionStatement(expr));
}
}
}
return node;

16
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/DomPersistence.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -20,7 +20,7 @@ namespace ICSharpCode.SharpDevelop.Dom
{
public const long FileMagic = 0x11635233ED2F428C;
public const long IndexFileMagic = 0x11635233ED2F427D;
public const short FileVersion = 12;
public const short FileVersion = 13;
ProjectContentRegistry registry;
string cacheDirectory;
@ -929,6 +929,13 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -929,6 +929,13 @@ namespace ICSharpCode.SharpDevelop.Dom
} else {
writer.Write((byte)0);
}
writer.Write((byte)((p.GetterModifiers != ModifierEnum.None ? 1 : 0) + (p.SetterModifiers != ModifierEnum.None ? 2 : 0)));
if (p.GetterModifiers != ModifierEnum.None) {
writer.Write((int)p.GetterModifiers);
}
if (p.SetterModifiers != ModifierEnum.None) {
writer.Write((int)p.SetterModifiers);
}
WriteParameters(p.Parameters);
}
@ -937,6 +944,13 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -937,6 +944,13 @@ namespace ICSharpCode.SharpDevelop.Dom
DefaultProperty p = new DefaultProperty(currentClass, ReadString());
ReadMember(p);
p.accessFlags = reader.ReadByte();
byte b = reader.ReadByte();
if ((b & 1) == 1) {
p.GetterModifiers = (ModifierEnum)reader.ReadInt32();
}
if ((b & 2) == 2) {
p.SetterModifiers = (ModifierEnum)reader.ReadInt32();
}
ReadParameters(p);
return p;
}

Loading…
Cancel
Save