diff --git a/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/OverrideMethodsCodeGenerator.cs b/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/OverrideMethodsCodeGenerator.cs index 8e2a953be2..3a67755259 100644 --- a/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/OverrideMethodsCodeGenerator.cs +++ b/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/OverrideMethodsCodeGenerator.cs @@ -9,6 +9,7 @@ using System; using System.Collections; using System.Collections.Generic; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.NRefactory.Ast; @@ -36,17 +37,8 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands protected override void InitContent() { - foreach (IClass c in currentClass.ClassInheritanceTree) { - if (c.FullyQualifiedName != currentClass.FullyQualifiedName) { - foreach (IMethod method in c.Methods) { - if (!method.IsPrivate && (method.IsAbstract || method.IsVirtual || method.IsOverride)) { - MethodWrapper newWrapper = new MethodWrapper(method); - if (!Content.Contains(newWrapper)) { - Content.Add(newWrapper); - } - } - } - } + foreach (IMethod m in OverrideCompletionDataProvider.GetOverridableMethods(currentClass)) { + Content.Add(new MethodWrapper(m)); } Content.Sort(); } diff --git a/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/OverridePropertiesCodeGenerator.cs b/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/OverridePropertiesCodeGenerator.cs index 24a8437913..923a0da330 100644 --- a/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/OverridePropertiesCodeGenerator.cs +++ b/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/OverridePropertiesCodeGenerator.cs @@ -9,6 +9,7 @@ using System; using System.Collections; using System.Collections.Generic; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.NRefactory.Ast; @@ -36,23 +37,8 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands protected override void InitContent() { - foreach (IClass c in currentClass.ClassInheritanceTree) { - if (c.FullyQualifiedName != currentClass.FullyQualifiedName) { - foreach (IProperty property in c.Properties) { - if (!property.IsPrivate && (property.IsAbstract || property.IsVirtual || property.IsOverride)) { - bool alreadyAdded = false; - foreach (PropertyWrapper w in Content) { - if (w.Property.Name == property.Name) { - alreadyAdded = true; - break; - } - } - if (!alreadyAdded) { - Content.Add(new PropertyWrapper(property)); - } - } - } - } + foreach (IProperty p in OverrideCompletionDataProvider.GetOverridableProperties(currentClass)) { + Content.Add(new PropertyWrapper(p)); } Content.Sort(); } diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/OverrideCompletionDataProvider.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/OverrideCompletionDataProvider.cs index 3363aa518b..9256b8c5c6 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/OverrideCompletionDataProvider.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/OverrideCompletionDataProvider.cs @@ -17,6 +17,48 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor { public class OverrideCompletionDataProvider : AbstractCompletionDataProvider { + /// + /// Gets a list of overridable methods from the specified class. + /// A better location for this method is in the DefaultClass + /// class and the IClass interface. + /// + public static IMethod[] GetOverridableMethods(IClass c) + { + if (c == null) { + throw new ArgumentException("c"); + } + + List methods = new List(); + foreach (IMethod m in c.DefaultReturnType.GetMethods()) { + if (m.IsOverridable && !m.IsConst && !m.IsPrivate) { + if (m.DeclaringType.FullyQualifiedName != c.FullyQualifiedName) { + methods.Add(m); + } + } + } + return methods.ToArray(); + } + + /// + /// Gets a list of overridable properties from the specified class. + /// + public static IProperty[] GetOverridableProperties(IClass c) + { + if (c == null) { + throw new ArgumentException("c"); + } + + List properties = new List(); + foreach (IProperty p in c.DefaultReturnType.GetProperties()) { + if (p.IsOverridable && !p.IsConst && !p.IsPrivate) { + if (p.DeclaringType.FullyQualifiedName != c.FullyQualifiedName) { + properties.Add(p); + } + } + } + return properties.ToArray(); + } + public override ICompletionData[] GenerateCompletionData(string fileName, TextArea textArea, char charTyped) { ParseInformation parseInfo = ParserService.GetParseInformation(fileName); @@ -24,27 +66,11 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor IClass c = parseInfo.MostRecentCompilationUnit.GetInnermostClass(textArea.Caret.Line, textArea.Caret.Column); if (c == null) return null; List result = new List(); - foreach (IMethod m in c.DefaultReturnType.GetMethods()) { - if (m.IsPublic || m.IsProtected) { - if (m.IsAbstract || m.IsVirtual || m.IsOverride) { - if (!m.IsSealed && !m.IsConst) { - if (m.DeclaringType.FullyQualifiedName != c.FullyQualifiedName) { - result.Add(new OverrideCompletionData(m)); - } - } - } - } + foreach (IMethod m in GetOverridableMethods(c)) { + result.Add(new OverrideCompletionData(m)); } - foreach (IProperty m in c.DefaultReturnType.GetProperties()) { - if (m.IsPublic || m.IsProtected) { - if (m.IsAbstract || m.IsVirtual || m.IsOverride) { - if (!m.IsSealed && !m.IsConst) { - if (m.DeclaringType.FullyQualifiedName != c.FullyQualifiedName) { - result.Add(new OverrideCompletionData(m)); - } - } - } - } + foreach (IProperty p in GetOverridableProperties(c)) { + result.Add(new OverrideCompletionData(p)); } return result.ToArray(); } diff --git a/src/Main/Base/Test/AbstractDecorationIsOverridableTestFixture.cs b/src/Main/Base/Test/AbstractDecorationIsOverridableTestFixture.cs new file mode 100644 index 0000000000..a0660c446f --- /dev/null +++ b/src/Main/Base/Test/AbstractDecorationIsOverridableTestFixture.cs @@ -0,0 +1,63 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Tests.Utils; +using NUnit.Framework; + +namespace ICSharpCode.SharpDevelop.Tests +{ + /// + /// Tests that the IsOverridable property returns the expected value. + /// + [TestFixture] + public class AbstractDecorationIsOverridableTestFixture + { + MockDecoration decoration; + + [SetUp] + public void SetUp() + { + decoration = new MockDecoration(); + } + + [Test] + public void NotOverridableByDefault() + { + Assert.IsFalse(decoration.IsOverridable); + } + + [Test] + public void IsOverrideSet() + { + decoration.Modifiers = ModifierEnum.Override; + Assert.IsTrue(decoration.IsOverridable); + } + + [Test] + public void IsVirtualSet() + { + decoration.Modifiers = ModifierEnum.Virtual; + Assert.IsTrue(decoration.IsOverridable); + } + + [Test] + public void IsAbstractSet() + { + decoration.Modifiers = ModifierEnum.Abstract; + Assert.IsTrue(decoration.IsOverridable); + } + + [Test] + public void IsAbstractAndSealedSet() + { + decoration.Modifiers = ModifierEnum.Abstract | ModifierEnum.Sealed; + Assert.IsFalse(decoration.IsOverridable); + } + } +} diff --git a/src/Main/Base/Test/CollectionClassOverridesTestFixture.cs b/src/Main/Base/Test/CollectionClassOverridesTestFixture.cs new file mode 100644 index 0000000000..d9d81df34d --- /dev/null +++ b/src/Main/Base/Test/CollectionClassOverridesTestFixture.cs @@ -0,0 +1,142 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Reflection; +using System.Text; + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.DefaultEditor.Commands; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Dom.CSharp; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Tests.Utils; +using NUnit.Framework; + +namespace ICSharpCode.SharpDevelop.Tests +{ + /// + /// SD2-1199. Tests the available overrides for the + /// System.Collections.ObjectModel.Collection class. + /// + [TestFixture] + public class CollectionClassOverridesTestFixture + { + [TestFixtureSetUp] + public void SetUpFixture() + { + if (!PropertyService.Initialized) { + PropertyService.InitializeService(String.Empty, String.Empty, String.Empty); + } + } + + /// + /// This shows how to get the list of overridable methods in the + /// Collection class using reflection only. + /// + public void GetMethodsThroughReflection() + { + Assembly a = Assembly.Load("mscorlib"); + Type t = a.GetType("System.Collections.ObjectModel.Collection`1"); + + List methodNames = new List(); + BindingFlags bindingFlags = BindingFlags.Instance | + BindingFlags.NonPublic | + BindingFlags.DeclaredOnly | + BindingFlags.Public; + + foreach (MethodInfo m in t.GetMethods(bindingFlags)) { + if (m.IsVirtual && !m.IsSpecialName && !m.IsFinal) { + methodNames.Add(m.Name); + } + } + + List expectedMethodNames = new List(); + expectedMethodNames.Add("ClearItems"); + expectedMethodNames.Add("InsertItem"); + expectedMethodNames.Add("RemoveItem"); + expectedMethodNames.Add("SetItem"); + + StringBuilder sb = new StringBuilder(); + foreach (string s in methodNames.ToArray()) { + sb.AppendLine(s); + } + Assert.AreEqual(expectedMethodNames.ToArray(), methodNames.ToArray(), sb.ToString()); + } + + /// + /// Tests that the IsSealed property is set for methods that are + /// flagged as final. The ReflectionMethod class was not setting + /// this correctly. + /// + [Test] + public void ExpectedMethodsFromProjectContent() + { + ProjectContentRegistry registry = new ProjectContentRegistry(); + IProjectContent mscorlibProjectContent = registry.Mscorlib; + IClass c = mscorlibProjectContent.GetClass("System.Collections.ObjectModel.Collection"); + + List methodNames = new List(); + foreach (IMethod m in c.Methods) { + if (m.IsVirtual && !m.IsSealed) { + methodNames.Add(m.Name); + } + } + + List expectedMethodNames = new List(); + expectedMethodNames.Add("ClearItems"); + expectedMethodNames.Add("InsertItem"); + expectedMethodNames.Add("RemoveItem"); + expectedMethodNames.Add("SetItem"); + + Assert.AreEqual(expectedMethodNames.ToArray(), methodNames.ToArray()); + } + + /// + /// Tests that the OverrideMethodsCodeGenerator returns the correct + /// methods for the System.Collections.ObjectModel.Collection type. + /// + [Test] + public void CodeGeneratorMethods() + { + ProjectContentRegistry registry = new ProjectContentRegistry(); + IProjectContent mscorlibProjectContent = registry.Mscorlib; + IClass collectionClass = mscorlibProjectContent.GetClass("System.Collections.ObjectModel.Collection"); + + DefaultProjectContent projectContent = new DefaultProjectContent(); + DefaultCompilationUnit unit = new DefaultCompilationUnit(projectContent); + DefaultClass c = new DefaultClass(unit, "MyCollection"); + c.BaseTypes.Add(new DefaultReturnType(collectionClass)); + + MockProject project = new MockProject(); + ProjectService.CurrentProject = project; + + OverrideMethodsCodeGenerator codeGenerator = new OverrideMethodsCodeGenerator(); + codeGenerator.Initialize(c); + + List methods = new List(); + foreach (object o in codeGenerator.Content) { + methods.Add(o.ToString()); + } + + List expectedMethods = new List(); + expectedMethods.Add("ClearItems"); + expectedMethods.Add("Equals"); + expectedMethods.Add("Finalize"); + expectedMethods.Add("GetHashCode"); + expectedMethods.Add("InsertItem"); + expectedMethods.Add("RemoveItem"); + expectedMethods.Add("SetItem"); + expectedMethods.Add("ToString"); + + Assert.AreEqual(expectedMethods.ToArray(), methods.ToArray()); + } + } +} + diff --git a/src/Main/Base/Test/ExceptionClassOverridesTestFixture.cs b/src/Main/Base/Test/ExceptionClassOverridesTestFixture.cs new file mode 100644 index 0000000000..b17eb07569 --- /dev/null +++ b/src/Main/Base/Test/ExceptionClassOverridesTestFixture.cs @@ -0,0 +1,143 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Reflection; +using System.Text; + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.DefaultEditor.Commands; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Dom.CSharp; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Tests.Utils; +using NUnit.Framework; + +namespace ICSharpCode.SharpDevelop.Tests +{ + /// + /// Tests the available overrides for the + /// System.Exception class. + /// + [TestFixture] + public class ExceptionClassOverridesTestFixture + { + [TestFixtureSetUp] + public void SetUpFixture() + { + if (!PropertyService.Initialized) { + PropertyService.InitializeService(String.Empty, String.Empty, String.Empty); + } + } + + /// + /// This shows how to get the list of overridable properties in the + /// Exception class using reflection only. + /// + public void GetPropertiesThroughReflection() + { + Assembly a = Assembly.Load("mscorlib"); + Type t = a.GetType("System.Exception"); + + List propertyNames = new List(); + BindingFlags bindingFlags = BindingFlags.Instance | + BindingFlags.NonPublic | + BindingFlags.DeclaredOnly | + BindingFlags.Public; + + foreach (PropertyInfo p in t.GetProperties(bindingFlags)) { + MethodInfo m = p.GetGetMethod(true); + if (m.IsVirtual && !m.IsPrivate && !m.IsFinal) { + propertyNames.Add(p.Name); + } + } + + List expectedPropertyNames = new List(); + expectedPropertyNames.Add("Data"); + expectedPropertyNames.Add("HelpLink"); + expectedPropertyNames.Add("Message"); + expectedPropertyNames.Add("Source"); + expectedPropertyNames.Add("StackTrace"); + + StringBuilder sb = new StringBuilder(); + foreach (string s in propertyNames.ToArray()) { + sb.AppendLine(s); + } + Assert.AreEqual(expectedPropertyNames.ToArray(), propertyNames.ToArray(), sb.ToString()); + } + + /// + /// Tests that the IsSealed property is set for properties that are + /// flagged as final. The ReflectionProperty class was not setting + /// this correctly. + /// + [Test] + public void ExpectedPropertiesFromProjectContent() + { + ProjectContentRegistry registry = new ProjectContentRegistry(); + IProjectContent mscorlibProjectContent = registry.Mscorlib; + IClass c = mscorlibProjectContent.GetClass("System.Exception"); + + List propertyNames = new List(); + foreach (IProperty p in c.Properties) { + if (p.IsVirtual && !p.IsSealed) { + propertyNames.Add(p.Name); + } + } + propertyNames.Sort(); + + List expectedPropertyNames = new List(); + expectedPropertyNames.Add("Data"); + expectedPropertyNames.Add("HelpLink"); + expectedPropertyNames.Add("Message"); + expectedPropertyNames.Add("Source"); + expectedPropertyNames.Add("StackTrace"); + + Assert.AreEqual(expectedPropertyNames.ToArray(), propertyNames.ToArray()); + } + + /// + /// Tests that the OverridePropertyCodeGenerator returns the correct + /// methods for the System.Exception type. + /// + [Test] + public void CodeGeneratorProperties() + { + ProjectContentRegistry registry = new ProjectContentRegistry(); + IProjectContent mscorlibProjectContent = registry.Mscorlib; + IClass exceptionClass = mscorlibProjectContent.GetClass("System.Exception"); + + DefaultProjectContent projectContent = new DefaultProjectContent(); + DefaultCompilationUnit unit = new DefaultCompilationUnit(projectContent); + DefaultClass c = new DefaultClass(unit, "MyException"); + c.BaseTypes.Add(new DefaultReturnType(exceptionClass)); + + MockProject project = new MockProject(); + ProjectService.CurrentProject = project; + + OverridePropertiesCodeGenerator codeGenerator = new OverridePropertiesCodeGenerator(); + codeGenerator.Initialize(c); + + List properties = new List(); + foreach (object o in codeGenerator.Content) { + properties.Add(o.ToString()); + } + + List expectedProperties = new List(); + expectedProperties.Add("Data"); + expectedProperties.Add("HelpLink"); + expectedProperties.Add("Message"); + expectedProperties.Add("Source"); + expectedProperties.Add("StackTrace"); + + Assert.AreEqual(expectedProperties.ToArray(), properties.ToArray()); + } + } +} + diff --git a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj index c3134764bf..00d9f90bc4 100644 --- a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj +++ b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj @@ -48,9 +48,14 @@ + + + + + @@ -59,6 +64,13 @@ + + + + + + + @@ -93,6 +105,10 @@ + + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} + ICSharpCode.TextEditor + {2748AD25-9C63-4E12-877B-4DCE96FBED54} ICSharpCode.SharpDevelop @@ -125,6 +141,7 @@ ICSharpCode.TextEditor.dll Always + diff --git a/src/Main/Base/Test/OverridableMethodsTestFixture.cs b/src/Main/Base/Test/OverridableMethodsTestFixture.cs new file mode 100644 index 0000000000..12ef407c81 --- /dev/null +++ b/src/Main/Base/Test/OverridableMethodsTestFixture.cs @@ -0,0 +1,134 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Tests.Utils; +using NUnit.Framework; + +namespace ICSharpCode.SharpDevelop.Tests +{ + /// + /// Tests the OverrideCompletionDataProvider GetOverridableMethods. + /// This method should be added to the IClass interface. + /// + [TestFixture] + public class OverridableMethodsTestFixture + { + MockClass c; + MockDefaultReturnType returnType; + List expectedMethods; + MockClass declaringType; + + [SetUp] + public void SetUp() + { + expectedMethods = new List(); + c = new MockClass("MyClass"); + declaringType = new MockClass("MyDeclaringType"); + returnType = new MockDefaultReturnType(); + c.DefaultReturnType = returnType; + } + + /// + /// Add one overridable method to the return type and this + /// should be returned in the list of overridable methods. + /// + [Test] + public void OneOverridableMethodReturned() + { + MockMethod method = new MockMethod("Run"); + method.DeclaringType = declaringType; + method.IsOverridable = true; + returnType.Methods.Add(method); + + expectedMethods.Add(method); + + IMethod[] methods = OverrideCompletionDataProvider.GetOverridableMethods(c); + + AssertAreMethodsEqual(expectedMethods, methods); + } + + /// + /// Make sure that an overridable method is not returned when + /// it is part of the class being considered. + /// + [Test] + public void OverridableMethodPartOfClass() + { + MockMethod method = new MockMethod("Run"); + method.DeclaringType = c; + method.IsOverridable = true; + returnType.Methods.Add(method); + + IMethod[] methods = OverrideCompletionDataProvider.GetOverridableMethods(c); + + AssertAreMethodsEqual(expectedMethods, methods); + } + + /// + /// An overridable but const method should not be returned. + /// + [Test] + public void OverridableConstMethodNotReturned() + { + MockMethod method = new MockMethod("Run"); + method.DeclaringType = declaringType; + method.IsOverridable = true; + method.IsConst = true; + returnType.Methods.Add(method); + + IMethod[] methods = OverrideCompletionDataProvider.GetOverridableMethods(c); + + AssertAreMethodsEqual(expectedMethods, methods); + } + + /// + /// An overridable but private method should not be returned. + /// + [Test] + public void OverridablePrivateMethodNotReturned() + { + MockMethod method = new MockMethod("Run"); + method.DeclaringType = declaringType; + method.IsOverridable = true; + method.IsPrivate = true; + returnType.Methods.Add(method); + + IMethod[] methods = OverrideCompletionDataProvider.GetOverridableMethods(c); + + AssertAreMethodsEqual(expectedMethods, methods); + } + + [Test] + [ExpectedException(typeof(ArgumentException))] + public void NullArgument() + { + OverrideCompletionDataProvider.GetOverridableMethods(null); + } + + void AssertAreMethodsEqual(List expectedMethods, IMethod[] methods) + { + // Get a list of expected method names. + List expectedMethodNames = new List(); + foreach (IMethod expectedMethod in expectedMethods) { + expectedMethodNames.Add(expectedMethod.Name); + } + + // Get a list of actual method names. + List methodNames = new List(); + foreach (IMethod m in methods) { + methodNames.Add(m.Name); + } + + // Compare the two arrays. + Assert.AreEqual(expectedMethodNames.ToArray(), methodNames.ToArray()); + } + } +} diff --git a/src/Main/Base/Test/OverridablePropertiesTestFixture.cs b/src/Main/Base/Test/OverridablePropertiesTestFixture.cs new file mode 100644 index 0000000000..e623014cc8 --- /dev/null +++ b/src/Main/Base/Test/OverridablePropertiesTestFixture.cs @@ -0,0 +1,134 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Tests.Utils; +using NUnit.Framework; + +namespace ICSharpCode.SharpDevelop.Tests +{ + /// + /// Tests the OverrideCompletionDataProvider GetOverridableProperties. + /// This property should be added to the IClass interface. + /// + [TestFixture] + public class OverridablePropertiesTestFixture + { + MockClass c; + MockDefaultReturnType returnType; + List expectedProperties; + MockClass declaringType; + + [SetUp] + public void SetUp() + { + expectedProperties = new List(); + c = new MockClass("MyClass"); + declaringType = new MockClass("MyDeclaringType"); + returnType = new MockDefaultReturnType(); + c.DefaultReturnType = returnType; + } + + /// + /// Add one overridable property to the return type and this + /// should be returned in the list of overridable properties. + /// + [Test] + public void OneOverridablePropertyReturned() + { + MockProperty property = new MockProperty("IsRunning"); + property.DeclaringType = declaringType; + property.IsOverridable = true; + returnType.Properties.Add(property); + + expectedProperties.Add(property); + + IProperty[] properties = OverrideCompletionDataProvider.GetOverridableProperties(c); + + AssertArePropertiesEqual(expectedProperties, properties); + } + + /// + /// Make sure that an overridable property is not returned when + /// it is part of the class being considered. + /// + [Test] + public void OverridablePropertyPartOfClass() + { + MockProperty property = new MockProperty("IsRunning"); + property.DeclaringType = c; + property.IsOverridable = true; + returnType.Properties.Add(property); + + IProperty[] properties = OverrideCompletionDataProvider.GetOverridableProperties(c); + + AssertArePropertiesEqual(expectedProperties, properties); + } + + /// + /// An overridable but const property should not be returned. + /// + [Test] + public void OverridableConstPropertyNotReturned() + { + MockProperty property = new MockProperty("IsRunning"); + property.DeclaringType = declaringType; + property.IsOverridable = true; + property.IsConst = true; + returnType.Properties.Add(property); + + IProperty[] properties = OverrideCompletionDataProvider.GetOverridableProperties(c); + + AssertArePropertiesEqual(expectedProperties, properties); + } + + /// + /// An overridable but private property should not be returned. + /// + [Test] + public void OverridablePrivatePropertyNotReturned() + { + MockProperty property = new MockProperty("Run"); + property.DeclaringType = declaringType; + property.IsOverridable = true; + property.IsPrivate = true; + returnType.Properties.Add(property); + + IProperty[] properties = OverrideCompletionDataProvider.GetOverridableProperties(c); + + AssertArePropertiesEqual(expectedProperties, properties); + } + + [Test] + [ExpectedException(typeof(ArgumentException))] + public void NullArgument() + { + OverrideCompletionDataProvider.GetOverridableProperties(null); + } + + void AssertArePropertiesEqual(List expectedProperties, IProperty[] properties) + { + // Get a list of expected property names. + List expectedPropertyNames = new List(); + foreach (IProperty expectedProperty in expectedProperties) { + expectedPropertyNames.Add(expectedProperty.Name); + } + + // Get a list of actual property names. + List propertyNames = new List(); + foreach (IProperty p in properties) { + propertyNames.Add(p.Name); + } + + // Compare the two arrays. + Assert.AreEqual(expectedPropertyNames.ToArray(), propertyNames.ToArray()); + } + } +} diff --git a/src/Main/Base/Test/Utils/MockAmbience.cs b/src/Main/Base/Test/Utils/MockAmbience.cs new file mode 100644 index 0000000000..f9c760d9d9 --- /dev/null +++ b/src/Main/Base/Test/Utils/MockAmbience.cs @@ -0,0 +1,87 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.SharpDevelop.Tests.Utils +{ + /// + /// Mock Ambience class. + /// + public class MockAmbience : AbstractAmbience + { + public MockAmbience() + { + } + + public override string Convert(ModifierEnum modifier) + { + return String.Empty; + } + + public override string Convert(IClass c) + { + return String.Empty; + } + + public override string ConvertEnd(IClass c) + { + return String.Empty; + } + + public override string Convert(IField c) + { + return String.Empty; + } + + public override string Convert(IProperty property) + { + return property.Name; + } + + public override string Convert(IEvent e) + { + return String.Empty; + } + + public override string Convert(IMethod m) + { + return m.Name; + } + + public override string ConvertEnd(IMethod m) + { + return String.Empty; + } + + public override string Convert(IParameter param) + { + return String.Empty; + } + + public override string Convert(IReturnType returnType) + { + return String.Empty; + } + + public override string WrapAttribute(string attribute) + { + return String.Empty; + } + + public override string WrapComment(string comment) + { + return String.Empty; + } + + public override string GetIntrinsicTypeName(string dotNetTypeName) + { + return String.Empty; + } + } +} diff --git a/src/Main/Base/Test/Utils/MockClass.cs b/src/Main/Base/Test/Utils/MockClass.cs new file mode 100644 index 0000000000..d627c106e3 --- /dev/null +++ b/src/Main/Base/Test/Utils/MockClass.cs @@ -0,0 +1,354 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.SharpDevelop.Dom; +using System; +using System.Collections.Generic; + +namespace ICSharpCode.SharpDevelop.Tests.Utils +{ + /// + /// Dummy class that implements the IClass interface. The + /// only property this mock class implements is the DefaultReturnType + /// property. + /// + public class MockClass : IClass + { + IReturnType returnType; + string qualifiedName = String.Empty; + + public MockClass(string qualifiedName) + { + this.qualifiedName = qualifiedName; + } + + public string FullyQualifiedName { + get { + return qualifiedName; + } + set { + qualifiedName = value; + } + } + + public IReturnType DefaultReturnType { + get { + return returnType; + } + set { + returnType = value; + } + } + + public string DotNetName { + get { + throw new NotImplementedException(); + } + } + + public string Name { + get { + throw new NotImplementedException(); + } + } + + public string Namespace { + get { + throw new NotImplementedException(); + } + } + + public ClassType ClassType { + get { + throw new NotImplementedException(); + } + } + + public IProjectContent ProjectContent { + get { + throw new NotImplementedException(); + } + } + + public ICompilationUnit CompilationUnit { + get { + throw new NotImplementedException(); + } + } + + public DomRegion Region { + get { + throw new NotImplementedException(); + } + } + + public DomRegion BodyRegion { + get { + throw new NotImplementedException(); + } + } + + public List BaseTypes { + get { + throw new NotImplementedException(); + } + } + + public List InnerClasses { + get { + throw new NotImplementedException(); + } + } + + public List Fields { + get { + throw new NotImplementedException(); + } + } + + public List Properties { + get { + throw new NotImplementedException(); + } + } + + public List Methods { + get { + throw new NotImplementedException(); + } + } + + public List Events { + get { + throw new NotImplementedException(); + } + } + + public IList TypeParameters { + get { + throw new NotImplementedException(); + } + } + + public IEnumerable ClassInheritanceTree { + get { + throw new NotImplementedException(); + } + } + + public IClass BaseClass { + get { + throw new NotImplementedException(); + } + } + + public IReturnType BaseType { + get { + throw new NotImplementedException(); + } + } + + public bool HasPublicOrInternalStaticMembers { + get { + throw new NotImplementedException(); + } + } + + public bool HasExtensionMethods { + get { + throw new NotImplementedException(); + } + } + + public bool IsPartial { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public IClass DeclaringType { + get { + throw new NotImplementedException(); + } + } + + public ModifierEnum Modifiers { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public IList Attributes { + get { + throw new NotImplementedException(); + } + } + + public string Documentation { + get { + throw new NotImplementedException(); + } + } + + public bool IsAbstract { + get { + throw new NotImplementedException(); + } + } + + public bool IsSealed { + get { + throw new NotImplementedException(); + } + } + + public bool IsStatic { + get { + throw new NotImplementedException(); + } + } + + public bool IsConst { + get { + throw new NotImplementedException(); + } + } + + public bool IsVirtual { + get { + throw new NotImplementedException(); + } + } + + public bool IsPublic { + get { + throw new NotImplementedException(); + } + } + + public bool IsProtected { + get { + throw new NotImplementedException(); + } + } + + public bool IsPrivate { + get { + throw new NotImplementedException(); + } + } + + public bool IsInternal { + get { + throw new NotImplementedException(); + } + } + + public bool IsReadonly { + get { + throw new NotImplementedException(); + } + } + + public bool IsProtectedAndInternal { + get { + throw new NotImplementedException(); + } + } + + public bool IsProtectedOrInternal { + get { + throw new NotImplementedException(); + } + } + + public bool IsOverride { + get { + throw new NotImplementedException(); + } + } + + public bool IsOverridable { + get { + throw new NotImplementedException(); + } + } + + public bool IsNew { + get { + throw new NotImplementedException(); + } + } + + public bool IsSynthetic { + get { + throw new NotImplementedException(); + } + } + + public object UserData { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public IReturnType GetBaseType(int index) + { + throw new NotImplementedException(); + } + + public IClass GetCompoundClass() + { + throw new NotImplementedException(); + } + + public IClass GetInnermostClass(int caretLine, int caretColumn) + { + throw new NotImplementedException(); + } + + public List GetAccessibleTypes(IClass callingClass) + { + throw new NotImplementedException(); + } + + public IMember SearchMember(string memberName, LanguageProperties language) + { + throw new NotImplementedException(); + } + + public bool IsTypeInInheritanceTree(IClass possibleBaseClass) + { + throw new NotImplementedException(); + } + + public bool IsAccessible(IClass callingClass, bool isClassInInheritanceTree) + { + throw new NotImplementedException(); + } + + public bool MustBeShown(IClass callingClass, bool showStatic, bool isClassInInheritanceTree) + { + throw new NotImplementedException(); + } + + public int CompareTo(object obj) + { + throw new NotImplementedException(); + } + + } +} diff --git a/src/Main/Base/Test/Utils/MockDecoration.cs b/src/Main/Base/Test/Utils/MockDecoration.cs new file mode 100644 index 0000000000..a049f9a78c --- /dev/null +++ b/src/Main/Base/Test/Utils/MockDecoration.cs @@ -0,0 +1,25 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.SharpDevelop.Tests.Utils +{ + public class MockDecoration : AbstractDecoration + { + public MockDecoration() : base(null) + { + } + + public override string DocumentationTag { + get { + return String.Empty; + } + } + } +} diff --git a/src/Main/Base/Test/Utils/MockDefaultReturnType.cs b/src/Main/Base/Test/Utils/MockDefaultReturnType.cs new file mode 100644 index 0000000000..f8300d0390 --- /dev/null +++ b/src/Main/Base/Test/Utils/MockDefaultReturnType.cs @@ -0,0 +1,137 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.SharpDevelop.Dom; +using System; +using System.Collections.Generic; + +namespace ICSharpCode.SharpDevelop.Tests.Utils +{ + public class MockDefaultReturnType : IReturnType + { + List methods = new List(); + List properties = new List(); + + public MockDefaultReturnType() + { + } + + /// + /// Gets the method list directly. Only available in the + /// mock default return type class. + /// + public List Methods { + get { + return methods; + } + } + + /// + /// Gets the property list directly. Only available in the + /// mock default return type class. + /// + public List Properties { + get { + return properties; + } + } + + public string FullyQualifiedName { + get { + throw new NotImplementedException(); + } + } + + public string Name { + get { + throw new NotImplementedException(); + } + } + + public string Namespace { + get { + throw new NotImplementedException(); + } + } + + public string DotNetName { + get { + throw new NotImplementedException(); + } + } + + public int TypeParameterCount { + get { + throw new NotImplementedException(); + } + } + + public bool IsDefaultReturnType { + get { + throw new NotImplementedException(); + } + } + + public bool IsArrayReturnType { + get { + throw new NotImplementedException(); + } + } + + public bool IsGenericReturnType { + get { + throw new NotImplementedException(); + } + } + + public bool IsConstructedReturnType { + get { + throw new NotImplementedException(); + } + } + + public IClass GetUnderlyingClass() + { + throw new NotImplementedException(); + } + + public List GetMethods() + { + return methods; + } + + public List GetProperties() + { + return properties; + } + + public List GetFields() + { + throw new NotImplementedException(); + } + + public List GetEvents() + { + throw new NotImplementedException(); + } + + public ArrayReturnType CastToArrayReturnType() + { + throw new NotImplementedException(); + } + + public GenericReturnType CastToGenericReturnType() + { + throw new NotImplementedException(); + } + + public ConstructedReturnType CastToConstructedReturnType() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Main/Base/Test/Utils/MockMethod.cs b/src/Main/Base/Test/Utils/MockMethod.cs new file mode 100644 index 0000000000..5cea0882bd --- /dev/null +++ b/src/Main/Base/Test/Utils/MockMethod.cs @@ -0,0 +1,276 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.SharpDevelop.Tests.Utils +{ + public class MockMethod : IMethod + { + string name = String.Empty; + bool overridable; + bool isConst; + bool isPrivate; + IClass declaringType; + + public MockMethod(string name) + { + this.name = name; + } + + public IList TypeParameters { + get { + throw new NotImplementedException(); + } + } + + public bool IsConstructor { + get { + throw new NotImplementedException(); + } + } + + public IList Parameters { + get { + throw new NotImplementedException(); + } + } + + public bool IsExtensionMethod { + get { + throw new NotImplementedException(); + } + } + + public string FullyQualifiedName { + get { + throw new NotImplementedException(); + } + } + + public IReturnType DeclaringTypeReference { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public DomRegion Region { + get { + throw new NotImplementedException(); + } + } + + public string Name { + get { + return name; + } + } + + public string Namespace { + get { + throw new NotImplementedException(); + } + } + + public string DotNetName { + get { + throw new NotImplementedException(); + } + } + + public IReturnType ReturnType { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public DomRegion BodyRegion { + get { + throw new NotImplementedException(); + } + } + + public IList InterfaceImplementations { + get { + throw new NotImplementedException(); + } + } + + public IClass DeclaringType { + get { + return declaringType; + } + set { + declaringType = value; + } + } + + public ModifierEnum Modifiers { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public IList Attributes { + get { + throw new NotImplementedException(); + } + } + + public string Documentation { + get { + throw new NotImplementedException(); + } + } + + public bool IsAbstract { + get { + throw new NotImplementedException(); + } + } + + public bool IsSealed { + get { + throw new NotImplementedException(); + } + } + + public bool IsStatic { + get { + throw new NotImplementedException(); + } + } + + public bool IsConst { + get { + return isConst; + } + set { + isConst = value; + } + } + + public bool IsVirtual { + get { + throw new NotImplementedException(); + } + } + + public bool IsPublic { + get { + throw new NotImplementedException(); + } + } + + public bool IsProtected { + get { + throw new NotImplementedException(); + } + } + + public bool IsPrivate { + get { + return isPrivate; + } + set { + isPrivate = value; + } + } + + public bool IsInternal { + get { + throw new NotImplementedException(); + } + } + + public bool IsReadonly { + get { + throw new NotImplementedException(); + } + } + + public bool IsProtectedAndInternal { + get { + throw new NotImplementedException(); + } + } + + public bool IsProtectedOrInternal { + get { + throw new NotImplementedException(); + } + } + + public bool IsOverride { + get { + throw new NotImplementedException(); + } + } + + public bool IsOverridable { + get { + return overridable; + } + set { + overridable = value; + } + } + + public bool IsNew { + get { + throw new NotImplementedException(); + } + } + + public bool IsSynthetic { + get { + throw new NotImplementedException(); + } + } + + public object UserData { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public bool IsAccessible(IClass callingClass, bool isClassInInheritanceTree) + { + throw new NotImplementedException(); + } + + public bool MustBeShown(IClass callingClass, bool showStatic, bool isClassInInheritanceTree) + { + throw new NotImplementedException(); + } + + public int CompareTo(object obj) + { + throw new NotImplementedException(); + } + + public object Clone() + { + throw new NotImplementedException(); + } + + } +} diff --git a/src/Main/Base/Test/Utils/MockProject.cs b/src/Main/Base/Test/Utils/MockProject.cs new file mode 100644 index 0000000000..6992ab7253 --- /dev/null +++ b/src/Main/Base/Test/Utils/MockProject.cs @@ -0,0 +1,30 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Dom.CSharp; +using ICSharpCode.SharpDevelop.Project; + +namespace ICSharpCode.SharpDevelop.Tests.Utils +{ + /// + /// Mocks IProject class that returns a dummy ambience. + /// + public class MockProject : AbstractProject + { + public MockProject() + { + } + + public override IAmbience Ambience { + get { + return new MockAmbience(); + } + } + } +} diff --git a/src/Main/Base/Test/Utils/MockProperty.cs b/src/Main/Base/Test/Utils/MockProperty.cs new file mode 100644 index 0000000000..37afcc370c --- /dev/null +++ b/src/Main/Base/Test/Utils/MockProperty.cs @@ -0,0 +1,294 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.SharpDevelop.Tests.Utils +{ + public class MockProperty : IProperty + { + bool overridable; + bool isConst; + bool isPrivate; + IClass declaringType; + string name = String.Empty; + + public MockProperty(string name) + { + this.name = name; + } + + public DomRegion GetterRegion { + get { + throw new NotImplementedException(); + } + } + + public DomRegion SetterRegion { + get { + throw new NotImplementedException(); + } + } + + public bool CanGet { + get { + throw new NotImplementedException(); + } + } + + public bool CanSet { + get { + throw new NotImplementedException(); + } + } + + public bool IsIndexer { + get { + throw new NotImplementedException(); + } + } + + public IList Parameters { + get { + throw new NotImplementedException(); + } + } + + public bool IsExtensionMethod { + get { + throw new NotImplementedException(); + } + } + + public string FullyQualifiedName { + get { + throw new NotImplementedException(); + } + } + + public IReturnType DeclaringTypeReference { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public DomRegion Region { + get { + throw new NotImplementedException(); + } + } + + public string Name { + get { + return name; + } + } + + public string Namespace { + get { + throw new NotImplementedException(); + } + } + + public string DotNetName { + get { + throw new NotImplementedException(); + } + } + + public IReturnType ReturnType { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public DomRegion BodyRegion { + get { + throw new NotImplementedException(); + } + } + + public IList InterfaceImplementations { + get { + throw new NotImplementedException(); + } + } + + public IClass DeclaringType { + get { + return declaringType; + } + set { + declaringType = value; + } + } + + public ModifierEnum Modifiers { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public IList Attributes { + get { + throw new NotImplementedException(); + } + } + + public string Documentation { + get { + throw new NotImplementedException(); + } + } + + public bool IsAbstract { + get { + throw new NotImplementedException(); + } + } + + public bool IsSealed { + get { + throw new NotImplementedException(); + } + } + + public bool IsStatic { + get { + throw new NotImplementedException(); + } + } + + public bool IsConst { + get { + return isConst; + } + set { + isConst = value; + } + } + + public bool IsVirtual { + get { + throw new NotImplementedException(); + } + } + + public bool IsPublic { + get { + throw new NotImplementedException(); + } + } + + public bool IsProtected { + get { + throw new NotImplementedException(); + } + } + + public bool IsPrivate { + get { + return isPrivate; + } + set { + isPrivate = value; + } + } + + public bool IsInternal { + get { + throw new NotImplementedException(); + } + } + + public bool IsReadonly { + get { + throw new NotImplementedException(); + } + } + + public bool IsProtectedAndInternal { + get { + throw new NotImplementedException(); + } + } + + public bool IsProtectedOrInternal { + get { + throw new NotImplementedException(); + } + } + + public bool IsOverride { + get { + throw new NotImplementedException(); + } + } + + public bool IsOverridable { + get { + return overridable; + } + set { + overridable = value; + } + } + + public bool IsNew { + get { + throw new NotImplementedException(); + } + } + + public bool IsSynthetic { + get { + throw new NotImplementedException(); + } + } + + public object UserData { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public bool IsAccessible(IClass callingClass, bool isClassInInheritanceTree) + { + throw new NotImplementedException(); + } + + public bool MustBeShown(IClass callingClass, bool showStatic, bool isClassInInheritanceTree) + { + throw new NotImplementedException(); + } + + public int CompareTo(object obj) + { + throw new NotImplementedException(); + } + + public object Clone() + { + throw new NotImplementedException(); + } + + } +} diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/DomPersistence.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/DomPersistence.cs index 5873779b3b..87e3d0b471 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/DomPersistence.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/DomPersistence.cs @@ -20,7 +20,7 @@ namespace ICSharpCode.SharpDevelop.Dom { public const long FileMagic = 0x11635233ED2F428C; public const long IndexFileMagic = 0x11635233ED2F427D; - public const short FileVersion = 9; + public const short FileVersion = 10; ProjectContentRegistry registry; string cacheDirectory; diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionMethod.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionMethod.cs index 861f400f0d..5e91e63780 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionMethod.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionMethod.cs @@ -65,6 +65,9 @@ namespace ICSharpCode.SharpDevelop.Dom.ReflectionLayer if (methodBase.IsAbstract) { modifiers |= ModifierEnum.Abstract; } + if (methodBase.IsFinal) { + modifiers |= ModifierEnum.Sealed; + } this.Modifiers = modifiers; } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionProperty.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionProperty.cs index 4a2a3ce0b7..2392022fc5 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionProperty.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionProperty.cs @@ -71,7 +71,9 @@ namespace ICSharpCode.SharpDevelop.Dom.ReflectionLayer if (methodBase.IsAbstract) { modifiers |= ModifierEnum.Abstract; } - + if (methodBase.IsFinal) { + modifiers |= ModifierEnum.Sealed; + } } else { // assume public property, if no methodBase could be get. modifiers = ModifierEnum.Public; }