Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/api-doc-tools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMin Huang <huangmin@microsoft.com>2022-02-23 06:04:18 +0300
committerGitHub <noreply@github.com>2022-02-23 06:04:18 +0300
commitecc38372e51f5ef79f965f143dcb762803c8e2e1 (patch)
treed3532b05ec4a47edbd046588072d925be4d86069
parent7199864055fee49ea45aecf0791b4fa61b4febe1 (diff)
feat#550375: Support ref and ref readonly return (#611)
* Support ref and ref readonly return * Add test cases * Update test
-rw-r--r--mdoc/Consts.cs1
-rw-r--r--mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs49
-rw-r--r--mdoc/Mono.Documentation/Updater/Formatters/CppFormatters/CppFullMemberFormatter.cs5
-rw-r--r--mdoc/Mono.Documentation/Updater/Formatters/FSharpFormatter.cs5
-rw-r--r--mdoc/Mono.Documentation/Updater/Formatters/MemberFormatter.cs17
-rw-r--r--mdoc/Mono.Documentation/Updater/Formatters/MsxdocSlashDocMemberFormatter.cs5
-rw-r--r--mdoc/Mono.Documentation/Updater/Formatters/SlashDocMemberFormatter.cs2
-rw-r--r--mdoc/mdoc.Test/BasicTests.cs9
-rw-r--r--mdoc/mdoc.Test/FormatterTests.cs30
-rw-r--r--mdoc/mdoc.Test/SampleClasses/ReadonlyRefClass.cs23
10 files changed, 92 insertions, 54 deletions
diff --git a/mdoc/Consts.cs b/mdoc/Consts.cs
index 52889455..db2772ed 100644
--- a/mdoc/Consts.cs
+++ b/mdoc/Consts.cs
@@ -48,5 +48,6 @@ namespace Mono.Documentation
public const string CompilerGeneratedAttribute = "System.Runtime.CompilerServices.CompilerGeneratedAttribute";
public const string IsByRefLikeAttribute = "System.Runtime.CompilerServices.IsByRefLikeAttribute";
public const string IsReadOnlyAttribute = "System.Runtime.CompilerServices.IsReadOnlyAttribute";
+ public const string InAttribute = "System.Runtime.InteropServices.InAttribute";
}
}
diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs
index 4f4f287a..37c0da24 100644
--- a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs
+++ b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs
@@ -517,18 +517,6 @@ namespace Mono.Documentation.Updater.Formatters
if (method.IsFinal) modifiers += " sealed";
if (modifiers == " virtual sealed") modifiers = "";
- if ((method.ReturnType.IsRequiredModifier
- && ((RequiredModifierType)method.ReturnType).ElementType.IsByReference)
- || method.ReturnType.IsByReference)
- {
- modifiers += " ref";
- }
-
- if (method.ReturnType.IsRequiredModifier && DocUtils.HasCustomAttribute(method.MethodReturnType, Consts.IsReadOnlyAttribute))
- {
- modifiers += " readonly";
- }
-
switch (method.Name)
{
case "op_Implicit":
@@ -542,6 +530,24 @@ namespace Mono.Documentation.Updater.Formatters
return buf.Append (modifiers);
}
+ protected override StringBuilder AppendRefTypeName(StringBuilder buf, ByReferenceType type, IAttributeParserContext context)
+ {
+ buf.Append("ref ");
+ return base.AppendRefTypeName(buf, type, context);
+ }
+
+ protected override StringBuilder AppendRequiredModifierTypeName(
+ StringBuilder buf, RequiredModifierType type, IAttributeParserContext context)
+ {
+ if (type.ModifierType.FullName == Consts.InAttribute && type.ElementType is ByReferenceType refType)
+ {
+ buf.Append("ref readonly ");
+ return _AppendTypeName(buf, refType.ElementType, context);
+ }
+
+ return base.AppendRequiredModifierTypeName(buf, type, context);
+ }
+
protected override StringBuilder AppendGenericMethod (StringBuilder buf, MethodDefinition method)
{
if (method.IsGenericMethod ())
@@ -585,19 +591,23 @@ namespace Mono.Documentation.Updater.Formatters
private StringBuilder AppendParameter (StringBuilder buf, ParameterDefinition parameter)
{
- if (parameter.ParameterType is ByReferenceType)
+ TypeReference parameterType = parameter.ParameterType;
+
+ if (parameterType is ByReferenceType byReferenceType)
{
if (parameter.IsOut)
{
buf.Append ("out ");
}
+ else if(parameter.IsIn)
+ {
+ buf.Append("in ");
+ }
else
{
- if (parameter.HasCustomAttributes && parameter.CustomAttributes.Any (ca => ca.AttributeType.Name == "IsReadOnlyAttribute"))
- buf.Append ("in ");
- else
- buf.Append ("ref ");
+ buf.Append("ref ");
}
+ parameterType = byReferenceType.ElementType;
}
if (parameter.HasCustomAttributes)
@@ -609,7 +619,7 @@ namespace Mono.Documentation.Updater.Formatters
var context = AttributeParserContext.Create (parameter);
var isNullableType = context.IsNullable ();
- buf.Append (GetTypeName (parameter.ParameterType, context));
+ buf.Append (GetTypeName (parameterType, context));
buf.Append (GetTypeNullableSymbol (parameter.ParameterType, isNullableType));
buf.Append (" ");
buf.Append (parameter.Name);
@@ -673,9 +683,6 @@ namespace Mono.Documentation.Updater.Formatters
modifiers = "";
buf.Append (modifiers).Append (' ');
- if (property.PropertyType.IsByReference)
- buf.Append("ref ");
-
var context = AttributeParserContext.Create (property);
var isNullableType = context.IsNullable ();
var propertyReturnTypeName = GetTypeName (property.PropertyType, context);
diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CppFormatters/CppFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CppFormatters/CppFullMemberFormatter.cs
index 9bb44003..516c9a93 100644
--- a/mdoc/Mono.Documentation/Updater/Formatters/CppFormatters/CppFullMemberFormatter.cs
+++ b/mdoc/Mono.Documentation/Updater/Formatters/CppFormatters/CppFullMemberFormatter.cs
@@ -776,10 +776,9 @@ namespace Mono.Documentation.Updater.Formatters.CppFormatters
return buf;
}
- protected override StringBuilder AppendRefTypeName(StringBuilder buf, TypeReference type, IAttributeParserContext context)
+ protected override StringBuilder AppendRefTypeName(StringBuilder buf, ByReferenceType type, IAttributeParserContext context)
{
- TypeSpecification spec = type as TypeSpecification;
- _AppendTypeName(buf, spec != null ? spec.ElementType : type.GetElementType(), context);
+ _AppendTypeName(buf, type.ElementType, context);
AppendHat(buf, type);
buf.Append(RefTypeModifier);
diff --git a/mdoc/Mono.Documentation/Updater/Formatters/FSharpFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/FSharpFormatter.cs
index 25b78bf8..f810f1dd 100644
--- a/mdoc/Mono.Documentation/Updater/Formatters/FSharpFormatter.cs
+++ b/mdoc/Mono.Documentation/Updater/Formatters/FSharpFormatter.cs
@@ -613,10 +613,9 @@ namespace Mono.Documentation.Updater
return buf;
}
- protected override StringBuilder AppendRefTypeName(StringBuilder buf, TypeReference type, IAttributeParserContext context)
+ protected override StringBuilder AppendRefTypeName(StringBuilder buf, ByReferenceType type, IAttributeParserContext context)
{
- ByReferenceType reftype = type as ByReferenceType;
- return AppendTypeName(buf, reftype?.ElementType, context);
+ return AppendTypeName(buf, type.ElementType, context);
}
protected override StringBuilder AppendModifiers(StringBuilder buf, MethodDefinition method)
diff --git a/mdoc/Mono.Documentation/Updater/Formatters/MemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/MemberFormatter.cs
index 439d91b5..6e1ca5bd 100644
--- a/mdoc/Mono.Documentation/Updater/Formatters/MemberFormatter.cs
+++ b/mdoc/Mono.Documentation/Updater/Formatters/MemberFormatter.cs
@@ -143,14 +143,14 @@ namespace Mono.Documentation.Updater
StringBuilder interimBuilder = new StringBuilder();
- if (ShouldStripModFromTypeName && type is RequiredModifierType)
+ if (ShouldStripModFromTypeName && type is RequiredModifierType requiredModifierType)
{
- AppendRequiredModifierTypeName(interimBuilder, type as RequiredModifierType, context);
+ AppendRequiredModifierTypeName(interimBuilder, requiredModifierType, context);
return SetBuffer(buf, interimBuilder, useTypeProjection: useTypeProjection);
}
- if (ShouldStripModFromTypeName && type is OptionalModifierType)
+ if (ShouldStripModFromTypeName && type is OptionalModifierType optionalModifierType)
{
- AppendOptionalModifierTypeName(interimBuilder, type as OptionalModifierType, context);
+ AppendOptionalModifierTypeName(interimBuilder, optionalModifierType, context);
return SetBuffer(buf, interimBuilder, useTypeProjection: useTypeProjection);
}
if (type is ArrayType)
@@ -158,9 +158,9 @@ namespace Mono.Documentation.Updater
AppendArrayTypeName(interimBuilder, type, context);
return SetBuffer(buf, interimBuilder, useTypeProjection: useTypeProjection);
}
- if (type is ByReferenceType)
+ if (type is ByReferenceType byReferenceType)
{
- AppendRefTypeName (interimBuilder, type, context);
+ AppendRefTypeName (interimBuilder, byReferenceType, context);
return SetBuffer(buf, interimBuilder, useTypeProjection: useTypeProjection);
}
if (type is PointerType)
@@ -290,10 +290,9 @@ namespace Mono.Documentation.Updater
get { return "@"; }
}
- protected virtual StringBuilder AppendRefTypeName (StringBuilder buf, TypeReference type, IAttributeParserContext context)
+ protected virtual StringBuilder AppendRefTypeName (StringBuilder buf, ByReferenceType type, IAttributeParserContext context)
{
- TypeSpecification spec = type as TypeSpecification;
- return _AppendTypeName(buf, spec != null ? spec.ElementType : type.GetElementType(), context);
+ return _AppendTypeName(buf, type.ElementType, context);
}
protected virtual string PointerModifier
diff --git a/mdoc/Mono.Documentation/Updater/Formatters/MsxdocSlashDocMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/MsxdocSlashDocMemberFormatter.cs
index 8d0beac3..a9b9aa6b 100644
--- a/mdoc/Mono.Documentation/Updater/Formatters/MsxdocSlashDocMemberFormatter.cs
+++ b/mdoc/Mono.Documentation/Updater/Formatters/MsxdocSlashDocMemberFormatter.cs
@@ -7,10 +7,9 @@ namespace Mono.Documentation.Updater
{
public MsxdocSlashDocMemberFormatter(TypeMap map) : base(map) { }
- protected override StringBuilder AppendRefTypeName(StringBuilder buf, TypeReference type, IAttributeParserContext context)
+ protected override StringBuilder AppendRefTypeName(StringBuilder buf, ByReferenceType type, IAttributeParserContext context)
{
- TypeSpecification spec = type as TypeSpecification;
- return _AppendTypeName(buf, spec != null ? spec.ElementType : type.GetElementType(), context).Append(RefTypeModifier);
+ return _AppendTypeName(buf, type.ElementType, context).Append(RefTypeModifier);
}
}
}
diff --git a/mdoc/Mono.Documentation/Updater/Formatters/SlashDocMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/SlashDocMemberFormatter.cs
index 2a5dfa51..26b2024d 100644
--- a/mdoc/Mono.Documentation/Updater/Formatters/SlashDocMemberFormatter.cs
+++ b/mdoc/Mono.Documentation/Updater/Formatters/SlashDocMemberFormatter.cs
@@ -82,7 +82,7 @@ namespace Mono.Documentation.Updater
return buf;
}
- protected override StringBuilder AppendRefTypeName (StringBuilder buf, TypeReference type, IAttributeParserContext context)
+ protected override StringBuilder AppendRefTypeName (StringBuilder buf, ByReferenceType type, IAttributeParserContext context)
{
return base.AppendRefTypeName (buf, type, context).Append (RefTypeModifier);
}
diff --git a/mdoc/mdoc.Test/BasicTests.cs b/mdoc/mdoc.Test/BasicTests.cs
index 61f8bbb4..094fa024 100644
--- a/mdoc/mdoc.Test/BasicTests.cs
+++ b/mdoc/mdoc.Test/BasicTests.cs
@@ -88,6 +88,15 @@ namespace mdoc.Test
return GetMethod(GetType(type), i => i.Name == name);
}
+ protected PropertyDefinition GetProperty(Type type, Func<PropertyDefinition, bool> query)
+ {
+ var properties = GetType(type).Properties;
+ var member = properties.FirstOrDefault(query)?.Resolve();
+ if (member == null)
+ throw new Exception("Did not find the member in the test class");
+ return member;
+ }
+
protected Dictionary<string, List<MemberReference>> GetClassInterface(TypeDefinition type)
{
return DocUtils.GetImplementedMembersFingerprintLookup(type);
diff --git a/mdoc/mdoc.Test/FormatterTests.cs b/mdoc/mdoc.Test/FormatterTests.cs
index f33177e7..2e16f65f 100644
--- a/mdoc/mdoc.Test/FormatterTests.cs
+++ b/mdoc/mdoc.Test/FormatterTests.cs
@@ -256,22 +256,28 @@ namespace mdoc.Test
Assert.AreEqual("public void SomeMethod4 (out string a, T t, object b = default);", sig);
}
- [Test]
- public void CSharpReadonlyRefReturn()
+ [TestCase(typeof(ReadonlyRefClass), "Ref", "public ref int Ref ();")]
+ [TestCase(typeof(ReadonlyRefClass), "ReadonlyRef", "public ref readonly int ReadonlyRef ();")]
+ [TestCase(typeof(ReadonlyRefClass), "RefInAndOutMethod", "public void RefInAndOutMethod (ref int a, in int b, out int c);")]
+ [TestCase(typeof(GenericRefClass<>), "Ref", "public ref T Ref ();")]
+ [TestCase(typeof(GenericRefClass<>), "ReadonlyRef", "public ref readonly T ReadonlyRef ();")]
+ [TestCase(typeof(GenericRefClass<>), "RefInAndOutMethod", "public void RefInAndOutMethod (ref T a, in T b, out T c);")]
+ public void CSharpRefReturnMethodTest(Type type, string methodName, string expectedSignature)
{
- var member = GetMethod(typeof(ReadonlyRefClass), m => m.Name == "ReadonlyRef");
- var formatter = new CSharpFullMemberFormatter();
- var sig = formatter.GetDeclaration(member);
- Assert.AreEqual("public ref readonly int ReadonlyRef ();", sig);
+ var member = GetMethod(type, m => m.Name == methodName);
+ var actualSignature = formatter.GetDeclaration(member);
+ Assert.AreEqual(expectedSignature, actualSignature);
}
- [Test]
- public void CSharpRefReturn()
+ [TestCase(typeof(ReadonlyRefClass), "RefProperty", "public ref int RefProperty { get; }")]
+ [TestCase(typeof(ReadonlyRefClass), "Item", "public ref readonly int this[int index] { get; }")]
+ [TestCase(typeof(GenericRefClass<>), "RefProperty", "public ref T RefProperty { get; }")]
+ [TestCase(typeof(GenericRefClass<>), "Item", "public ref readonly T this[int index] { get; }")]
+ public void CSharpRefReturnPropertyTest(Type type, string propertyName, string expectedSignature)
{
- var member = GetMethod(typeof(ReadonlyRefClass), m => m.Name == "Ref");
- var formatter = new CSharpFullMemberFormatter();
- var sig = formatter.GetDeclaration(member);
- Assert.AreEqual("public ref int Ref ();", sig);
+ var member = GetProperty(type, p => p.Name == propertyName);
+ var actualSignature = formatter.GetDeclaration(member);
+ Assert.AreEqual(expectedSignature, actualSignature);
}
[Test]
diff --git a/mdoc/mdoc.Test/SampleClasses/ReadonlyRefClass.cs b/mdoc/mdoc.Test/SampleClasses/ReadonlyRefClass.cs
index dbe738db..59f35672 100644
--- a/mdoc/mdoc.Test/SampleClasses/ReadonlyRefClass.cs
+++ b/mdoc/mdoc.Test/SampleClasses/ReadonlyRefClass.cs
@@ -3,8 +3,27 @@
public class ReadonlyRefClass
{
int i;
-
public ref int Ref() => ref i;
- public ref readonly int ReadonlyRef() => ref i;
+
+ public ref readonly int ReadonlyRef() => ref i;
+
+ public ref int RefProperty { get { return ref i; } }
+
+ public ref readonly int this[int index] => throw null;
+
+ public void RefInAndOutMethod(ref int a, in int b, out int c) => throw null;
+ }
+
+ public class GenericRefClass<T>
+ {
+ public ref T Ref() => throw null;
+
+ public ref readonly T ReadonlyRef() => throw null;
+
+ public ref T RefProperty => throw null;
+
+ public ref readonly T this[int index] => throw null;
+
+ public void RefInAndOutMethod(ref T a, in T b, out T c) => throw null;
}
}