diff options
author | Jeff Chen <59190910+JeffInChrist@users.noreply.github.com> | 2021-10-08 10:23:22 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-08 10:23:22 +0300 |
commit | d85a540dc66c137262f044ed4b9f82aa7bee9c1f (patch) | |
tree | af15344ed3ade49dffc83812f175e955b81250a8 | |
parent | fd9de0126df76cd7f72e4b987c85dd4cb5e1a54c (diff) |
Fixed issues of attached entities and the unique case of TargetProperty attached property. (#576)
* Fixed the issue of dual property const
* Added tests for attached entities and fix typos
* update
* update
* Switch to external WPF reference for build failure on macOS.
* Fixed attached events and dropped WPF
* Setting the test case of WPF conditionally on different platforms
* update
-rw-r--r-- | external/Windows/PresentationFramework.dll | bin | 0 -> 2098224 bytes | |||
-rw-r--r-- | mdoc/Consts.cs | 52 | ||||
-rw-r--r-- | mdoc/Mono.Documentation/Util/AttachedEntitiesHelper.cs | 43 | ||||
-rw-r--r-- | mdoc/mdoc.Test/Enumeration/AttachedEntityTests.cs | 85 | ||||
-rw-r--r-- | mdoc/mdoc.Test/mdoc.Test.csproj | 4 |
5 files changed, 131 insertions, 53 deletions
diff --git a/external/Windows/PresentationFramework.dll b/external/Windows/PresentationFramework.dll Binary files differnew file mode 100644 index 00000000..3d3f5d57 --- /dev/null +++ b/external/Windows/PresentationFramework.dll diff --git a/mdoc/Consts.cs b/mdoc/Consts.cs index 6439895e..20c362ca 100644 --- a/mdoc/Consts.cs +++ b/mdoc/Consts.cs @@ -1,41 +1,47 @@ using System; namespace Mono.Documentation { - public static class Consts - { - public static string MonoVersion = "5.8.4"; - public const string DocId = "DocId"; - public const string CppCli = "C++ CLI"; - public const string CppCx = "C++ CX"; - public const string CppWinRt = "C++ WINRT"; + public static class Consts + { + public static string MonoVersion = "5.8.4"; + public const string DocId = "DocId"; + public const string CppCli = "C++ CLI"; + public const string CppCx = "C++ CX"; + public const string CppWinRt = "C++ WINRT"; public const string CSharp = "C#"; public const string VbNet = "VB.NET"; - public const string DocIdLowCase = "docid"; - public const string VbNetLowCase = "vb.net"; - public const string CppCliLowCase = "c++/cli"; + public const string DocIdLowCase = "docid"; + public const string VbNetLowCase = "vb.net"; + public const string CppCliLowCase = "c++/cli"; public const string CppCxLowCase = "c++/cx"; - public const string CppWinRtLowCase = "c++/winrt"; - public const string Tab = " "; - public const string FSharp = "F#"; - public const string FSharpLowCase = "f#"; - public const string Javascript = "JavaScript"; - public const string JavascriptLowCase = "javascript"; + public const string CppWinRtLowCase = "c++/winrt"; + public const string Tab = " "; + public const string FSharp = "F#"; + public const string FSharpLowCase = "f#"; + public const string Javascript = "JavaScript"; + public const string JavascriptLowCase = "javascript"; - public const string DependencyPropertyFullName = "System.Windows.DependencyProperty"; + public const string DependencyPropertyFullName = "System.Windows.DependencyProperty"; public const string DependencyPropertyFullNameWindowsXaml = "Windows.UI.Xaml.DependencyProperty"; public const string DependencyPropertyFullNameMicrosoftXaml = "Microsoft.UI.Xaml.DependencyProperty"; public const string DependencyObjectFullName = "System.Windows.DependencyObject"; - public const string DependencyObjectFullNameXaml = "Windows.UI.Xaml.DependencyObject"; + public const string DependencyObjectFullNameWinRT = "Windows.UI.Xaml.DependencyObject"; + public const string DependencyObjectFullNameWinUI = "Microsoft.UI.Xaml.DependencyObject"; + + public const string RoutedEventFullName = "System.Windows.RoutedEvent"; + public const string RoutedEventFullNameWinRT = "Windows.UI.Xaml.RoutedEvent"; + public const string RoutedEventFullNameWinUI = "Microsoft.UI.Xaml.RoutedEvent"; + public const string DependencyPropertyFullNameIInputElement = "System.Windows.IInputElement"; public const string DependencyPropertyFullNameObject = "System.Object"; public const string VoidFullName = "System.Void"; - public const string RefTypeObsoleteString = "Types with embedded references are not supported in this version of your compiler."; - public const string FrameworksIndexFolderName = "FrameworksIndex"; - public const string CompilerGeneratedAttribute = "System.Runtime.CompilerServices.CompilerGeneratedAttribute"; - public const string CompilationMappingAttribute = "Microsoft.FSharp.Core.CompilationMappingAttribute"; + public const string RefTypeObsoleteString = "Types with embedded references are not supported in this version of your compiler."; + public const string FrameworksIndexFolderName = "FrameworksIndex"; + public const string CompilerGeneratedAttribute = "System.Runtime.CompilerServices.CompilerGeneratedAttribute"; + public const string CompilationMappingAttribute = "Microsoft.FSharp.Core.CompilationMappingAttribute"; public const string FrameworksIndex = "FrameworksIndex"; - public const string FrameworkAlternate = "FrameworkAlternate"; + public const string FrameworkAlternate = "FrameworkAlternate"; public const string Index = "Index"; public static bool CollapseInheritedInterfaces = true; diff --git a/mdoc/Mono.Documentation/Util/AttachedEntitiesHelper.cs b/mdoc/Mono.Documentation/Util/AttachedEntitiesHelper.cs index 02057c38..d8bb3970 100644 --- a/mdoc/Mono.Documentation/Util/AttachedEntitiesHelper.cs +++ b/mdoc/Mono.Documentation/Util/AttachedEntitiesHelper.cs @@ -32,9 +32,9 @@ namespace Mono.Documentation.Util { yield return attachedEventReference; } - foreach (var attachedEventProperty in GetAttachedProperties(type, methodsLookUpTable)) + foreach (var attachedPropertyReference in GetAttachedProperties(type, methodsLookUpTable)) { - yield return attachedEventProperty; + yield return attachedPropertyReference; } } @@ -62,7 +62,9 @@ namespace Mono.Documentation.Util var removeMethodName = $"Remove{GetEventName(field.Name)}Handler"; return // WPF implements attached events as routed events; the identifier to use for an event (RoutedEvent) is already defined by the WPF event system - IsAssignableTo(field.FieldType, "System.Windows.RoutedEvent") + (IsAssignableTo(field.FieldType, Consts.RoutedEventFullName) || + IsAssignableTo(field.FieldType, Consts.RoutedEventFullNameWinRT) || + IsAssignableTo(field.FieldType, Consts.RoutedEventFullNameWinUI)) && field.IsPublic && field.IsStatic && field.IsInitOnly @@ -90,9 +92,11 @@ namespace Mono.Documentation.Util return false; return // The first parameter is DependencyObject - IsAssignableTo(parameters[0].ParameterType, "System.Windows.DependencyObject") - - // The second parameter is the handler to add/remove + (IsAssignableTo(parameters[0].ParameterType, Consts.DependencyObjectFullName) ||
+ IsAssignableTo(parameters[0].ParameterType, Consts.DependencyObjectFullNameWinRT) ||
+ IsAssignableTo(parameters[0].ParameterType, Consts.DependencyObjectFullNameWinUI))
+
+ // The second parameter is the handler to add/remove
&& IsAttachedEventHandler(parameters[1].ParameterType); } @@ -130,12 +134,14 @@ namespace Mono.Documentation.Util // https://github.com/mono/api-doc-tools/issues/63#issuecomment-328995418 if (!field.Name.EndsWith(PropertyConst, StringComparison.Ordinal)) return false; - var propertyName = GetPropertyName(field.Name); + var propertyName = GetPropertyName(field.Name); var getMethodName = $"Get{propertyName}"; var setMethodName = $"Set{propertyName}"; - var hasExistingProperty = field?.DeclaringType?.Properties.Any (p => p.Name.Equals (propertyName, System.StringComparison.Ordinal) && GetCheckVisible(p.Resolve())); - var hasExistingField = field?.DeclaringType?.Fields.Any (f => f.Name.Equals (propertyName, System.StringComparison.Ordinal) && GetCheckVisible(f.Resolve())); + var hasDualPropertyConst = propertyName.EndsWith(PropertyConst, StringComparison.Ordinal); + var hasExistingProperty = field?.DeclaringType?.Properties.Any (p => p.Name.Equals (propertyName, StringComparison.Ordinal) && GetCheckVisible(p.Resolve())); + var hasExistingField = hasDualPropertyConst ? false : + field?.DeclaringType?.Fields.Any (f => f.Name.Equals (propertyName, StringComparison.Ordinal) && GetCheckVisible(f.Resolve())); return !hasExistingProperty.IsTrue () && !hasExistingField.IsTrue () && // Class X has a static field of type DependencyProperty [Name]Property @@ -145,7 +151,7 @@ namespace Mono.Documentation.Util && field.IsStatic && field.IsInitOnly - // Class X also has static methods with the following names: Get[Name] and Set[Name] + // Class X also has static methods with the following names: Get[Name] or Set[Name] && ((methods.ContainsKey(getMethodName) && methods[getMethodName].Any(IsAttachedPropertyGetMethod)) || (methods.ContainsKey(setMethodName) && methods[setMethodName].Any(IsAttachedPropertySetMethod))); @@ -160,8 +166,8 @@ namespace Mono.Documentation.Util var getMethodName = $"Get{propertyName}"; var setMethodName = $"Set{propertyName}"; - var hasExistingProperty = property?.DeclaringType?.Properties.Any(p => p.Name.Equals(propertyName, System.StringComparison.Ordinal) && GetCheckVisible(p.Resolve())); - var hasExistingField = property?.DeclaringType?.Fields.Any(f => f.Name.Equals(propertyName, System.StringComparison.Ordinal) && GetCheckVisible(f.Resolve())); + var hasExistingProperty = property?.DeclaringType?.Properties.Any(p => p.Name.Equals(propertyName, StringComparison.Ordinal) && GetCheckVisible(p.Resolve())); + var hasExistingField = property?.DeclaringType?.Fields.Any(f => f.Name.Equals(propertyName, StringComparison.Ordinal) && GetCheckVisible(f.Resolve())); return !hasExistingProperty.IsTrue() && !hasExistingField.IsTrue() &&
// Class X has a static field of type DependencyProperty [Name]Property
@@ -169,7 +175,7 @@ namespace Mono.Documentation.Util || property.PropertyType.FullName == Consts.DependencyPropertyFullNameMicrosoftXaml)
- // Class X also has static methods with the following names: Get[Name] and Set[Name]
+ // Class X also has static methods with the following names: Get[Name] or Set[Name]
&& ((methods.ContainsKey(getMethodName) && methods[getMethodName].Any(IsAttachedPropertyGetMethod)) || (methods.ContainsKey(setMethodName) && methods[setMethodName].Any(IsAttachedPropertySetMethod)));
@@ -183,7 +189,9 @@ namespace Mono.Documentation.Util // && IsAssignableTo(method.ReturnType, ""); // The Get method takes one argument of type DependencyObject(or something IsAssignableTo(DependencyObject), - && (IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullName) || IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullNameXaml)); + && (IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullName) || + IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullNameWinRT) ||
+ IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullNameWinUI)); } private static bool IsAttachedPropertySetMethod(MethodDefinition method) @@ -191,8 +199,11 @@ namespace Mono.Documentation.Util return method.Parameters.Count == 2// The Set method takes two arguments. // The first has type DependencyObject(or IsAssignableTo…), - && (IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullName) || IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullNameXaml) - || IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyPropertyFullNameIInputElement) || IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyPropertyFullNameObject)) + && (IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullName) || + IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullNameWinRT) ||
+ IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullNameWinUI) ||
+ IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyPropertyFullNameIInputElement) || + IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyPropertyFullNameObject)) // the second has type dp.PropertyType (or IsAssignableTo…).
// && IsAssignableTo(method.Parameters[1].ParameterType, "")
diff --git a/mdoc/mdoc.Test/Enumeration/AttachedEntityTests.cs b/mdoc/mdoc.Test/Enumeration/AttachedEntityTests.cs index 451cc49c..271aa81b 100644 --- a/mdoc/mdoc.Test/Enumeration/AttachedEntityTests.cs +++ b/mdoc/mdoc.Test/Enumeration/AttachedEntityTests.cs @@ -1,11 +1,8 @@ using NUnit.Framework; using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Mono.Documentation.Util; using Windows.UI.Xaml; +using Mono.Documentation.Util; using Mono.Documentation.Updater; using Mono.Documentation.Updater.Formatters; @@ -26,7 +23,7 @@ namespace mdoc.Test.Enumeration [TestCase] public void Test_AttachedProperty() { - var type = GetTypeDef<AttachedTestClass>(); + var type = GetTypeDef<AttachedPropertyTestClass>(); var list = AttachedEntitiesHelper.GetAttachedEntities(type); Assert.AreEqual(3, list.Count()); @@ -37,7 +34,7 @@ namespace mdoc.Test.Enumeration { string expected = "see GetSome, and SetSome"; - var type = GetTypeDef<AttachedTestClass>(); + var type = GetTypeDef<AttachedPropertyTestClass>(); var list = AttachedEntitiesHelper.GetAttachedEntities(type); MemberFormatter formatter = new CSharpMemberFormatter(); @@ -50,7 +47,7 @@ namespace mdoc.Test.Enumeration { string expected = "see GetSomeGet"; - var type = GetTypeDef<AttachedTestClass>(); + var type = GetTypeDef<AttachedPropertyTestClass>(); var list = AttachedEntitiesHelper.GetAttachedEntities(type); MemberFormatter formatter = new CSharpMemberFormatter(); @@ -63,7 +60,7 @@ namespace mdoc.Test.Enumeration { string expected = "see SetSomeSet"; - var type = GetTypeDef<AttachedTestClass>(); + var type = GetTypeDef<AttachedPropertyTestClass>(); var list = AttachedEntitiesHelper.GetAttachedEntities(type); MemberFormatter formatter = new CSharpMemberFormatter(); @@ -72,17 +69,56 @@ namespace mdoc.Test.Enumeration } [TestCase] - public void Test_AttachedProperty_Property() + public void Test_AttachedEntities() { - var type = GetTypeDef<AttachedPropertyTestClass>(); - Assert.AreEqual(1, type.Properties.Count(t => t.Name == "AttributeAttachProperty")); + var type = GetTypeDef<AttachedEntitiesTestClass>(); + Assert.IsTrue(type.Fields.Any(t => t.Name == "TestingEvent")); + Assert.IsTrue(type.Fields.Any(t => t.Name == "TargetProperty")); + Assert.IsTrue(type.Fields.Any(t => t.Name == "TargetPropertyProperty")); + Assert.IsTrue(type.Properties.Any(t => t.Name == "AttributeAttachProperty")); + + var list = AttachedEntitiesHelper.GetAttachedEntities(type);
+ Assert.AreEqual(4, list.Count()); + Assert.IsTrue(list.Any(t => t.Name == "Testing" && t is AttachedEventReference)); + Assert.IsTrue(list.Any(t => t.Name == "Target" && t is AttachedPropertyReference)); + Assert.IsTrue(list.Any(t => t.Name == "TargetProperty" && t is AttachedPropertyReference)); + Assert.IsTrue(list.Any(t => t.Name == "AttributeAttach" && t is AttachedPropertyReference)); + }
+
+ [TestCase(IncludePlatform = "Win32NT")] + public void Test_AttachedEntities_NetFramework() + { + var os = Environment.OSVersion;
+ Console.WriteLine("OS platform is: {0}", os.Platform.ToString()); + + var type = GetTypeDef<System.Windows.Media.Animation.Storyboard>(); var list = AttachedEntitiesHelper.GetAttachedEntities(type); - Assert.AreEqual("AttributeAttach", list.FirstOrDefault(t => t.Name == "AttributeAttach").Name); + Assert.AreEqual(3, list.Count()); + Assert.IsTrue(type.Fields.Any(t => t.Name == "TargetProperty")); + Assert.IsTrue(type.Fields.Any(t => t.Name == "TargetPropertyProperty")); + Assert.IsTrue(list.Any(t => t.Name == "Target" && t is AttachedPropertyReference)); + Assert.IsTrue(list.Any(t => t.Name == "TargetProperty" && t is AttachedPropertyReference)); + + type = GetTypeDef<System.Windows.Controls.Primitives.Selector>(); + list = AttachedEntitiesHelper.GetAttachedEntities(type); + Assert.AreEqual(4, list.Count());
+ Assert.IsTrue(list.Any(t => t.Name == "IsSelected" && t is AttachedPropertyReference));
+ Assert.IsTrue(list.Any(t => t.Name == "IsSelectionActive" && t is AttachedPropertyReference));
+ Assert.IsTrue(list.Any(t => t.Name == "Selected" && t is AttachedEventReference));
+ Assert.IsTrue(list.Any(t => t.Name == "Unselected" && t is AttachedEventReference)); + + type = GetTypeDef<Windows.UI.Xaml.Media.Animation.Storyboard>(); + list = AttachedEntitiesHelper.GetAttachedEntities(type); + Assert.AreEqual(2, list.Count());
+ Assert.IsTrue(type.Properties.Any(t => t.Name == "TargetNameProperty"));
+ Assert.IsTrue(type.Properties.Any(t => t.Name == "TargetPropertyProperty"));
+ Assert.IsTrue(list.Any(t => t.Name == "TargetName" && t is AttachedPropertyReference));
+ Assert.IsTrue(list.Any(t => t.Name == "TargetProperty" && t is AttachedPropertyReference)); } public class AttachedTestClassNoAttachedEntities { } - public class AttachedTestClass + public class AttachedPropertyTestClass { public static readonly DependencyProperty SomeProperty; public static bool GetSome(DependencyObject obj) { return false; } @@ -102,11 +138,32 @@ namespace mdoc.Test.Enumeration public static void SetSomeNotReadOnly(DependencyObject obj, bool val) { } } - public class AttachedPropertyTestClass + public class AttachedEntitiesTestClass { public DependencyProperty AttributeAttachProperty { get; set; } public static bool GetAttributeAttach(DependencyObject obj) { return false; } public static void SetAttributeAttach(DependencyObject obj, bool val) { } + + public static readonly DependencyProperty TargetProperty; + public static bool GetTarget(DependencyObject obj) { return false; } + public static void SetTarget(DependencyObject obj, bool val) { }
+
+ public delegate void EventHandler(object sender, EventArgs e);
+ public static readonly RoutedEvent TestingEvent;
+ public static void AddTestingHandler(DependencyObject element, EventHandler handler) { }
+ public static void RemoveTestingHandler(DependencyObject element, EventHandler handler) { } + + public static readonly DependencyProperty TargetPropertyProperty; + public static string GetTargetProperty(DependencyObject obj) + { + if (obj == null) { throw new ArgumentNullException("obj"); } + return (string)obj.GetValue(TargetPropertyProperty); + } + public static void SetTargetProperty(DependencyObject obj, string val) + {
+ if (obj == null) { throw new ArgumentNullException("obj"); } + obj.SetValue(TargetPropertyProperty, val); + } } } } diff --git a/mdoc/mdoc.Test/mdoc.Test.csproj b/mdoc/mdoc.Test/mdoc.Test.csproj index 6f33aeb6..7b4768d5 100644 --- a/mdoc/mdoc.Test/mdoc.Test.csproj +++ b/mdoc/mdoc.Test/mdoc.Test.csproj @@ -46,6 +46,10 @@ <Reference Include="nunit.framework, Version=3.10.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnit.3.10.1\lib\net45\nunit.framework.dll</HintPath>
</Reference>
+ <Reference Include="PresentationFramework">
+ <Private>True</Private>
+ <HintPath>..\..\external\Windows\PresentationFramework.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="Mono.Cecil, Version=0.10.0.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
<HintPath>..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.dll</HintPath>
|