diff options
author | Xiao Luo <basehello@icloud.com> | 2021-04-14 18:20:54 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-14 18:20:54 +0300 |
commit | 806f222aad9a217efc587776915ffba95f92a20f (patch) | |
tree | 3f0aa84640e4c842a92aa3744b7f836d2282cb87 | |
parent | 38d866cbbf3eb19b0a1a523153a3303a9ac2b1f3 (diff) |
Improve argument value formatter (#539)
https://dev.azure.com/ceapex/Engineering/_workitems/edit/366340
34 files changed, 1266 insertions, 301 deletions
diff --git a/mdoc/Mono.Documentation/MDocUpdater.cs b/mdoc/Mono.Documentation/MDocUpdater.cs index 8d7463e0..d75db09e 100644 --- a/mdoc/Mono.Documentation/MDocUpdater.cs +++ b/mdoc/Mono.Documentation/MDocUpdater.cs @@ -4408,9 +4408,9 @@ namespace Mono.Documentation return docTypeFormatter.GetName (type, useTypeProjection: useTypeProjection); } - internal static string GetDocTypeFullName (TypeReference type, bool useTypeProjection = true) + internal static string GetDocTypeFullName (TypeReference type, bool useTypeProjection = true, bool isTypeofOperator = false) { - return DocTypeFullMemberFormatter.Default.GetName (type, useTypeProjection: useTypeProjection); + return DocTypeFullMemberFormatter.Default.GetName (type, useTypeProjection: useTypeProjection, isTypeofOperator: isTypeofOperator); } internal static string GetXPathForMember (DocumentationMember member) diff --git a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/ApplePlatformEnumFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/ApplePlatformEnumFormatter.cs deleted file mode 100644 index 55dd508f..00000000 --- a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/ApplePlatformEnumFormatter.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -using Mono.Cecil; - -namespace Mono.Documentation.Updater -{ - /// <summary>A custom formatter for the ObjCRuntime.Platform enumeration.</summary> - class ApplePlatformEnumFormatter : AttributeValueFormatter - { - public override bool TryFormatValue (object v, ResolvedTypeInfo type, out string returnvalue) - { - TypeReference valueType = type.Reference; - string typename = MDocUpdater.GetDocTypeFullName (valueType); - TypeDefinition valueDef = type.Definition; - if (typename.Contains ("ObjCRuntime.Platform") && valueDef.CustomAttributes.Any (ca => ca.AttributeType.FullName == "System.FlagsAttribute")) - { - - var values = GetEnumerationValues (valueDef); - long c = ToInt64 (v); - - returnvalue = Format (c, values, typename); - return true; - } - - returnvalue = null; - return false; - } - - string Format (long c, IDictionary<long, string> values, string typename) - { - int iosarch, iosmajor, iosminor, iossubminor; - int macarch, macmajor, macminor, macsubminor; - GetEncodingiOS (c, out iosarch, out iosmajor, out iosminor, out iossubminor); - GetEncodingMac ((ulong)c, out macarch, out macmajor, out macminor, out macsubminor); - - if (iosmajor == 0 & iosminor == 0 && iossubminor == 0) - { - return FormatValues ("Mac", macarch, macmajor, macminor, macsubminor); - } - - if (macmajor == 0 & macminor == 0 && macsubminor == 0) - { - return FormatValues ("iOS", iosarch, iosmajor, iosminor, iossubminor); - } - - return string.Format ("(Platform){0}", c); - } - - string FormatValues (string plat, int arch, int major, int minor, int subminor) - { - string archstring = ""; - switch (arch) - { - case 1: - archstring = "32"; - break; - case 2: - archstring = "64"; - break; - } - return string.Format ("Platform.{4}_{0}_{1}{2} | Platform.{4}_Arch{3}", - major, - minor, - subminor == 0 ? "" : "_" + subminor.ToString (), - archstring, - plat - ); - } - - void GetEncodingiOS (long entireLong, out int archindex, out int major, out int minor, out int subminor) - { - long lowerBits = entireLong & 0xffffffff; - int lowerBitsAsInt = (int)lowerBits; - GetEncoding (lowerBitsAsInt, out archindex, out major, out minor, out subminor); - } - - void GetEncodingMac (ulong entireLong, out int archindex, out int major, out int minor, out int subminor) - { - ulong higherBits = entireLong & 0xffffffff00000000; - int higherBitsAsInt = (int)((higherBits) >> 32); - GetEncoding (higherBitsAsInt, out archindex, out major, out minor, out subminor); - } - - void GetEncoding (Int32 encodedBits, out int archindex, out int major, out int minor, out int subminor) - { - // format is AAJJNNSS - archindex = (int)((encodedBits & 0xFF000000) >> 24); - major = (int)((encodedBits & 0x00FF0000) >> 16); - minor = (int)((encodedBits & 0x0000FF00) >> 8); - subminor = (int)((encodedBits & 0x000000FF) >> 0); - } - } -}
\ No newline at end of file diff --git a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs index 1378675a..b8076d73 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs @@ -2,13 +2,14 @@ using Mono.Documentation.Util; using System; using System.Collections.Generic; -using System.IO; using System.Linq; namespace Mono.Documentation.Updater.Formatters { public class AttributeFormatter { + private AttributeValueFormatter valueFormatter = new AttributeValueFormatter(); + public virtual string PrefixBrackets { get; } = ""; public virtual string SurfixBrackets { get; } = ""; public virtual string Language { get; } = ""; @@ -119,37 +120,9 @@ namespace Mono.Documentation.Updater.Formatters return $"{name}={value}"; } - public virtual string MakeAttributesValueString(object v, TypeReference valueType) + public virtual string MakeAttributesValueString(object argumentValue, TypeReference argumentType) { - var formatters = new[] { - new AttributeValueFormatter (), - new ApplePlatformEnumFormatter (), - new StandardFlagsEnumFormatter (), - new DefaultAttributeValueFormatter (), - }; - - ResolvedTypeInfo type = new ResolvedTypeInfo(valueType); - - if (valueType is ArrayType && v is CustomAttributeArgument[]) - { - ArrayType atype = valueType as ArrayType; - CustomAttributeArgument[] args = v as CustomAttributeArgument[]; - var returnvalue = $"new {atype.FullName}{(atype.FullName.EndsWith("[]") ? "" : "[]")} {{ { string.Join(", ", args.Select(a => MakeAttributesValueString(a.Value, a.Type)).ToArray()) } }}"; - return returnvalue; - } - - foreach (var formatter in formatters) - { - string formattedValue; - if (formatter.TryFormatValue(v, type, out formattedValue)) - { - return formattedValue; - } - } - - // this should never occur because the DefaultAttributeValueFormatter will always - // successfully format the value ... but this is needed to satisfy the compiler :) - throw new InvalidDataException(string.Format("Unable to format attribute value ({0})", v.ToString())); + return valueFormatter.Format(argumentType, argumentValue); } private bool IsIgnoredAttribute(CustomAttribute customAttribute) diff --git a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeValueFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeValueFormatter.cs index a9e092bb..41566740 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeValueFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeValueFormatter.cs @@ -1,92 +1,385 @@ -using System; +using Mono.Cecil; +using System; using System.Collections.Generic; using System.Linq; -using Mono.Cecil; - -using Mono.Documentation.Util; namespace Mono.Documentation.Updater { - /// <summary>Formats attribute values. Should return true if it is able to format the value.</summary> - class AttributeValueFormatter - { - public virtual bool TryFormatValue (object v, ResolvedTypeInfo type, out string returnvalue) + public class AttributeValueFormatter + { + public string Format(TypeReference argumentType, object argumentValue) { - TypeReference valueType = type.Reference; - if (v == null) + // When a property type of an attribute is an object type you can assign any type to it, + // so we need to convert the object type to a concrete object type. + if (argumentValue is CustomAttributeArgument attributeArgument) { - returnvalue = "null"; - return true; + return Format(attributeArgument.Type, attributeArgument.Value); } - if (valueType.FullName == "System.Type") + + return FormatValue(argumentType, argumentValue); + } + + // The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are: + // https://github.com/dotnet/csharplang/blob/main/spec/attributes.md#attribute-parameter-types + private string FormatValue(TypeReference argumentType, object argumentValue) + { + if (IsNull(argumentValue)) { - var vTypeRef = v as TypeReference; - if (vTypeRef != null) - returnvalue = "typeof(" + NativeTypeManager.GetTranslatedName (vTypeRef) + ")"; // TODO: drop NS handling - else - returnvalue = "typeof(" + v.ToString () + ")"; + return "null"; + } - return true; + if (IsArrayType(argumentType, argumentValue)) + { + return ConvertToArrayType(argumentType, argumentValue); } - if (valueType.FullName == "System.String") + + if (IsTypeType(argumentType, argumentValue)) { - returnvalue = "\"" + FilterSpecialChars (v.ToString ()) + "\""; - return true; + return ConvertToType(argumentType, argumentValue); } - if (valueType.FullName == "System.Char") + + if (IsStringType(argumentType, argumentValue)) { - returnvalue = "'" + FilterSpecialChars (v.ToString ()) + "'"; - return true; + return ConvertToString(argumentType, argumentValue); } - if (v is Boolean) + + if (IsCharType(argumentType, argumentValue)) { - returnvalue = (bool)v ? "true" : "false"; - return true; + return ConvertToChar(argumentType, argumentValue); } - TypeDefinition valueDef = type.Definition; - if (valueDef == null || !valueDef.IsEnum) + if (IsBoolType(argumentType, argumentValue)) { - returnvalue = v.ToString (); - return true; + return ConvertToBool(argumentType, argumentValue); } - string typename = MDocUpdater.GetDocTypeFullName (valueType); - var values = GetEnumerationValues (valueDef); - long c = ToInt64 (v); - if (values.ContainsKey (c)) + if (IsEnumType(argumentType, argumentValue)) { - returnvalue = typename + "." + values[c]; - return true; + return ConvertToEnum(argumentType, argumentValue); + } + + return ConvertUnhandledTypeToString(argumentValue); + } + + private bool IsNull(object argumentValue) + { + return argumentValue == null; + } + + private bool IsEnumType(TypeReference argumentType, object argumentValue) + { + return argumentType.Resolve().IsEnum; + } + + private bool IsTypeType(TypeReference argumentType, object argumentValue) + { + return IsType("System.Type", argumentType, argumentValue); + } + + private bool IsStringType(TypeReference argumentType, object argumentValue) + { + return IsType("System.String", argumentType, argumentValue); + } + + private bool IsCharType(TypeReference argumentType, object argumentValue) + { + return IsType("System.Char", argumentType, argumentValue); + } + + private bool IsBoolType(TypeReference argumentType, object argumentValue) + { + return IsType("System.Boolean", argumentType, argumentValue); + } + + private bool IsType(string typeFullName, TypeReference argumentType, object argumentValue) + { + return argumentType.FullName.Equals(typeFullName); + } + + private bool IsArrayType(TypeReference argumentType, object argumentValue) + { + return argumentType is ArrayType && argumentValue is CustomAttributeArgument[]; + } + + private string ConvertToArrayType(TypeReference argumentType, object argumentValue) + { + var arrayType = argumentType as ArrayType; + var arrayArguments = argumentValue as CustomAttributeArgument[]; + var arrayTypeFullName = $"new {arrayType.FullName}{(arrayType.FullName.EndsWith("[]") ? "" : "[]")}"; + var arrayArgumentValues = arrayArguments.Select(i => FormatValue(i.Type, i.Value)); + + return $"{arrayTypeFullName} {{ {string.Join(", ", arrayArgumentValues)} }}"; + } + + private bool IsFlagsEnum(TypeReference argumentType, object argumentValue) + { + var argumentTypeDefinition = argumentType.Resolve(); + var isApplyFlagsAttributeEnumType = argumentTypeDefinition.CustomAttributes.Any(a => a.AttributeType.FullName == "System.FlagsAttribute"); + var isNotApplyAttributeFlagsEnumType = IsNotApplyAttributeFlagsEnumType(argumentTypeDefinition, argumentValue); + + return isApplyFlagsAttributeEnumType || isNotApplyAttributeFlagsEnumType; + } + + /// <summary> + /// We have a few legacy flags enum type not apply FlagsAttribute to it. + /// For example, Microsoft.JScript.JSFunctionAttributeEnum in .NET Framework 1.1 but the issue has been fixed in the newer version. + /// </summary> + private bool IsNotApplyAttributeFlagsEnumType(TypeDefinition argumentType, object argumentValue) + { + (var typeFullName, var enumConstants, var enumValue) = ExtractEnumTypeData(argumentType, argumentValue); + if (enumConstants.ContainsKey(enumValue)) + { + // Not is a combinations of values. + return false; + } + + var flagsEnumValues = enumConstants.Keys.ToList(); + flagsEnumValues.Remove(0); // The zero value is not a valid flags enum value. + + // The following example is an invalid and valid flags enum type. + // None = 0, Read = 1, Write = 2, ReadWrite = 3 maybe is a flags enum type but sometimes it is not. + // Read = 1, Write = 2, Open = 4, Close = 8 actually is a flags enum type. + var minFlagsEnumValueCount = 4; + if (flagsEnumValues.Count() >= minFlagsEnumValueCount) + { + long allEnumLogicalOrValue = 0; + foreach (var item in flagsEnumValues) + { + allEnumLogicalOrValue = allEnumLogicalOrValue | item; + } + + var isFlagsEnumType = !flagsEnumValues.Any(i => (i & allEnumLogicalOrValue) != i); + var isCombinationValue = flagsEnumValues.Count(i => (i & enumValue) != i) > 1; + + return isFlagsEnumType && isCombinationValue; } - returnvalue = null; return false; } - internal static IDictionary<long, string> GetEnumerationValues(TypeDefinition type) + private bool IsApplePlatformEnum(TypeReference argumentType, object argumentValue) + { + return MDocUpdater.GetDocTypeFullName(argumentType).Contains("ObjCRuntime.Platform"); + } + + private string ConvertToType(TypeReference argumentType, object argumentValue) { + var valueResult = GetArgumentValue("System.Type", argumentType, argumentValue); + var typeFullName = MDocUpdater.GetDocTypeFullName((TypeReference)valueResult, isTypeofOperator: true); + + return $"typeof({typeFullName})"; + } + + private string ConvertToString(TypeReference argumentType, object argumentValue) + { + var valueResult = GetArgumentValue("System.String", argumentType, argumentValue); + if (valueResult == null) + { + return "null"; + } + + return string.Format("\"{0}\"", FilterSpecialChars(valueResult.ToString())); + } + + private string ConvertToBool(TypeReference argumentType, object argumentValue) + { + return GetArgumentValue("System.Boolean", argumentType, argumentValue).ToString().ToLower(); + } + + private string ConvertToChar(TypeReference argumentType, object argumentValue) + { + var valueResult = GetArgumentValue("System.Char", argumentType, argumentValue).ToString(); + + return string.Format("'{0}'", FilterSpecialChars(valueResult)); + } + + private string ConvertUnhandledTypeToString(object argumentValue) + { + return argumentValue.ToString(); + } + + private string ConvertToEnum(TypeReference argumentType, object argumentValue) + { + if (IsFlagsEnum(argumentType, argumentValue)) + { + if (IsApplePlatformEnum(argumentType, argumentValue)) + { + return ConvertToApplePlatformEnum(argumentType, argumentValue); + } + + return ConvertToFlagsEnum(argumentType, argumentValue); + } + + return ConvertToNormalEnum(argumentType, argumentValue); + } + + private string ConvertToNormalEnum(TypeReference argumentType, object argumentValue) + { + (var typeFullName, var enumConstants, var enumValue) = ExtractEnumTypeData(argumentType, argumentValue); + if (enumConstants.ContainsKey(enumValue)) + { + return typeFullName + "." + enumConstants[enumValue]; + } + + return ConvertToUnknownEnum(argumentType, argumentValue); + } + + private string ConvertToUnknownEnum(TypeReference argumentType, object argumentValue) + { + (var typeFullName, var enumConstants, var enumValue) = ExtractEnumTypeData(argumentType, argumentValue); + + return $"({typeFullName}) {enumValue}"; + } + + private string ConvertToFlagsEnum(TypeReference argumentType, object argumentValue) + { + (var typeFullName, var enumConstants, var enumValue) = ExtractEnumTypeData(argumentType, argumentValue); + if (enumConstants.ContainsKey(enumValue)) + { + // Not is a combinations of values. + return $"{typeFullName}.{enumConstants[enumValue]}"; + } + + var flagsEnumValues = enumConstants.Keys.Where(i => (enumValue & i) == i && i != 0).ToList(); + var duplicateEnumValues = flagsEnumValues.Where(i => flagsEnumValues.Any(a => (a & i) == i && a > i)); + + flagsEnumValues.RemoveAll(i => duplicateEnumValues.Contains(i)); + var flagsEnumNames = flagsEnumValues + .Select(i => $"{typeFullName}.{enumConstants[i]}") + .OrderBy(val => val) // to maintain a consistent list across frameworks/versions + .ToArray(); + + if (flagsEnumNames.Length > 0) + { + return string.Join(" | ", flagsEnumNames); + } + + return ConvertToUnknownEnum(argumentType, argumentValue); + } + + private string ConvertToApplePlatformEnum(TypeReference argumentType, object argumentValue) + { + (var typeFullName, var enumConstants, var enumValue) = ExtractEnumTypeData(argumentType, argumentValue); + if (enumConstants.ContainsKey(enumValue)) + { + return typeFullName + "." + enumConstants[enumValue]; + } + + return FormatApplePlatformEnum(enumValue); + } + + private (string typeFullName, IDictionary<long, string> enumConstants, long enumValue) ExtractEnumTypeData(TypeReference argumentType, object argumentValue) + { + var argumentTypeDefinition = argumentType.Resolve(); + var typeFullName = MDocUpdater.GetDocTypeFullName(argumentTypeDefinition); + var enumConstants = GetEnumerationValues(argumentTypeDefinition); + var enumValue = ToInt64(argumentValue); + + return (typeFullName, enumConstants, enumValue); + } + + private string FormatApplePlatformEnum(long enumValue) + { + int iosarch, iosmajor, iosminor, iossubminor; + int macarch, macmajor, macminor, macsubminor; + GetEncodingiOS(enumValue, out iosarch, out iosmajor, out iosminor, out iossubminor); + GetEncodingMac((ulong)enumValue, out macarch, out macmajor, out macminor, out macsubminor); + + if (iosmajor == 0 & iosminor == 0 && iossubminor == 0) + { + return FormatApplePlatformEnumValue("Mac", macarch, macmajor, macminor, macsubminor); + } + + if (macmajor == 0 & macminor == 0 && macsubminor == 0) + { + return FormatApplePlatformEnumValue("iOS", iosarch, iosmajor, iosminor, iossubminor); + } + + return string.Format("(Platform){0}", enumValue); + } + + private string FormatApplePlatformEnumValue(string plat, int arch, int major, int minor, int subminor) + { + var archstring = string.Empty; + switch (arch) + { + case 1: + archstring = "32"; + break; + case 2: + archstring = "64"; + break; + } + + return string.Format("Platform.{4}_{0}_{1}{2} | Platform.{4}_Arch{3}", + major, + minor, + subminor == 0 ? "" : "_" + subminor.ToString(), + archstring, + plat + ); + } + + private void GetEncodingiOS(long entireLong, out int archindex, out int major, out int minor, out int subminor) + { + long lowerBits = entireLong & 0xffffffff; + int lowerBitsAsInt = (int)lowerBits; + GetEncodingApplePlatform(lowerBitsAsInt, out archindex, out major, out minor, out subminor); + } + + private void GetEncodingMac(ulong entireLong, out int archindex, out int major, out int minor, out int subminor) + { + ulong higherBits = entireLong & 0xffffffff00000000; + int higherBitsAsInt = (int)((higherBits) >> 32); + GetEncodingApplePlatform(higherBitsAsInt, out archindex, out major, out minor, out subminor); + } + + private void GetEncodingApplePlatform(Int32 encodedBits, out int archindex, out int major, out int minor, out int subminor) + { + // format is AAJJNNSS + archindex = (int)((encodedBits & 0xFF000000) >> 24); + major = (int)((encodedBits & 0x00FF0000) >> 16); + minor = (int)((encodedBits & 0x0000FF00) >> 8); + subminor = (int)((encodedBits & 0x000000FF) >> 0); + } + + private object GetArgumentValue(string argumentTypeFullName, TypeReference argumentType, object argumentValue) + { + if (argumentType.FullName.Equals(argumentTypeFullName)) + { + return argumentValue; + } + + throw new ArgumentException($"The argument type does not match {argumentTypeFullName}."); + } + + private IDictionary<long, string> GetEnumerationValues(TypeDefinition argumentType) + { + var enumValues = from f in argumentType.Fields + where !(f.IsRuntimeSpecialName || f.IsSpecialName) + select f; + var values = new Dictionary<long, string>(); - foreach (var f in - (from f in type.Fields - where !(f.IsRuntimeSpecialName || f.IsSpecialName) - select f)) + foreach (var item in enumValues) { - values[ToInt64(f.Constant)] = f.Name; + values[ToInt64(item.Constant)] = item.Name; } + return values; } - internal static long ToInt64(object value) + private long ToInt64(object value) { if (value is ulong) return (long)(ulong)value; + return Convert.ToInt64(value); } - public static string FilterSpecialChars(string value) + private string FilterSpecialChars(string value) { - return value.Replace("\0", "\\0") + return value + .Replace("\0", "\\0") .Replace("\t", "\\t") .Replace("\n", "\\n") .Replace("\r", "\\r") diff --git a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/DefaultAttributeValueFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/DefaultAttributeValueFormatter.cs deleted file mode 100644 index d0a2f8ec..00000000 --- a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/DefaultAttributeValueFormatter.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Mono.Documentation.Updater -{ - /// <summary>The final value formatter in the pipeline ... if no other formatter formats the value, - /// then this one will serve as the default implementation.</summary> - class DefaultAttributeValueFormatter : AttributeValueFormatter - { - public override bool TryFormatValue (object v, ResolvedTypeInfo type, out string returnvalue) - { - returnvalue = "(" + MDocUpdater.GetDocTypeFullName (type.Reference) + ") " + FilterSpecialChars(v.ToString ()); - return true; - } - } -}
\ No newline at end of file diff --git a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/StandardFlagsEnumFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/StandardFlagsEnumFormatter.cs deleted file mode 100644 index 16a1ebe0..00000000 --- a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/StandardFlagsEnumFormatter.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Linq; - -using Mono.Cecil; - -namespace Mono.Documentation.Updater -{ - /// <summary>Flags enum formatter that assumes powers of two values.</summary> - /// <remarks>As described here: https://msdn.microsoft.com/en-us/library/vstudio/ms229062(v=vs.100).aspx</remarks> - class StandardFlagsEnumFormatter : AttributeValueFormatter - { - public override bool TryFormatValue (object v, ResolvedTypeInfo type, out string returnvalue) - { - TypeReference valueType = type.Reference; - TypeDefinition valueDef = type.Definition; - if (valueDef.CustomAttributes.Any (ca => ca.AttributeType.FullName == "System.FlagsAttribute")) - { - - string typename = MDocUpdater.GetDocTypeFullName (valueType); - var values = GetEnumerationValues (valueDef); - long c = ToInt64 (v); - returnvalue = string.Join (" | ", - (from i in values.Keys - where (c & i) == i && i != 0 - select typename + "." + values[i]) - .DefaultIfEmpty (c.ToString ()) - .OrderBy (val => val) // to maintain a consistent list across frameworks/versions - .ToArray ()); - - return true; - } - - returnvalue = null; - return false; - } - } -}
\ No newline at end of file diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs index 34749cc5..d0d674db 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs @@ -107,7 +107,7 @@ namespace Mono.Documentation.Updater.Formatters return buf; } - protected override string GetTypeName (TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = true) + protected override string GetTypeName (TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = true, bool isTypeofOperator = false) { GenericInstanceType genType = type as GenericInstanceType; if (IsSpecialGenericNullableValueType (genType)) diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CppFormatters/CppFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CppFormatters/CppFullMemberFormatter.cs index 757b6431..1ae7b91a 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/CppFormatters/CppFullMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/CppFormatters/CppFullMemberFormatter.cs @@ -553,7 +553,7 @@ namespace Mono.Documentation.Updater.Formatters.CppFormatters return AppendConstraints (buf, method.GenericParameters); } - protected override StringBuilder AppendGenericType(StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false) + protected override StringBuilder AppendGenericType(StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false, bool isTypeofOperator = false) { List<TypeReference> decls = DocUtils.GetDeclaringTypes( type is GenericInstanceType ? type.GetElementType() : type); diff --git a/mdoc/Mono.Documentation/Updater/Formatters/FSharpFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/FSharpFormatter.cs index 0589c7f9..25b78bf8 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/FSharpFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/FSharpFormatter.cs @@ -308,7 +308,7 @@ namespace Mono.Documentation.Updater return "class"; } - protected override StringBuilder AppendGenericType(StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false) + protected override StringBuilder AppendGenericType(StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false, bool isTypeofOperator = false) { List<TypeReference> decls = DocUtils.GetDeclaringTypes( type is GenericInstanceType ? type.GetElementType() : type); diff --git a/mdoc/Mono.Documentation/Updater/Formatters/ILFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/ILFullMemberFormatter.cs index 1ad73548..ad30e238 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/ILFullMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/ILFullMemberFormatter.cs @@ -203,7 +203,7 @@ namespace Mono.Documentation.Updater.Formatters return buf.ToString (); } - protected override StringBuilder AppendGenericType (StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false) + protected override StringBuilder AppendGenericType (StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false, bool isTypeofOperator = false) { List<TypeReference> decls = DocUtils.GetDeclaringTypes ( type is GenericInstanceType ? type.GetElementType () : type); diff --git a/mdoc/Mono.Documentation/Updater/Formatters/JsFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/JsFormatter.cs index 8664d1ba..dabceb3e 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/JsFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/JsFormatter.cs @@ -151,7 +151,7 @@ namespace Mono.Documentation.Updater.Formatters return CamelCase(method.Name); } - protected override string GetTypeName(TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false) + protected override string GetTypeName(TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false, bool isTypeofOperator = false) { int n = type.Name.IndexOf("`"); if (n >= 0) diff --git a/mdoc/Mono.Documentation/Updater/Formatters/MemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/MemberFormatter.cs index faf87874..d5f634e1 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/MemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/MemberFormatter.cs @@ -1,12 +1,10 @@ -using System; +using Mono.Cecil; +using Mono.Documentation.Util; +using System; using System.Collections.Generic; using System.Linq; using System.Text; - -using Mono.Documentation.Util; -using Mono.Cecil; - namespace Mono.Documentation.Updater { public abstract class MemberFormatter @@ -25,16 +23,16 @@ namespace Mono.Documentation.Updater get { return "//"; } } - public string GetName (MemberReference member, bool appendGeneric = true, bool useTypeProjection = true) + public string GetName (MemberReference member, bool appendGeneric = true, bool useTypeProjection = true, bool isTypeofOperator = false) { - return GetName (member, EmptyAttributeParserContext.Empty(), appendGeneric, useTypeProjection: useTypeProjection); + return GetName (member, EmptyAttributeParserContext.Empty(), appendGeneric, useTypeProjection, isTypeofOperator); } - public virtual string GetName (MemberReference member, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = true) + public virtual string GetName (MemberReference member, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = true, bool isTypeofOperator = false) { TypeReference type = member as TypeReference; if (type != null) - return GetTypeName (type, context, appendGeneric, useTypeProjection: useTypeProjection); + return GetTypeName (type, context, appendGeneric, useTypeProjection, isTypeofOperator); MethodReference method = member as MethodReference; if (method != null && method.Name == ".ctor") // method.IsConstructor return GetConstructorName (method); @@ -58,12 +56,12 @@ namespace Mono.Documentation.Updater return GetTypeName (type, EmptyAttributeParserContext.Empty(), appendGeneric, useTypeProjection: useTypeProjection); } - protected virtual string GetTypeName (TypeReference type, IAttributeParserContext context, bool appendGeneric=true, bool useTypeProjection = true) + protected virtual string GetTypeName (TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = true, bool isTypeofOperator = false) { if (type == null) throw new ArgumentNullException (nameof (type)); - var typeName = _AppendTypeName (new StringBuilder (type.Name.Length), type, context, appendGeneric, useTypeProjection: useTypeProjection).ToString (); + var typeName = _AppendTypeName (new StringBuilder (type.Name.Length), type, context, appendGeneric, useTypeProjection, isTypeofOperator).ToString (); return RemoveMod (typeName); } @@ -138,7 +136,7 @@ namespace Mono.Documentation.Updater get => true; } - protected StringBuilder _AppendTypeName (StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection =false) + protected StringBuilder _AppendTypeName (StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false, bool isTypeofOperator = false) { if (type == null) return buf; @@ -206,7 +204,7 @@ namespace Mono.Documentation.Updater AppendFullTypeName (interimBuilder, type, context); return SetBuffer(buf, interimBuilder, useTypeProjection: useTypeProjection); } - AppendGenericType (interimBuilder, type, context, appendGeneric, useTypeProjection: useTypeProjection); + AppendGenericType (interimBuilder, type, context, appendGeneric, useTypeProjection, isTypeofOperator); return SetBuffer(buf, interimBuilder, useTypeProjection: useTypeProjection); } @@ -320,7 +318,7 @@ namespace Mono.Documentation.Updater get { return "."; } } - protected virtual StringBuilder AppendGenericType (StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = true) + protected virtual StringBuilder AppendGenericType (StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = true, bool isTypeofOperator = false) { int argIdx = 0; int prev = 0; @@ -344,22 +342,54 @@ namespace Mono.Documentation.Updater if (appendGeneric && c > 0) { buf.Append (GenericTypeContainer[0]); - var origState = MemberFormatterState; - MemberFormatterState = MemberFormatterState.WithinGenericTypeParameters; - AppendGenericTypeParameter (buf, genArgs[argIdx++], context, useTypeProjection); - for (int i = 1; i < c; ++i) + + var currentTypeArguments = genArgs.Skip(argIdx).Take(c); + if (IsTypeOfOperatorWithUnboundGenericType(decl, currentTypeArguments, isTypeofOperator)) { - buf.Append (","); + buf.Append(string.Join(string.Empty, Enumerable.Repeat(",", currentTypeArguments.Count() - 1))); + } + else + { + var origState = MemberFormatterState; + MemberFormatterState = MemberFormatterState.WithinGenericTypeParameters; AppendGenericTypeParameter (buf, genArgs[argIdx++], context, useTypeProjection); + for (int i = 1; i < c; ++i) + { + buf.Append (","); + AppendGenericTypeParameter (buf, genArgs[argIdx++], context, useTypeProjection); + } + + MemberFormatterState = origState; } - MemberFormatterState = origState; buf.Append (GenericTypeContainer[1]); } } + return buf; } + private bool IsTypeOfOperatorWithUnboundGenericType(TypeReference type, IEnumerable<TypeReference> genericArguments, bool isTypeofOperator) + { + if (isTypeofOperator) + { + var argumentCount = genericArguments.Count() > 0 ? genericArguments.Count().ToString() : string.Empty; + var genericTypeSeparator = $"`{argumentCount}"; + var genericTypeSeparatorIndex = type.FullName.LastIndexOf(genericTypeSeparator); + + var leftAngleBracketIndex = type.FullName.IndexOf("<", genericTypeSeparatorIndex); + var validLeftAngleBracketIndex = genericTypeSeparatorIndex + genericTypeSeparator.Length + 1; + + // If the type is an unbound generic type that type hasn't angle brackets after its full name. + var notExistParameterType = genericTypeSeparatorIndex >= 0 && leftAngleBracketIndex != validLeftAngleBracketIndex; + var notPassParameterType = genericArguments.All(i => i is GenericParameter); + + return notExistParameterType && notPassParameterType; + } + + return false; + } + private void AppendGenericTypeParameter (StringBuilder buf, TypeReference type, IAttributeParserContext context, bool useTypeProjection = true) { var isNullableType = false; diff --git a/mdoc/Mono.Documentation/Updater/Formatters/SlashDocMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/SlashDocMemberFormatter.cs index 4bb986fc..2a5dfa51 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/SlashDocMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/SlashDocMemberFormatter.cs @@ -102,7 +102,7 @@ namespace Mono.Documentation.Updater return buf.Append (ArrayDelimeters[1]); } - protected override StringBuilder AppendGenericType (StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false) + protected override StringBuilder AppendGenericType (StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false, bool isTypeofOperator = false) { if (!AddTypeCount) base.AppendGenericType (buf, type, context); diff --git a/mdoc/Mono.Documentation/Updater/Formatters/VBFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/VBFullMemberFormatter.cs index 92a74cec..6d9761f8 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/VBFullMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/VBFullMemberFormatter.cs @@ -209,7 +209,7 @@ namespace Mono.Documentation.Updater } } - protected override StringBuilder AppendGenericType(StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false) + protected override StringBuilder AppendGenericType(StringBuilder buf, TypeReference type, IAttributeParserContext context, bool appendGeneric = true, bool useTypeProjection = false, bool isTypeofOperator = false) { List<TypeReference> decls = DocUtils.GetDeclaringTypes( type is GenericInstanceType ? type.GetElementType() : type); diff --git a/mdoc/Mono.Documentation/Updater/ResolvedTypeInfo.cs b/mdoc/Mono.Documentation/Updater/ResolvedTypeInfo.cs deleted file mode 100644 index 0db9b6da..00000000 --- a/mdoc/Mono.Documentation/Updater/ResolvedTypeInfo.cs +++ /dev/null @@ -1,29 +0,0 @@ - -using Mono.Cecil; -
-namespace Mono.Documentation.Updater -{
- class ResolvedTypeInfo - { - TypeDefinition typeDef; - - public ResolvedTypeInfo (TypeReference value) - { - Reference = value; - } - - public TypeReference Reference { get; private set; } - - public TypeDefinition Definition - { - get - { - if (typeDef == null) - { - typeDef = Reference.Resolve (); - } - return typeDef; - } - } - } -}
\ No newline at end of file diff --git a/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Circle.xml b/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Circle.xml index 0df6e8c0..1cf1d136 100644 --- a/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Circle.xml +++ b/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Circle.xml @@ -16,8 +16,8 @@ <AttributeName Language="F#">[<System.Diagnostics.DebuggerDisplay("{__DebugDisplay(),nq}")>]</AttributeName> </Attribute> <Attribute> - <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions/Shape/Circle@DebugTypeProxy))]</AttributeName> - <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions/Shape/Circle@DebugTypeProxy))>]</AttributeName> + <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions+Shape+Circle@DebugTypeProxy))]</AttributeName> + <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions+Shape+Circle@DebugTypeProxy))>]</AttributeName> </Attribute> <Attribute> <AttributeName Language="C#">[System.Serializable]</AttributeName> diff --git a/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Prism.xml b/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Prism.xml index 6b82ea56..d692ac3a 100644 --- a/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Prism.xml +++ b/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Prism.xml @@ -16,8 +16,8 @@ <AttributeName Language="F#">[<System.Diagnostics.DebuggerDisplay("{__DebugDisplay(),nq}")>]</AttributeName> </Attribute> <Attribute> - <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions/Shape/Prism@DebugTypeProxy))]</AttributeName> - <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions/Shape/Prism@DebugTypeProxy))>]</AttributeName> + <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions+Shape+Prism@DebugTypeProxy))]</AttributeName> + <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions+Shape+Prism@DebugTypeProxy))>]</AttributeName> </Attribute> <Attribute> <AttributeName Language="C#">[System.Serializable]</AttributeName> diff --git a/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Rectangle.xml b/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Rectangle.xml index af196c39..fe657c9b 100644 --- a/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Rectangle.xml +++ b/mdoc/Test/en.expected-fsharp/DiscriminatedUnions+Shape+Rectangle.xml @@ -16,8 +16,8 @@ <AttributeName Language="F#">[<System.Diagnostics.DebuggerDisplay("{__DebugDisplay(),nq}")>]</AttributeName> </Attribute> <Attribute> - <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions/Shape/Rectangle@DebugTypeProxy))]</AttributeName> - <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions/Shape/Rectangle@DebugTypeProxy))>]</AttributeName> + <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions+Shape+Rectangle@DebugTypeProxy))]</AttributeName> + <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(DiscriminatedUnions+Shape+Rectangle@DebugTypeProxy))>]</AttributeName> </Attribute> <Attribute> <AttributeName Language="C#">[System.Serializable]</AttributeName> diff --git a/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+FirstLast.xml b/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+FirstLast.xml index b7b7a2de..e31b131c 100644 --- a/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+FirstLast.xml +++ b/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+FirstLast.xml @@ -16,8 +16,8 @@ <AttributeName Language="F#">[<System.Diagnostics.DebuggerDisplay("{__DebugDisplay(),nq}")>]</AttributeName> </Attribute> <Attribute> - <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples/PersonName/FirstLast@DebugTypeProxy))]</AttributeName> - <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples/PersonName/FirstLast@DebugTypeProxy))>]</AttributeName> + <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples+PersonName+FirstLast@DebugTypeProxy))]</AttributeName> + <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples+PersonName+FirstLast@DebugTypeProxy))>]</AttributeName> </Attribute> <Attribute> <AttributeName Language="C#">[System.Serializable]</AttributeName> diff --git a/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+FirstOnly.xml b/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+FirstOnly.xml index c50cd03a..8bc63289 100644 --- a/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+FirstOnly.xml +++ b/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+FirstOnly.xml @@ -16,8 +16,8 @@ <AttributeName Language="F#">[<System.Diagnostics.DebuggerDisplay("{__DebugDisplay(),nq}")>]</AttributeName> </Attribute> <Attribute> - <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples/PersonName/FirstOnly@DebugTypeProxy))]</AttributeName> - <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples/PersonName/FirstOnly@DebugTypeProxy))>]</AttributeName> + <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples+PersonName+FirstOnly@DebugTypeProxy))]</AttributeName> + <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples+PersonName+FirstOnly@DebugTypeProxy))>]</AttributeName> </Attribute> <Attribute> <AttributeName Language="C#">[System.Serializable]</AttributeName> diff --git a/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+LastOnly.xml b/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+LastOnly.xml index 9039e514..b9346976 100644 --- a/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+LastOnly.xml +++ b/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+PersonName+LastOnly.xml @@ -16,8 +16,8 @@ <AttributeName Language="F#">[<System.Diagnostics.DebuggerDisplay("{__DebugDisplay(),nq}")>]</AttributeName> </Attribute> <Attribute> - <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples/PersonName/LastOnly@DebugTypeProxy))]</AttributeName> - <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples/PersonName/LastOnly@DebugTypeProxy))>]</AttributeName> + <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples+PersonName+LastOnly@DebugTypeProxy))]</AttributeName> + <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples+PersonName+LastOnly@DebugTypeProxy))>]</AttributeName> </Attribute> <Attribute> <AttributeName Language="C#">[System.Serializable]</AttributeName> diff --git a/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+Shape+Circle.xml b/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+Shape+Circle.xml index 538409b3..cfc60932 100644 --- a/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+Shape+Circle.xml +++ b/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+Shape+Circle.xml @@ -16,8 +16,8 @@ <AttributeName Language="F#">[<System.Diagnostics.DebuggerDisplay("{__DebugDisplay(),nq}")>]</AttributeName> </Attribute> <Attribute> - <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples/Shape/Circle@DebugTypeProxy))]</AttributeName> - <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples/Shape/Circle@DebugTypeProxy))>]</AttributeName> + <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples+Shape+Circle@DebugTypeProxy))]</AttributeName> + <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples+Shape+Circle@DebugTypeProxy))>]</AttributeName> </Attribute> <Attribute> <AttributeName Language="C#">[System.Serializable]</AttributeName> diff --git a/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+Shape+Rectangle.xml b/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+Shape+Rectangle.xml index f22cf1ab..418a8add 100644 --- a/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+Shape+Rectangle.xml +++ b/mdoc/Test/en.expected-fsharp/PatternMatching/PatternMatchingExamples+Shape+Rectangle.xml @@ -16,8 +16,8 @@ <AttributeName Language="F#">[<System.Diagnostics.DebuggerDisplay("{__DebugDisplay(),nq}")>]</AttributeName> </Attribute> <Attribute> - <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples/Shape/Rectangle@DebugTypeProxy))]</AttributeName> - <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples/Shape/Rectangle@DebugTypeProxy))>]</AttributeName> + <AttributeName Language="C#">[System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples+Shape+Rectangle@DebugTypeProxy))]</AttributeName> + <AttributeName Language="F#">[<System.Diagnostics.DebuggerTypeProxy(typeof(PatternMatching.PatternMatchingExamples+Shape+Rectangle@DebugTypeProxy))>]</AttributeName> </Attribute> <Attribute> <AttributeName Language="C#">[System.Serializable]</AttributeName> diff --git a/mdoc/mdoc.Test/AttributeValueFormatterTest.cs b/mdoc/mdoc.Test/AttributeValueFormatterTest.cs new file mode 100644 index 00000000..78d93872 --- /dev/null +++ b/mdoc/mdoc.Test/AttributeValueFormatterTest.cs @@ -0,0 +1,168 @@ +using mdoc.Test.SampleClasses; +using Mono.Cecil; +using Mono.Documentation.Updater; +using Mono.Documentation.Updater.Formatters; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace mdoc.Test +{ + [TestFixture()] + public class AttributeValueFormatterTest : BasicTests + { + [TestCase("PropertyTypeType", "typeof(Mono.Cecil.TypeReference)")] + [TestCase("PropertyTypeTypeWithNull", "null")] + [TestCase("PropertyTypeTypeWithNestedType", "typeof(mdoc.Test.SampleClasses.SomeNestedTypes+NestedClass)")] + [TestCase("PropertyTypeTypeWithUnboundCollection", "typeof(System.Collections.Generic.ICollection<>)")] + [TestCase("PropertyTypeTypeWithCollectionOfInt", "typeof(System.Collections.Generic.ICollection<System.Int32>)")] + [TestCase("PropertyTypeTypeWithUnboundDictionary", "typeof(System.Collections.Generic.IDictionary<,>)")] + [TestCase("PropertyTypeTypeWithDictionaryOfInt", "typeof(System.Collections.Generic.IDictionary<System.Int32,System.Int32>)")] + [TestCase("PropertyTypeTypeWithUnboundCustomGenericType", "typeof(mdoc.Test.SampleClasses.SomeGenericClass<>)")] + [TestCase("PropertyTypeTypeWithCustomGenericTypeOfInt", "typeof(mdoc.Test.SampleClasses.SomeGenericClass<System.Int32>)")] + [TestCase("PropertyTypeTypeWithUnboundNestedGenericType", "typeof(mdoc.Test.SampleClasses.SomeNestedTypes+NestedGenericType<>)")] + [TestCase("PropertyTypeTypeWithNestedGenericTypeOfInt", "typeof(mdoc.Test.SampleClasses.SomeNestedTypes+NestedGenericType<System.Int32>)")] + [TestCase("PropertyTypeTypeWithUnboundInnerNestedGenericType", "typeof(mdoc.Test.SampleClasses.SomeNestedTypes+NestedGenericType<>+InnerNestedGenericType<>)")] + [TestCase("PropertyTypeTypeWithInnerNestedGenericTypeOfInt", "typeof(mdoc.Test.SampleClasses.SomeNestedTypes+NestedGenericType<System.String>+InnerNestedGenericType<System.Int32>)")] + [TestCase("PropertyBoolType", "true")] + [TestCase("PropertySByteType", SByte.MinValue)] + [TestCase("PropertyByteType", Byte.MaxValue)] + [TestCase("PropertyInt16Type", Int16.MinValue)] + [TestCase("PropertyUInt16Type", UInt16.MaxValue)] + [TestCase("PropertyInt32Type", Int32.MinValue)] + [TestCase("PropertyUInt32Type", UInt32.MaxValue)] + [TestCase("PropertyInt64Type", Int64.MinValue)] + [TestCase("PropertyUInt64Type", UInt64.MaxValue)] + [TestCase("PropertySingleType", Single.MinValue)] + [TestCase("PropertyDoubleType", Double.MinValue)] + [TestCase("PropertyCharType", "'C'")] + [TestCase("PropertyStringType", "\"This is a string argument.\"")] + [TestCase("PropertyStringTypeWithEmptyString", "\"\"")] + [TestCase("PropertyStringTypeWithNull", "null")] + [TestCase("PropertyEnumType", "System.ConsoleColor.Red")] + [TestCase("PropertyEnumTypeWithUnknownValue", "(System.ConsoleColor) 2147483647")] + [TestCase("PropertyNestedEnumType", "mdoc.Test.SampleClasses.SomeNestedTypes+NestedEnum.Read")] + [TestCase("PropertyNestedEnumTypeWithUnknownValue", "(mdoc.Test.SampleClasses.SomeNestedTypes+NestedEnum) 2147483647")] + [TestCase("PropertyFlagsEnumType", "System.AttributeTargets.Class | System.AttributeTargets.Enum")] + [TestCase("PropertyFlagsEnumTypeWithAllValue", "System.AttributeTargets.All")] + [TestCase("PropertyFlagsEnumTypeWithUndefineValueZero", "(System.AttributeTargets) 0")] + [TestCase("PropertyDuplicateFlagsEnumTypeWithCombinationValue", "mdoc.Test.SampleClasses.SomeFlagsEnum.Open | mdoc.Test.SampleClasses.SomeFlagsEnum.ReadWrite")] + [TestCase("PropertyNestedFlagsEnumType", "mdoc.Test.SampleClasses.SomeNestedTypes+NestedFlagsEnum.Class | mdoc.Test.SampleClasses.SomeNestedTypes+NestedFlagsEnum.Enum")] + [TestCase("PropertyNestedFlagsEnumTypeWithUndefineValueZero", "(mdoc.Test.SampleClasses.SomeNestedTypes+NestedFlagsEnum) 0")] + [TestCase("PropertyFlagsEnumTypeWithNotApplyAttributeValidTypeAndCombinationValue", "mdoc.Test.SampleClasses.NotApplyAttributeValidFlagsEnum.Class | mdoc.Test.SampleClasses.NotApplyAttributeValidFlagsEnum.Enum")] + [TestCase("PropertyFlagsEnumTypeWithNotApplyAttributeValidTypeAndSingleValue", "mdoc.Test.SampleClasses.NotApplyAttributeValidFlagsEnum.Class")] + [TestCase("PropertyFlagsEnumTypeWithNotApplyAttributeInvalidTypeAndUnknownCombinationValue", "(mdoc.Test.SampleClasses.NotApplyAttributeInvalidFlagsEnum) 5")] + [TestCase("PropertyFlagsEnumTypeWithApplePlatformType", "Platform.Mac_10_8 | Platform.Mac_Arch64")] + [TestCase("PropertyFlagsEnumTypeWithApplePlatformAndNoneValue", "ObjCRuntime.Platform.None")] + [TestCase("PropertyArrayOfIntType", "new System.Int32[] { 0, 0, 7 }")] + [TestCase("PropertyArrayOfIntTypeWithNull", "null")] + [TestCase("PropertyObjectWithNull", "null")] + [TestCase("PropertyObjectWithTypeType", "typeof(Mono.Cecil.TypeReference)")] + [TestCase("PropertyObjectWithNestedTypeType", "typeof(mdoc.Test.SampleClasses.SomeNestedTypes+NestedClass)")] + [TestCase("PropertyObjectWithUnboundCollectionType", "typeof(System.Collections.Generic.ICollection<>)")] + [TestCase("PropertyObjectWithCollectionTypeOfInt", "typeof(System.Collections.Generic.ICollection<System.Int32>)")] + [TestCase("PropertyObjectWithUnboundDictionaryType", "typeof(System.Collections.Generic.IDictionary<,>)")] + [TestCase("PropertyObjectWithDictionaryTypeOfInt", "typeof(System.Collections.Generic.IDictionary<System.Int32,System.Int32>)")] + [TestCase("PropertyObjectWithUnboundCustomGenericType", "typeof(mdoc.Test.SampleClasses.SomeGenericClass<>)")] + [TestCase("PropertyObjectWithCustomGenericTypeOfInt", "typeof(mdoc.Test.SampleClasses.SomeGenericClass<System.Int32>)")] + [TestCase("PropertyObjectWithUnboundNestedGenericType", "typeof(mdoc.Test.SampleClasses.SomeNestedTypes+NestedGenericType<>)")] + [TestCase("PropertyObjectWithNestedGenericTypeOfInt", "typeof(mdoc.Test.SampleClasses.SomeNestedTypes+NestedGenericType<System.Int32>)")] + [TestCase("PropertyObjectWithUnboundInnerNestedGenericType", "typeof(mdoc.Test.SampleClasses.SomeNestedTypes+NestedGenericType<>+InnerNestedGenericType<>)")] + [TestCase("PropertyObjectWithInnerNestedGenericTypeOfInt", "typeof(mdoc.Test.SampleClasses.SomeNestedTypes+NestedGenericType<System.String>+InnerNestedGenericType<System.Int32>)")] + [TestCase("PropertyObjectWithBoolType", "true")] + [TestCase("PropertyObjectWithSByteType", SByte.MinValue)] + [TestCase("PropertyObjectWithByteType", Byte.MaxValue)] + [TestCase("PropertyObjectWithInt16Type", Int16.MinValue)] + [TestCase("PropertyObjectWithUInt16Type", UInt16.MaxValue)] + [TestCase("PropertyObjectWithInt32Type", Int32.MinValue)] + [TestCase("PropertyObjectWithUInt32Type", UInt32.MaxValue)] + [TestCase("PropertyObjectWithInt64Type", Int64.MinValue)] + [TestCase("PropertyObjectWithUInt64Type", UInt64.MaxValue)] + [TestCase("PropertyObjectWithSingleType", Single.MinValue)] + [TestCase("PropertyObjectWithDoubleType", Double.MinValue)] + [TestCase("PropertyObjectWithCharType", "'C'")] + [TestCase("PropertyObjectWithStringType", "\"This is a string argument.\"")] + [TestCase("PropertyObjectWithStringTypeAndEmptyString", "\"\"")] + [TestCase("PropertyObjectWithEnumType", "System.ConsoleColor.Red")] + [TestCase("PropertyObjectWithEnumTypeAndUnknownValue", "(System.ConsoleColor) 2147483647")] + [TestCase("PropertyObjectWithNestedEnumType", "mdoc.Test.SampleClasses.SomeNestedTypes+NestedEnum.Read")] + [TestCase("PropertyObjectWithNestedEnumTypeAndUnknownValue", "(mdoc.Test.SampleClasses.SomeNestedTypes+NestedEnum) 2147483647")] + [TestCase("PropertyObjectWithFlagsEnumType", "System.AttributeTargets.Class | System.AttributeTargets.Enum")] + [TestCase("PropertyObjectWithFlagsEnumTypeAndAllValue", "System.AttributeTargets.All")] + [TestCase("PropertyObjectWithFlagsEnumTypeAndUndefineValueZero", "(System.AttributeTargets) 0")] + [TestCase("PropertyObjectWithDuplicateFlagsEnumTypeAndCombinationValue", "mdoc.Test.SampleClasses.SomeFlagsEnum.Open | mdoc.Test.SampleClasses.SomeFlagsEnum.ReadWrite")] + [TestCase("PropertyObjectWithNestedFlagsEnumType", "mdoc.Test.SampleClasses.SomeNestedTypes+NestedFlagsEnum.Class | mdoc.Test.SampleClasses.SomeNestedTypes+NestedFlagsEnum.Enum")] + [TestCase("PropertyObjectWithNestedFlagsEnumTypeAndUndefineValueZero", "(mdoc.Test.SampleClasses.SomeNestedTypes+NestedFlagsEnum) 0")] + [TestCase("PropertyObjectWithNotApplyAttributeValidFlagsEnumTypeAndCombinationValue", "mdoc.Test.SampleClasses.NotApplyAttributeValidFlagsEnum.Class | mdoc.Test.SampleClasses.NotApplyAttributeValidFlagsEnum.Enum")] + [TestCase("PropertyObjectWithNotApplyAttributeValidFlagsEnumTypeAndSingleValue", "mdoc.Test.SampleClasses.NotApplyAttributeValidFlagsEnum.Class")] + [TestCase("PropertyObjectWithNotApplyAttributeInvalidFlagsEnumTypeAndUnknownCombinationValue", "(mdoc.Test.SampleClasses.NotApplyAttributeInvalidFlagsEnum) 5")] + [TestCase("PropertyObjectWithApplePlatformFlagsEnumType", "Platform.Mac_10_8 | Platform.Mac_Arch64")] + [TestCase("PropertyObjectWithApplePlatformFlagsEnumTypeAndNoneValue", "ObjCRuntime.Platform.None")] + [TestCase("PropertyObjectWithArrayOfIntType", "new System.Int32[] { 0, 0, 7 }")] + public void TestFormatValueWithDifferentTypes(string methodName, object argumentValue) + { + TestAttributeValueFormatter(typeof(SomeAttribute), methodName, argumentValue); + } + + [TestCase("GetEnumerator", "typeof(mdoc.Test.SampleClasses.SomeIteratorStateMachine<,>+<GetEnumerator>d__0)", typeof(SomeIteratorStateMachine<,>))] + [TestCase("GetEnumerator", "typeof(mdoc.Test.SampleClasses.SomeIteratorStateMachine<,>+SomeNestedIteratorStateMachine<,>+<GetEnumerator>d__0)", typeof(SomeIteratorStateMachine<,>.SomeNestedIteratorStateMachine<,>))] + [TestCase("WithParameterType", "typeof(mdoc.Test.SampleClasses.SomeIteratorStateMachine<,>+<WithParameterType>d__2<,>)", typeof(SomeIteratorStateMachine<,>))] + [TestCase("WithParameterType", "typeof(mdoc.Test.SampleClasses.SomeIteratorStateMachine<,>+SomeNestedIteratorStateMachine<,>+<WithParameterType>d__2<,>)", typeof(SomeIteratorStateMachine<,>.SomeNestedIteratorStateMachine<,>))] + public void TestFormartValueWithIteratorStateMachineAttribute(string methodName, object argumentValue, Type type) + { + TestAttributeValueFormatter(type, methodName, argumentValue); + } + + private void TestAttributeValueFormatter(Type type, string memberName, object expectedValue) + { + var (argumentType, argumentValue) = GetAttributeArguments(type, memberName); + + var attributeFormatter = new AttributeValueFormatter(); + var formatValue = attributeFormatter.Format(argumentType, argumentValue); + + Assert.AreEqual(expectedValue.ToString(), formatValue); + } + + private (TypeReference argumentType, object argumentValue) GetAttributeArguments(Type type, string memberName) + { + var methodDefinition = GetMethod(type, memberName); + var methodAttribute = AttributeFormatter.GetCustomAttributes(methodDefinition).First(); + CustomAttribute customAttribute = methodAttribute.Item1; + + var customAttributeList = new List<(TypeReference, object)>(); + for (int i = 0; i < customAttribute.ConstructorArguments.Count; ++i) + { + customAttributeList.Add((customAttribute.ConstructorArguments[i].Type, customAttribute.ConstructorArguments[i].Value)); + } + + foreach (var item in GetAttributeArgumentsFromFieldsAndProperties(customAttribute)) + { + customAttributeList.Add((item.argumentType, item.argumentValue)); + } + + return customAttributeList.First(); + } + + private IEnumerable<(string argumentName, TypeReference argumentType, object argumentValue)> GetAttributeArgumentsFromFieldsAndProperties(CustomAttribute customAttribute) + { + return (from namedArg in customAttribute.Fields + select (namedArg.Name, namedArg.Argument.Type, namedArg.Argument.Value)) + .Concat(from namedArg in customAttribute.Properties + select (namedArg.Name, namedArg.Argument.Type, namedArg.Argument.Value)) + .OrderBy(v => v.Name); + } + + protected override TypeDefinition GetType(Type type) + { + var moduleName = type.Module.FullyQualifiedName; + return GetType(moduleName, ConvertNestedTypeFullName(type.FullName)); + } + + private string ConvertNestedTypeFullName(string fullName) + { + // Simply of implementation for help nested class convert the full name from .NET style to mono.cecil style. + return fullName.Replace("+", "/"); + } + } +} diff --git a/mdoc/mdoc.Test/SampleClasses/ApplePlatformEnum.cs b/mdoc/mdoc.Test/SampleClasses/ApplePlatformEnum.cs new file mode 100644 index 00000000..490c7978 --- /dev/null +++ b/mdoc/mdoc.Test/SampleClasses/ApplePlatformEnum.cs @@ -0,0 +1,48 @@ +using System; + +namespace ObjCRuntime +{ + [Flags] + public enum Platform : ulong + { + None = 0, + iOS_2_0 = 0x0000000000020000, + iOS_2_2 = 0x0000000000020200, + iOS_3_0 = 0x0000000000030000, + iOS_3_1 = 0x0000000000030100, + iOS_3_2 = 0x0000000000030200, + iOS_4_0 = 0x0000000000040000, + iOS_4_1 = 0x0000000000040100, + iOS_4_2 = 0x0000000000040200, + iOS_4_3 = 0x0000000000040300, + iOS_5_0 = 0x0000000000050000, + iOS_5_1 = 0x0000000000050100, + iOS_6_0 = 0x0000000000060000, + iOS_6_1 = 0x0000000000060100, + iOS_7_0 = 0x0000000000070000, + iOS_7_1 = 0x0000000000070100, + iOS_8_0 = 0x0000000000080000, + iOS_8_1 = 0x0000000000080100, + iOS_8_2 = 0x0000000000080200, + iOS_8_3 = 0x0000000000080300, + Mac_10_0 = 0x000A000000000000, + Mac_10_1 = 0x000A010000000000, + Mac_10_2 = 0x000A020000000000, + Mac_10_3 = 0x000A030000000000, + Mac_10_4 = 0x000A040000000000, + Mac_10_5 = 0x000A050000000000, + Mac_10_6 = 0x000A060000000000, + Mac_10_7 = 0x000A070000000000, + Mac_10_8 = 0x000A080000000000, + Mac_10_9 = 0x000A090000000000, + Mac_10_10 = 0x000A0A0000000000, + iOS_Version = 0x0000000000FFFFFF, + Mac_Version = 0x00FFFFFF00000000, + Mac_Arch32 = 0x0100000000000000, + Mac_Arch64 = 0x0200000000000000, + Mac_Arch = 0xFF00000000000000, + iOS_Arch32 = 0x0000000001000000, + iOS_Arch64 = 0x0000000002000000, + iOS_Arch = 0x00000000FF000000 + } +} diff --git a/mdoc/mdoc.Test/SampleClasses/AttributeDataTypeAttribute.cs b/mdoc/mdoc.Test/SampleClasses/AttributeDataTypeAttribute.cs new file mode 100644 index 00000000..ce49992e --- /dev/null +++ b/mdoc/mdoc.Test/SampleClasses/AttributeDataTypeAttribute.cs @@ -0,0 +1,57 @@ +using System; + +namespace mdoc.Test.SampleClasses +{ + public class AttributeDataTypeAttribute : Attribute + { + public object ObjectType { get; set; } + + public Type TypeType { get; set; } + + public bool BoolType { get; set; } + + public SByte SByteType { get; set; } + + public Byte ByteType { get; set; } + + public Int16 Int16Type { get; set; } + + public UInt16 UInt16Type { get; set; } + + public Int32 Int32Type { get; set; } + + public Int32? NullableOfInt32Type { get; set; } + + public UInt32 UInt32Type { get; set; } + + public Int64 Int64Type { get; set; } + + public UInt64 UInt64Type { get; set; } + + public Single SingleType { get; set; } + + public Double DoubleType { get; set; } + + public char CharType { get; set; } + + public string StringType { get; set; } + + public int[] ArrayOfIntType { get; set; } + + public ConsoleColor EnumType { get; set; } + + public SomeNestedTypes.NestedEnum NestedEnumType { get; set; } + + public SomeNestedTypes.NestedFlagsEnum NestedFlagsEnumType { get; set; } + + public SomeFlagsEnum DuplicateFlagsEnumType { get; set; } + + public AttributeTargets FlagsEnumType { get; set; } + + public NotApplyAttributeValidFlagsEnum NotApplyAttributeFlagsEnumType { get; set; } + + public NotApplyAttributeInvalidFlagsEnum NotApplyAttributeInvalidFlagsEnumType { get; set; } + + public ObjCRuntime.Platform ApplePlatformFlagsEnumType { get; set; } + } +} diff --git a/mdoc/mdoc.Test/SampleClasses/NotApplyAttributeInvalidFlagsEnum.cs b/mdoc/mdoc.Test/SampleClasses/NotApplyAttributeInvalidFlagsEnum.cs new file mode 100644 index 00000000..e0ad0455 --- /dev/null +++ b/mdoc/mdoc.Test/SampleClasses/NotApplyAttributeInvalidFlagsEnum.cs @@ -0,0 +1,10 @@ +namespace mdoc.Test.SampleClasses +{ + public enum NotApplyAttributeInvalidFlagsEnum + { + None = 0, + Read = 1, + Write = 2, + ReadWrite = 3 + } +} diff --git a/mdoc/mdoc.Test/SampleClasses/NotApplyAttributeValidFlagsEnum.cs b/mdoc/mdoc.Test/SampleClasses/NotApplyAttributeValidFlagsEnum.cs new file mode 100644 index 00000000..de4fa77e --- /dev/null +++ b/mdoc/mdoc.Test/SampleClasses/NotApplyAttributeValidFlagsEnum.cs @@ -0,0 +1,12 @@ +namespace mdoc.Test.SampleClasses +{ + public enum NotApplyAttributeValidFlagsEnum + { + None = 0, + Assembly = 1, + Module = 2, + Class = 4, + Struct = 8, + Enum = 16 + } +} diff --git a/mdoc/mdoc.Test/SampleClasses/SomeAttribute.cs b/mdoc/mdoc.Test/SampleClasses/SomeAttribute.cs new file mode 100644 index 00000000..2b7850ce --- /dev/null +++ b/mdoc/mdoc.Test/SampleClasses/SomeAttribute.cs @@ -0,0 +1,450 @@ +using Mono.Cecil; +using System; +using System.Collections.Generic; + +namespace mdoc.Test.SampleClasses +{ + public class SomeAttribute + { + [AttributeDataType(TypeType = typeof(TypeReference))] + public void PropertyTypeType() + { + } + + [AttributeDataType(TypeType = null)] + public void PropertyTypeTypeWithNull() + { + } + + [AttributeDataType(TypeType = typeof(SomeNestedTypes.NestedClass))] + public void PropertyTypeTypeWithNestedType() + { + } + + [AttributeDataType(TypeType = typeof(ICollection<>))] + public void PropertyTypeTypeWithUnboundCollection() + { + } + + [AttributeDataType(TypeType = typeof(ICollection<int>))] + public void PropertyTypeTypeWithCollectionOfInt() + { + } + + [AttributeDataType(TypeType = typeof(IDictionary<,>))] + public void PropertyTypeTypeWithUnboundDictionary() + { + } + + [AttributeDataType(TypeType = typeof(IDictionary<int, int>))] + public void PropertyTypeTypeWithDictionaryOfInt() + { + } + + [AttributeDataType(TypeType = typeof(SomeGenericClass<>))] + public void PropertyTypeTypeWithUnboundCustomGenericType() + { + } + + [AttributeDataType(TypeType = typeof(SomeGenericClass<int>))] + public void PropertyTypeTypeWithCustomGenericTypeOfInt() + { + } + + [AttributeDataType(TypeType = typeof(SomeNestedTypes.NestedGenericType<>))] + public void PropertyTypeTypeWithUnboundNestedGenericType() + { + } + + [AttributeDataType(TypeType = typeof(SomeNestedTypes.NestedGenericType<int>))] + public void PropertyTypeTypeWithNestedGenericTypeOfInt() + { + } + + + [AttributeDataType(TypeType = typeof(SomeNestedTypes.NestedGenericType<>.InnerNestedGenericType<>))] + public void PropertyTypeTypeWithUnboundInnerNestedGenericType() + { + } + + [AttributeDataType(TypeType = typeof(SomeNestedTypes.NestedGenericType<string>.InnerNestedGenericType<int>))] + public void PropertyTypeTypeWithInnerNestedGenericTypeOfInt() + { + } + + [AttributeDataType(BoolType = true)] + public void PropertyBoolType() + { + } + + [AttributeDataType(SByteType = SByte.MinValue)] + public void PropertySByteType() + { + } + + [AttributeDataType(ByteType = Byte.MaxValue)] + public void PropertyByteType() + { + } + + [AttributeDataType(Int16Type = Int16.MinValue)] + public void PropertyInt16Type() + { + } + + [AttributeDataType(UInt16Type = UInt16.MaxValue)] + public void PropertyUInt16Type() + { + } + + [AttributeDataType(Int32Type = Int32.MinValue)] + public void PropertyInt32Type() + { + } + + [AttributeDataType(UInt32Type = UInt32.MaxValue)] + public void PropertyUInt32Type() + { + } + + [AttributeDataType(Int64Type = Int64.MinValue)] + public void PropertyInt64Type() + { + } + + [AttributeDataType(UInt64Type = UInt64.MaxValue)] + public void PropertyUInt64Type() + { + } + + [AttributeDataType(SingleType = Single.MinValue)] + public void PropertySingleType() + { + } + + [AttributeDataType(DoubleType = Double.MinValue)] + public void PropertyDoubleType() + { + } + + [AttributeDataType(CharType = 'C')] + public void PropertyCharType() + { + } + + [AttributeDataType(StringType = "This is a string argument.")] + public void PropertyStringType() + { + } + + [AttributeDataType(StringType = null)] + public void PropertyStringTypeWithNull() + { + } + + [AttributeDataType(StringType = "")] + public void PropertyStringTypeWithEmptyString() + { + } + + [AttributeDataType(ArrayOfIntType = new[] { 0, 0, 7 })] + public void PropertyArrayOfIntType() + { + } + + [AttributeDataType(ArrayOfIntType = null)] + public void PropertyArrayOfIntTypeWithNull() + { + } + + [AttributeDataType(EnumType = ConsoleColor.Red)] + public void PropertyEnumType() + { + } + + [AttributeDataType(EnumType = (ConsoleColor)int.MaxValue)] + public void PropertyEnumTypeWithUnknownValue() + { + } + + [AttributeDataType(NestedEnumType = SomeNestedTypes.NestedEnum.Read)] + public void PropertyNestedEnumType() + { + } + + [AttributeDataType(NestedEnumType = (SomeNestedTypes.NestedEnum)int.MaxValue)] + public void PropertyNestedEnumTypeWithUnknownValue() + { + } + + [AttributeDataType(FlagsEnumType = AttributeTargets.Class | AttributeTargets.Enum)] + public void PropertyFlagsEnumType() + { + } + + [AttributeDataType(FlagsEnumType = AttributeTargets.All)] + public void PropertyFlagsEnumTypeWithAllValue() + { + } + + [AttributeDataType(FlagsEnumType = (AttributeTargets)0)] + public void PropertyFlagsEnumTypeWithUndefineValueZero() + { + } + + [AttributeDataType(DuplicateFlagsEnumType = SomeFlagsEnum.Read | SomeFlagsEnum.Write | SomeFlagsEnum.Open)] + public void PropertyDuplicateFlagsEnumTypeWithCombinationValue() + { + } + + [AttributeDataType(NestedFlagsEnumType = SomeNestedTypes.NestedFlagsEnum.Class | SomeNestedTypes.NestedFlagsEnum.Enum)] + public void PropertyNestedFlagsEnumType() + { + } + + [AttributeDataType(NestedFlagsEnumType = (SomeNestedTypes.NestedFlagsEnum)0)] + public void PropertyNestedFlagsEnumTypeWithUndefineValueZero() + { + } + + [AttributeDataType(NotApplyAttributeFlagsEnumType = NotApplyAttributeValidFlagsEnum.Class | NotApplyAttributeValidFlagsEnum.Enum)] + public void PropertyFlagsEnumTypeWithNotApplyAttributeValidTypeAndCombinationValue() + { + } + + [AttributeDataType(NotApplyAttributeFlagsEnumType = NotApplyAttributeValidFlagsEnum.Class)] + public void PropertyFlagsEnumTypeWithNotApplyAttributeValidTypeAndSingleValue() + { + } + + [AttributeDataType(NotApplyAttributeInvalidFlagsEnumType = (NotApplyAttributeInvalidFlagsEnum)5)] + public void PropertyFlagsEnumTypeWithNotApplyAttributeInvalidTypeAndUnknownCombinationValue() + { + } + + [AttributeDataType(ApplePlatformFlagsEnumType = ObjCRuntime.Platform.Mac_10_8 | ObjCRuntime.Platform.Mac_Arch64)] + public void PropertyFlagsEnumTypeWithApplePlatformType() + { + } + + [AttributeDataType(ApplePlatformFlagsEnumType = ObjCRuntime.Platform.None)] + public void PropertyFlagsEnumTypeWithApplePlatformAndNoneValue() + { + } + + [AttributeDataType(ObjectType = null)] + public void PropertyObjectWithNull() + { + } + + [AttributeDataType(ObjectType = typeof(TypeReference))] + public void PropertyObjectWithTypeType() + { + } + + [AttributeDataType(ObjectType = typeof(SomeNestedTypes.NestedClass))] + public void PropertyObjectWithNestedTypeType() + { + } + + [AttributeDataType(ObjectType = typeof(ICollection<>))] + public void PropertyObjectWithUnboundCollectionType() + { + } + + [AttributeDataType(ObjectType = typeof(ICollection<int>))] + public void PropertyObjectWithCollectionTypeOfInt() + { + } + + [AttributeDataType(ObjectType = typeof(IDictionary<,>))] + public void PropertyObjectWithUnboundDictionaryType() + { + } + + [AttributeDataType(ObjectType = typeof(IDictionary<int, int>))] + public void PropertyObjectWithDictionaryTypeOfInt() + { + } + + [AttributeDataType(ObjectType = typeof(SomeGenericClass<>))] + public void PropertyObjectWithUnboundCustomGenericType() + { + } + + [AttributeDataType(ObjectType = typeof(SomeGenericClass<int>))] + public void PropertyObjectWithCustomGenericTypeOfInt() + { + } + + [AttributeDataType(ObjectType = typeof(SomeNestedTypes.NestedGenericType<>))] + public void PropertyObjectWithUnboundNestedGenericType() + { + } + + [AttributeDataType(ObjectType = typeof(SomeNestedTypes.NestedGenericType<int>))] + public void PropertyObjectWithNestedGenericTypeOfInt() + { + } + + [AttributeDataType(ObjectType = typeof(SomeNestedTypes.NestedGenericType<>.InnerNestedGenericType<>))] + public void PropertyObjectWithUnboundInnerNestedGenericType() + { + } + + [AttributeDataType(ObjectType = typeof(SomeNestedTypes.NestedGenericType<string>.InnerNestedGenericType<int>))] + public void PropertyObjectWithInnerNestedGenericTypeOfInt() + { + } + + [AttributeDataType(ObjectType = true)] + public void PropertyObjectWithBoolType() + { + } + + [AttributeDataType(ObjectType = SByte.MinValue)] + public void PropertyObjectWithSByteType() + { + } + + [AttributeDataType(ObjectType = Byte.MaxValue)] + public void PropertyObjectWithByteType() + { + } + + [AttributeDataType(ObjectType = Int16.MinValue)] + public void PropertyObjectWithInt16Type() + { + } + + [AttributeDataType(ObjectType = UInt16.MaxValue)] + public void PropertyObjectWithUInt16Type() + { + } + + [AttributeDataType(ObjectType = Int32.MinValue)] + public void PropertyObjectWithInt32Type() + { + } + + [AttributeDataType(ObjectType = UInt32.MaxValue)] + public void PropertyObjectWithUInt32Type() + { + } + + [AttributeDataType(ObjectType = Int64.MinValue)] + public void PropertyObjectWithInt64Type() + { + } + + [AttributeDataType(ObjectType = UInt64.MaxValue)] + public void PropertyObjectWithUInt64Type() + { + } + + [AttributeDataType(ObjectType = Single.MinValue)] + public void PropertyObjectWithSingleType() + { + } + + [AttributeDataType(ObjectType = Double.MinValue)] + public void PropertyObjectWithDoubleType() + { + } + + [AttributeDataType(ObjectType = 'C')] + public void PropertyObjectWithCharType() + { + } + + [AttributeDataType(ObjectType = "This is a string argument.")] + public void PropertyObjectWithStringType() + { + } + + [AttributeDataType(ObjectType = "")] + public void PropertyObjectWithStringTypeAndEmptyString() + { + } + + [AttributeDataType(ObjectType = new[] { 0, 0, 7 })] + public void PropertyObjectWithArrayOfIntType() + { + } + + [AttributeDataType(ObjectType = ConsoleColor.Red)] + public void PropertyObjectWithEnumType() + { + } + + [AttributeDataType(ObjectType = (ConsoleColor)int.MaxValue)] + public void PropertyObjectWithEnumTypeAndUnknownValue() + { + } + + [AttributeDataType(ObjectType = SomeNestedTypes.NestedEnum.Read)] + public void PropertyObjectWithNestedEnumType() + { + } + + [AttributeDataType(ObjectType = (SomeNestedTypes.NestedEnum)int.MaxValue)] + public void PropertyObjectWithNestedEnumTypeAndUnknownValue() + { + } + + [AttributeDataType(ObjectType = AttributeTargets.Class | AttributeTargets.Enum)] + public void PropertyObjectWithFlagsEnumType() + { + } + + [AttributeDataType(ObjectType = AttributeTargets.All)] + public void PropertyObjectWithFlagsEnumTypeAndAllValue() + { + } + + [AttributeDataType(ObjectType = (AttributeTargets)0)] + public void PropertyObjectWithFlagsEnumTypeAndUndefineValueZero() + { + } + + [AttributeDataType(ObjectType = SomeFlagsEnum.Read | SomeFlagsEnum.Write | SomeFlagsEnum.Open)] + public void PropertyObjectWithDuplicateFlagsEnumTypeAndCombinationValue() + { + } + + [AttributeDataType(ObjectType = SomeNestedTypes.NestedFlagsEnum.Class | SomeNestedTypes.NestedFlagsEnum.Enum)] + public void PropertyObjectWithNestedFlagsEnumType() + { + } + + [AttributeDataType(ObjectType = (SomeNestedTypes.NestedFlagsEnum)0)] + public void PropertyObjectWithNestedFlagsEnumTypeAndUndefineValueZero() + { + } + + [AttributeDataType(ObjectType = NotApplyAttributeValidFlagsEnum.Class | NotApplyAttributeValidFlagsEnum.Enum)] + public void PropertyObjectWithNotApplyAttributeValidFlagsEnumTypeAndCombinationValue() + { + } + + [AttributeDataType(ObjectType = NotApplyAttributeValidFlagsEnum.Class)] + public void PropertyObjectWithNotApplyAttributeValidFlagsEnumTypeAndSingleValue() + { + } + + [AttributeDataType(ObjectType = (NotApplyAttributeInvalidFlagsEnum)5)] + public void PropertyObjectWithNotApplyAttributeInvalidFlagsEnumTypeAndUnknownCombinationValue() + { + } + + [AttributeDataType(ObjectType = ObjCRuntime.Platform.Mac_10_8 | ObjCRuntime.Platform.Mac_Arch64)] + public void PropertyObjectWithApplePlatformFlagsEnumType() + { + } + + [AttributeDataType(ObjectType = ObjCRuntime.Platform.None)] + public void PropertyObjectWithApplePlatformFlagsEnumTypeAndNoneValue() + { + } + } +} diff --git a/mdoc/mdoc.Test/SampleClasses/SomeFlagsEnum.cs b/mdoc/mdoc.Test/SampleClasses/SomeFlagsEnum.cs new file mode 100644 index 00000000..a95365d3 --- /dev/null +++ b/mdoc/mdoc.Test/SampleClasses/SomeFlagsEnum.cs @@ -0,0 +1,14 @@ +using System; + +namespace mdoc.Test.SampleClasses +{ + [Flags] + public enum SomeFlagsEnum + { + Read = 1, + Write = 2, + ReadWrite = Read | Write, + Open = 4, + Close = 8 + } +} diff --git a/mdoc/mdoc.Test/SampleClasses/SomeIteratorStateMachine.cs b/mdoc/mdoc.Test/SampleClasses/SomeIteratorStateMachine.cs new file mode 100644 index 00000000..3dbf6032 --- /dev/null +++ b/mdoc/mdoc.Test/SampleClasses/SomeIteratorStateMachine.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace mdoc.Test.SampleClasses +{ + public class SomeIteratorStateMachine<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> + { + public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() + { + yield return new KeyValuePair<TKey, TValue>(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + public IEnumerator<KeyValuePair<T1, T2>> WithParameterType<T1, T2>() + { + yield return new KeyValuePair<T1, T2>(); + + } + + public class SomeNestedIteratorStateMachine<NestedTKey, NestedTValue> : IEnumerable<KeyValuePair<NestedTKey, NestedTValue>> + { + public IEnumerator<KeyValuePair<NestedTKey, NestedTValue>> GetEnumerator() + { + yield return new KeyValuePair<NestedTKey, NestedTValue>(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + public IEnumerator<KeyValuePair<NestedT1, NestedT2>> WithParameterType<NestedT1, NestedT2>() + { + yield return new KeyValuePair<NestedT1, NestedT2>(); + + } + } + } +} diff --git a/mdoc/mdoc.Test/SampleClasses/SomeNestedTypes.cs b/mdoc/mdoc.Test/SampleClasses/SomeNestedTypes.cs new file mode 100644 index 00000000..1c8f332e --- /dev/null +++ b/mdoc/mdoc.Test/SampleClasses/SomeNestedTypes.cs @@ -0,0 +1,34 @@ +using System; + +namespace mdoc.Test.SampleClasses +{ + public class SomeNestedTypes + { + public class NestedClass + { + } + + public class NestedGenericType<T> + { + public class InnerNestedGenericType<T1> + { + } + } + + public enum NestedEnum + { + Read = 1, + Write = 2, + } + + [Flags] + public enum NestedFlagsEnum + { + Assembly = 1, + Module = 2, + Class = 4, + Struct = 8, + Enum = 16 + } + } +} diff --git a/mdoc/mdoc.Test/mdoc.Test.csproj b/mdoc/mdoc.Test/mdoc.Test.csproj index 5daf4464..11960802 100644 --- a/mdoc/mdoc.Test/mdoc.Test.csproj +++ b/mdoc/mdoc.Test/mdoc.Test.csproj @@ -72,6 +72,7 @@ <Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="AttributeValueFormatterTest.cs" />
<Compile Include="BasicFormatterTests.cs" />
<Compile Include="BasicTests.cs" />
<Compile Include="CppWinRtMembersTests.cs" />
@@ -94,11 +95,19 @@ <Compile Include="MDocFileSourceTests.cs" />
<Compile Include="MDocUpdaterTests.cs" />
<Compile Include="NullableReferenceTypesTests.cs" />
+ <Compile Include="SampleClasses\ApplePlatformEnum.cs" />
<Compile Include="SampleClasses\EiiImplementclass.cs" />
<Compile Include="SampleClasses\Interface_A.cs" />
<Compile Include="SampleClasses\Interface_B.cs" />
<Compile Include="SampleClasses\InternalEIICalss.cs" />
+ <Compile Include="SampleClasses\SomeFlagsEnum.cs" />
+ <Compile Include="SampleClasses\SomeIteratorStateMachine.cs" />
+ <Compile Include="SampleClasses\NotApplyAttributeValidFlagsEnum.cs" />
+ <Compile Include="SampleClasses\NotApplyAttributeInvalidFlagsEnum.cs" />
<Compile Include="SampleClasses\NullablesAndTuples.cs" />
+ <Compile Include="SampleClasses\AttributeDataTypeAttribute.cs" />
+ <Compile Include="SampleClasses\SomeAttribute.cs" />
+ <Compile Include="SampleClasses\SomeNestedTypes.cs" />
<Compile Include="SampleClasses\StaticClass.cs" />
<Compile Include="SampleClasses\TestClassThree.cs" />
<Compile Include="SpanSpecial.cs" />
diff --git a/mdoc/mdoc.csproj b/mdoc/mdoc.csproj index f9b0d745..9de40804 100644 --- a/mdoc/mdoc.csproj +++ b/mdoc/mdoc.csproj @@ -59,7 +59,6 @@ <Compile Include="Mono.Documentation\Framework\FrameworkTypeModel.cs" />
<Compile Include="Mono.Documentation\Framework\FrameworkNamespaceModel.cs" />
<Compile Include="Mono.Documentation\Updater\IAttributeParserContext.cs" />
- <Compile Include="Mono.Documentation\Updater\Formatters\AttributeFormatters\ApplePlatformEnumFormatter.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\AttributeFormatters\AttributeFormatter.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\AttributeFormatters\CppWinRtAttributeFormatter.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\AttributeFormatters\FSharpAttributeFormatter.cs" />
@@ -81,12 +80,9 @@ <Compile Include="Mono.Documentation\Updater\Formatters\CSharpMemberFormatter.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\SlashDocCSharpMemberFormatter.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\MsxdocSlashDocMemberFormatter.cs" />
- <Compile Include="Mono.Documentation\Updater\Formatters\AttributeFormatters\StandardFlagsEnumFormatter.cs" />
- <Compile Include="Mono.Documentation\Updater\Formatters\AttributeFormatters\DefaultAttributeValueFormatter.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\AttributeFormatters\AttributeValueFormatter.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\VBFullMemberFormatter.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\VBMemberFormatter.cs" />
- <Compile Include="Mono.Documentation\Updater\ResolvedTypeInfo.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\FileNameMemberFormatter.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\SlashDocMemberFormatter.cs" />
<Compile Include="Mono.Documentation\Updater\Formatters\DocTypeMemberFormatter.cs" />
|