Skip to content

Commit 6fad2bf

Browse files
authored
1 parent 052b62a commit 6fad2bf

File tree

4 files changed

+121
-17
lines changed

4 files changed

+121
-17
lines changed

mdoc/Mono.Documentation/Util/AttachedEntitiesHelper.cs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ private static IEnumerable<AttachedPropertyReference> GetAttachedProperties(Type
114114
if (IsAttachedProperty(field, methods))
115115
yield return new AttachedPropertyReference(field);
116116
}
117+
118+
foreach (var property in type.Properties.Where(t => t.PropertyType.FullName == Consts.DependencyPropertyFullName
119+
|| t.PropertyType.FullName == Consts.DependencyPropertyFullNameXaml))
120+
{
121+
if (IsAttachedProperty(property, methods))
122+
yield return new AttachedPropertyReference(property);
123+
}
117124
}
118125

119126
private static bool IsAttachedProperty(FieldDefinition field, Dictionary<string, IEnumerable<MethodDefinition>> methods)
@@ -126,8 +133,8 @@ private static bool IsAttachedProperty(FieldDefinition field, Dictionary<string,
126133
var getMethodName = $"Get{propertyName}";
127134
var setMethodName = $"Set{propertyName}";
128135

129-
var hasExistingProperty = field?.DeclaringType?.Properties.Any (p => p.Name.Equals (propertyName, System.StringComparison.Ordinal) && ChkPropertyVisible(p));
130-
var hasExistingField = field?.DeclaringType?.Fields.Any (f => f.Name.Equals (propertyName, System.StringComparison.Ordinal) && ChkFieldVisible(f));
136+
var hasExistingProperty = field?.DeclaringType?.Properties.Any (p => p.Name.Equals (propertyName, System.StringComparison.Ordinal) && GetCheckVisible(p.Resolve()));
137+
var hasExistingField = field?.DeclaringType?.Fields.Any (f => f.Name.Equals (propertyName, System.StringComparison.Ordinal) && GetCheckVisible(f.Resolve()));
131138

132139
return !hasExistingProperty.IsTrue () && !hasExistingField.IsTrue () &&
133140
// Class X has a static field of type DependencyProperty [Name]Property
@@ -140,6 +147,29 @@ private static bool IsAttachedProperty(FieldDefinition field, Dictionary<string,
140147
&& ((methods.ContainsKey(getMethodName) && methods[getMethodName].Any(IsAttachedPropertyGetMethod))
141148
|| (methods.ContainsKey(setMethodName) && methods[setMethodName].Any(IsAttachedPropertySetMethod)));
142149

150+
}
151+
152+
private static bool IsAttachedProperty(PropertyDefinition property, Dictionary<string, IEnumerable<MethodDefinition>> methods)
153+
{
154+
155+
if (!property.Name.EndsWith(PropertyConst, StringComparison.Ordinal))
156+
return false;
157+
var propertyName = GetPropertyName(property.Name);
158+
var getMethodName = $"Get{propertyName}";
159+
var setMethodName = $"Set{propertyName}";
160+
161+
var hasExistingProperty = property?.DeclaringType?.Properties.Any(p => p.Name.Equals(propertyName, System.StringComparison.Ordinal) && GetCheckVisible(p.Resolve()));
162+
var hasExistingField = property?.DeclaringType?.Fields.Any(f => f.Name.Equals(propertyName, System.StringComparison.Ordinal) && GetCheckVisible(f.Resolve()));
163+
164+
return !hasExistingProperty.IsTrue() && !hasExistingField.IsTrue() &&
165+
// Class X has a static field of type DependencyProperty [Name]Property
166+
(property.PropertyType.Name == Consts.DependencyPropertyFullName || property.PropertyType.FullName == Consts.DependencyPropertyFullNameXaml)
167+
168+
169+
// Class X also has static methods with the following names: Get[Name] and Set[Name]
170+
&& ((methods.ContainsKey(getMethodName) && methods[getMethodName].Any(IsAttachedPropertyGetMethod))
171+
|| (methods.ContainsKey(setMethodName) && methods[setMethodName].Any(IsAttachedPropertySetMethod)));
172+
143173
}
144174

145175
private static bool IsAttachedPropertyGetMethod(MethodDefinition method)
@@ -180,6 +210,19 @@ private static bool IsAssignableTo(TypeReference type, string targetTypeName)
180210
return type.FullName == targetTypeName || IsAssignableTo(typeDefenition.BaseType, targetTypeName);
181211
}
182212

