diff --git a/src/Main/Base/Test/ReflectionLayerTests.cs b/src/Main/Base/Test/ReflectionLayerTests.cs index 67aa7e0238..a7d13b06d0 100644 --- a/src/Main/Base/Test/ReflectionLayerTests.cs +++ b/src/Main/Base/Test/ReflectionLayerTests.cs @@ -259,27 +259,34 @@ namespace ICSharpCode.SharpDevelop.Tests public void TestMethod(string param) where V: K where K: IComparable {} public void GetIndex(T element) where T: IEquatable {} + + public int Property { get; protected set; } + public int ReadOnlyPropertyWithPrivateSetter { get; private set; } } protected abstract IClass GetClass(Type type); protected abstract IEnumerable GetAssemblyAttributes(Assembly assembly); + IClass testClass; + + [TestFixtureSetUp] + public void FixtureSetUp() + { + testClass = GetClass(typeof(TestClass<,>)); + } + [Test] - public void ReflectionParserTest() + public void TestClassTypeParameters() { - IClass c = GetClass(typeof(TestClass<,>)); - - CheckClass(c); + Assert.AreSame(testClass, testClass.TypeParameters[0].Class); + Assert.AreSame(testClass, testClass.TypeParameters[1].Class); + Assert.AreSame(testClass.TypeParameters[1], ((GenericReturnType)testClass.TypeParameters[0].Constraints[0]).TypeParameter); } - void CheckClass(IClass c) + [Test] + public void TestMethod() { - Assert.AreSame(c, c.TypeParameters[0].Class); - Assert.AreSame(c, c.TypeParameters[1].Class); - Assert.AreSame(c.TypeParameters[1], ((GenericReturnType)c.TypeParameters[0].Constraints[0]).TypeParameter); - - IMethod m = c.Methods.First(delegate(IMethod me) { return me.Name == "TestMethod"; }); - Assert.IsNotNull(m); + IMethod m = testClass.Methods.Single(me => me.Name == "TestMethod"); Assert.AreEqual("K", m.TypeParameters[0].Name); Assert.AreEqual("V", m.TypeParameters[1].Name); Assert.AreSame(m, m.TypeParameters[0].Method); @@ -288,9 +295,12 @@ namespace ICSharpCode.SharpDevelop.Tests Assert.AreEqual("IComparable", m.TypeParameters[0].Constraints[0].Name); GenericReturnType kConst = (GenericReturnType)m.TypeParameters[1].Constraints[0]; Assert.AreSame(m.TypeParameters[0], kConst.TypeParameter); - - m = c.Methods.First(delegate(IMethod me) { return me.Name == "GetIndex"; }); - Assert.IsNotNull(m); + } + + [Test] + public void GetIndex() + { + IMethod m = testClass.Methods.Single(me => me.Name == "GetIndex"); Assert.AreEqual("T", m.TypeParameters[0].Name); Assert.AreSame(m, m.TypeParameters[0].Method); @@ -301,6 +311,24 @@ namespace ICSharpCode.SharpDevelop.Tests Assert.AreSame(m.TypeParameters[0], grt.TypeParameter); } + [Test] + public void Property() + { + IProperty p = testClass.Properties.Single(pr => pr.Name == "Property"); + Assert.AreEqual(ModifierEnum.Public, p.Modifiers); + Assert.AreEqual(ModifierEnum.None, p.GetterModifiers); + Assert.AreEqual(ModifierEnum.Protected, p.SetterModifiers); + } + + [Test] + public void CannotSetReadOnlyProperty() + { + IProperty p = testClass.Properties.Single(pr => pr.Name == "ReadOnlyPropertyWithPrivateSetter"); + Assert.AreEqual(ModifierEnum.Public, p.Modifiers); + Assert.AreEqual(ModifierEnum.None, p.GetterModifiers); + Assert.IsFalse(p.CanSet); + } + [Test] public void AssemblyAttribute() { diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs index 7fef53065c..08d2ab675f 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs @@ -46,7 +46,7 @@ namespace ICSharpCode.SharpDevelop.Dom try { a.PositionalArguments.Add(ReflectionReturnType.Parse(pc, (string)o)); } catch (ReflectionTypeNameSyntaxError ex) { - LoggingService.Warn(ex); + LoggingService.Warn("parsing '" + o + "'", ex); a.PositionalArguments.Add(o); } } else { @@ -304,25 +304,7 @@ namespace ICSharpCode.SharpDevelop.Dom } foreach (PropertyDefinition property in type.Properties) { - if ((property.GetMethod != null && IsVisible(property.GetMethod.Attributes)) - || (property.SetMethod != null && IsVisible(property.SetMethod.Attributes))) - { - DefaultProperty p = new DefaultProperty(this, property.Name); - if (this.ClassType == ClassType.Interface) { - p.Modifiers = ModifierEnum.Public | ModifierEnum.Abstract; - } else { - p.Modifiers = TranslateModifiers(property); - } - p.ReturnType = CreateType(this.ProjectContent, this, property.PropertyType); - p.CanGet = property.GetMethod != null; - p.CanSet = property.SetMethod != null; - if (p.Name == defaultMemberName) { - p.IsIndexer = true; - } - AddParameters(p, property.Parameters); - AddAttributes(CompilationUnit.ProjectContent, p.Attributes, property.CustomAttributes); - Properties.Add(p); - } + AddProperty(defaultMemberName, property); } foreach (EventDefinition eventDef in type.Events) { @@ -349,6 +331,42 @@ namespace ICSharpCode.SharpDevelop.Dom } } + void AddProperty(string defaultMemberName, PropertyDefinition property) + { + if ((property.GetMethod != null && IsVisible(property.GetMethod.Attributes)) + || (property.SetMethod != null && IsVisible(property.SetMethod.Attributes))) + { + DefaultProperty p = new DefaultProperty(this, property.Name); + if (this.ClassType == ClassType.Interface) { + p.Modifiers = ModifierEnum.Public | ModifierEnum.Abstract; + } else { + p.Modifiers = TranslateModifiers(property); + } + p.ReturnType = CreateType(this.ProjectContent, this, property.PropertyType); + p.CanGet = property.GetMethod != null && IsVisible(property.GetMethod.Attributes); + p.CanSet = property.SetMethod != null && IsVisible(property.SetMethod.Attributes); + if (p.CanGet) + p.GetterModifiers = GetAccessorVisibility(p, property.GetMethod); + if (p.CanSet) + p.SetterModifiers = GetAccessorVisibility(p, property.SetMethod); + if (p.Name == defaultMemberName) { + p.IsIndexer = true; + } + AddParameters(p, property.Parameters); + AddAttributes(CompilationUnit.ProjectContent, p.Attributes, property.CustomAttributes); + Properties.Add(p); + } + } + + static ModifierEnum GetAccessorVisibility(IProperty p, MethodDefinition accessor) + { + ModifierEnum visibility = ModifierEnum.VisibilityMask & TranslateModifiers(accessor); + if (visibility == (p.Modifiers & ModifierEnum.VisibilityMask)) + return ModifierEnum.None; + else + return visibility; + } + void AddMethod(MethodDefinition method) { if (IsVisible(method.Attributes)) { diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs index 65231813b1..e0342c00ea 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs @@ -28,6 +28,7 @@ namespace ICSharpCode.SharpDevelop.Dom XmlDoc xmlDoc = new XmlDoc(); IUsing defaultImports; + bool isDisposed; public IUsing DefaultImports { get { @@ -223,6 +224,7 @@ namespace ICSharpCode.SharpDevelop.Dom public string GetXmlDocumentation(string memberTag) { + CheckNotDisposed(); string desc = xmlDoc.GetDocumentation(memberTag); if (desc != null) { return desc; @@ -241,6 +243,13 @@ namespace ICSharpCode.SharpDevelop.Dom public virtual void Dispose() { xmlDoc.Dispose(); + isDisposed = true; + } + + [Conditional("DEBUG")] + void CheckNotDisposed() + { + Debug.Assert(!isDisposed); } public void AddClassToNamespaceList(IClass addClass) @@ -588,6 +597,7 @@ namespace ICSharpCode.SharpDevelop.Dom protected IClass GetClassInternal(string typeName, int typeParameterCount, LanguageProperties language) { + CheckNotDisposed(); #if DEBUG if (System.Text.RegularExpressions.Regex.IsMatch (typeName, "`[0-9]+$")) Debug.Assert(false, "how did a Reflection type name get here?"); diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs index c6e3057a5b..02bab5041b 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs @@ -11,8 +11,10 @@ using System.Collections.Generic; namespace ICSharpCode.SharpDevelop.Dom { - public interface IProjectContent : IDisposable + public interface IProjectContent { + void Dispose(); + XmlDoc XmlDoc { get; } 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 e0056b3ab1..1393c35b98 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 = 22; + public const short FileVersion = 23; ProjectContentRegistry registry; string cacheDirectory; 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 2392022fc5..4d47b4210b 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionProperty.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionProperty.cs @@ -34,16 +34,17 @@ namespace ICSharpCode.SharpDevelop.Dom.ReflectionLayer } } - MethodInfo methodBase = null; + MethodInfo getterMethod = null; try { - methodBase = propertyInfo.GetGetMethod(true); + getterMethod = propertyInfo.GetGetMethod(true); } catch (Exception) {} - if (methodBase == null) { - try { - methodBase = propertyInfo.GetSetMethod(true); - } catch (Exception) {} - } + MethodInfo setterMethod = null; + try { + setterMethod = propertyInfo.GetSetMethod(true); + } catch (Exception) {} + + MethodInfo methodBase = getterMethod ?? setterMethod; ModifierEnum modifiers = ModifierEnum.None; if (methodBase != null) { @@ -78,6 +79,35 @@ namespace ICSharpCode.SharpDevelop.Dom.ReflectionLayer modifiers = ModifierEnum.Public; } this.Modifiers = modifiers; + if (getterMethod != null) { + ModifierEnum getterModifier = GetAccessorModifier(getterMethod); + if (getterModifier == ModifierEnum.Private) { + this.CanGet = false; + } else { + if (getterModifier != (modifiers & ModifierEnum.VisibilityMask)) + this.GetterModifiers = getterModifier; + } + } + if (setterMethod != null) { + ModifierEnum setterModifier = GetAccessorModifier(setterMethod); + if (setterModifier == ModifierEnum.Private) { + this.CanSet = false; + } else { + if (setterModifier != (modifiers & ModifierEnum.VisibilityMask)) + this.SetterModifiers = setterModifier; + } + } + } + + static ModifierEnum GetAccessorModifier(MethodInfo accessor) + { + if (accessor.IsPublic) { + return ModifierEnum.Public; + } else if (accessor.IsFamily || accessor.IsFamilyOrAssembly) { + return ModifierEnum.Protected; + } else { + return ModifierEnum.Private; // or internal, we don't care about that difference + } } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/XmlDoc.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/XmlDoc.cs index cc55e19d1c..8acff35573 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/XmlDoc.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/XmlDoc.cs @@ -254,7 +254,7 @@ namespace ICSharpCode.SharpDevelop.Dom static XmlDoc Load(string fileName, string cachePath, bool allowRedirect) { - //LoggingService.Debug("Loading XmlDoc for " + fileName); + LoggingService.Debug("Loading XmlDoc for " + fileName); XmlDoc doc; string cacheName = null; if (cachePath != null) {