213+
private static bool GetCheckVisible(IMemberDefinition member)
214+
{
215+
if (member == null)
216+
throw new ArgumentNullException("member");
217+
PropertyDefinition prop = member as PropertyDefinition;
218+
if (prop != null)
219+
return ChkPropertyVisible(prop);
220+
FieldDefinition field = member as FieldDefinition;
221+
if (field != null)
222+
return ChkFieldVisible(field);
223+
return false;
224+
}
225+
183226
private static bool ChkPropertyVisible(PropertyDefinition property)
184227
{
185228
MethodDefinition method;

mdoc/Mono.Documentation/Util/AttachedPropertyDefinition.cs

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,84 @@ namespace Mono.Documentation.Util
66
public class AttachedPropertyDefinition : AttachedPropertyReference, IMemberDefinition
77
{
88
private readonly FieldDefinition fieldDefinition;
9+
private readonly PropertyDefinition propertyDefinition;
10+
private bool isAttachedField;
911

1012
public AttachedPropertyDefinition(FieldDefinition fieldDefinition, MetadataToken metadataToken) : base(fieldDefinition)
1113
{
1214
this.fieldDefinition = fieldDefinition;
1315
MetadataToken = metadataToken;
16+
isAttachedField = true;
17+
}
18+
19+
public AttachedPropertyDefinition(PropertyDefinition propertyDefinition, MetadataToken metadataToken) : base(propertyDefinition)
20+
{
21+
this.propertyDefinition = propertyDefinition;
22+
MetadataToken = metadataToken;
1423
}
1524

1625
public MemberReference GetMethod
1726
{
18-
get => this.DeclaringType.GetMember(
19-
$"Get{AttachedEntitiesHelper.GetPropertyName(fieldDefinition.Name)}",
20-
m => (m as MethodReference)?.Parameters.Count == 1);
27+
get =>
28+
isAttachedField ?
29+
this.DeclaringType.GetMember(
30+
$"Get{AttachedEntitiesHelper.GetPropertyName(fieldDefinition.Name)}",
31+
m => (m as MethodReference)?.Parameters.Count == 1)
32+
:
33+
this.DeclaringType.GetMember(
34+
$"Get{AttachedEntitiesHelper.GetPropertyName(propertyDefinition.Name)}",
35+
m => (m as MethodReference)?.Parameters.Count == 1);
2136
}
2237
public MemberReference SetMethod
2338
{
24-
get => this.DeclaringType.GetMember(
25-
$"Set{AttachedEntitiesHelper.GetPropertyName(fieldDefinition.Name)}",
26-
m => (m as MethodReference)?.Parameters.Count == 2);
39+
get =>
40+
isAttachedField ?
41+
this.DeclaringType.GetMember(
42+
$"Set{AttachedEntitiesHelper.GetPropertyName(fieldDefinition.Name)}",
43+
m => (m as MethodReference)?.Parameters.Count == 2)
44+
:
45+
this.DeclaringType.GetMember(
46+
$"Set{AttachedEntitiesHelper.GetPropertyName(propertyDefinition.Name)}",
47+
m => (m as MethodReference)?.Parameters.Count == 2);
2748
}
2849

29-
public Collection<CustomAttribute> CustomAttributes => fieldDefinition.CustomAttributes;
30-
public bool HasCustomAttributes => fieldDefinition.HasCustomAttributes;
50+
public Collection<CustomAttribute> CustomAttributes => isAttachedField ? fieldDefinition.CustomAttributes : propertyDefinition.CustomAttributes;
51+
public bool HasCustomAttributes => isAttachedField ? fieldDefinition.HasCustomAttributes : propertyDefinition.HasCustomAttributes;
3152

3253
public bool IsSpecialName
3354
{
34-
get { return fieldDefinition.IsSpecialName; }
35-
set { fieldDefinition.IsSpecialName = value; }
55+
get { return isAttachedField ? fieldDefinition.IsSpecialName : propertyDefinition.IsSpecialName; }
56+
set
57+
{
58+
if (isAttachedField)
59+
fieldDefinition.IsSpecialName = value;
60+
else
61+
propertyDefinition.IsSpecialName = value;
62+
}
3663
}
3764

3865
public bool IsRuntimeSpecialName
3966
{
40-
get { return fieldDefinition.IsRuntimeSpecialName; }
41-
set { fieldDefinition.IsRuntimeSpecialName = value; }
67+
get { return isAttachedField ? fieldDefinition.IsRuntimeSpecialName : propertyDefinition.IsRuntimeSpecialName; }
68+
set
69+
{
70+
if (isAttachedField)
71+
fieldDefinition.IsRuntimeSpecialName = value;
72+
else
73+
propertyDefinition.IsRuntimeSpecialName = value;
74+
}
4275
}
4376

4477
public new TypeDefinition DeclaringType
4578
{
46-
get { return fieldDefinition.DeclaringType; }
47-
set { fieldDefinition.DeclaringType = value; }
79+
get { return isAttachedField ? fieldDefinition.DeclaringType : propertyDefinition.DeclaringType; }
80+
set
81+
{
82+
if (isAttachedField)
83+
fieldDefinition.DeclaringType = value;
84+
else
85+
propertyDefinition.DeclaringType = value;
86+
}
4887
}
4988
}
5089
}

mdoc/Mono.Documentation/Util/AttachedPropertyReference.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,23 @@ namespace Mono.Documentation.Util
55
public class AttachedPropertyReference : FieldReference
66
{
77
private readonly FieldDefinition fieldDefinition;
8+
private readonly PropertyDefinition propertyDefinition;
89
private AttachedPropertyDefinition definition;
910

1011
public AttachedPropertyReference(FieldDefinition fieldDefinition) : base(AttachedEntitiesHelper.GetPropertyName(fieldDefinition.Name), fieldDefinition.FieldType, fieldDefinition.DeclaringType)
1112
{
1213
this.fieldDefinition = fieldDefinition;
1314
}
1415

16+
public AttachedPropertyReference(PropertyDefinition propertyDefinition) : base(AttachedEntitiesHelper.GetPropertyName(propertyDefinition.Name), propertyDefinition.PropertyType, propertyDefinition.DeclaringType)
17+
{
18+
this.propertyDefinition = propertyDefinition;
19+
}
20+
1521
protected override IMemberDefinition ResolveDefinition()
1622
{
1723
return definition ??
18-
(definition = new AttachedPropertyDefinition(fieldDefinition, MetadataToken));
24+
(definition = fieldDefinition != null ? new AttachedPropertyDefinition(fieldDefinition, MetadataToken) : new AttachedPropertyDefinition(propertyDefinition, MetadataToken));
1925
}
2026
}
2127
}

mdoc/mdoc.Test/Enumeration/AttachedEntityTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ public void Test_AttachedProperty_Formatter_SetOnly()
7171
Assert.AreEqual(expected, def);
7272
}
7373

74+
[TestCase]
75+
public void Test_AttachedProperty_Property()
76+
{
77+
var type = GetTypeDef<AttachedPropertyTestClass>();
78+
Assert.AreEqual(1, type.Properties.Count(t => t.Name == "AttributeAttachProperty"));
79+
var list = AttachedEntitiesHelper.GetAttachedEntities(type);
80+
Assert.AreEqual("AttributeAttach", list.FirstOrDefault(t => t.Name == "AttributeAttach").Name);
81+
}
82+
7483
public class AttachedTestClassNoAttachedEntities { }
7584

7685
public class AttachedTestClass
@@ -92,5 +101,12 @@ public static void SetSomeSet(DependencyObject obj, bool val) { }
92101
public static bool GetSomeNotReadOnly(DependencyObject obj) { return false; }
93102
public static void SetSomeNotReadOnly(DependencyObject obj, bool val) { }
94103
}
104+
105+
public class AttachedPropertyTestClass
106+
{
107+
public DependencyProperty AttributeAttachProperty { get; set; }
108+
public static bool GetAttributeAttach(DependencyObject obj) { return false; }
109+
public static void SetAttributeAttach(DependencyObject obj, bool val) { }
110+
}
95111
}
96112
}

0 commit comments

Comments
 (0)