Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mdoc/Mono.Documentation/MDocUpdater.Member.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ internal static void MakeTypeParameterConstraints(XmlElement root, XmlElement e,
AppendElementText(ce, "ParameterAttribute", "NotNullableValueTypeConstraint");
if ((attrs & GenericParameterAttributes.ReferenceTypeConstraint) != 0)
AppendElementText(ce, "ParameterAttribute", "ReferenceTypeConstraint");
// Check for 'allows ref struct' constraint
if ((attrs & (GenericParameterAttributes)0x0020) != 0) // Assuming 0x0020 is the flag for 'allows ref struct'
AppendElementText(ce, "ParameterAttribute", "AllowByRefLike");

#if NEW_CECIL
foreach (GenericParameterConstraint c in constraints)
Expand Down
1 change: 1 addition & 0 deletions mdoc/Mono.Documentation/MDocUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4166,6 +4166,7 @@ private void MakeTypeParameters (FrameworkTypeEntry entry, XmlElement root, ILis
xElement.RemoveAttribute(Consts.FrameworkAlternate);
xElement.SetAttribute(Consts.FrameworkAlternate, fxaValue);
MakeParamsAttributes(existing.Element, AttributeFormatter.PreProcessCustomAttributes(t.CustomAttributes), entry, member);
MakeTypeParameterConstraints(root, xElement, xElement, t);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,10 @@ private StringBuilder AppendConstraints (StringBuilder buf, IList<GenericParamet
bool isref = (attrs & GenericParameterAttributes.ReferenceTypeConstraint) != 0;
bool isvt = (attrs & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0;
bool isnew = (attrs & GenericParameterAttributes.DefaultConstructorConstraint) != 0;
bool isAllowsRefStruct = (attrs & (GenericParameterAttributes)0x0020) != 0; // Assuming 0x0020 is the flag for 'allows ref struct'
bool comma = false;

if (!isref && !isvt && !isnew && constraints.Count == 0)
if (!isref && !isvt && !isAllowsRefStruct && !isnew && constraints.Count == 0)
continue;
buf.Append (" where ").Append (genArg.Name).Append (" : ");
if (isref)
Expand Down Expand Up @@ -350,6 +351,14 @@ private StringBuilder AppendConstraints (StringBuilder buf, IList<GenericParamet
buf.Append (", ");
buf.Append ("new()");
}

// Handle 'allows ref struct' constraint
if (isAllowsRefStruct)
{
if (comma || constraints.Count > 0 || isnew)
buf.Append(", ");
buf.Append("allows ref struct");
}
}
return buf;
}
Expand Down
46 changes: 46 additions & 0 deletions mdoc/mdoc.Test/MDocUpdaterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,5 +253,51 @@ public void Run_WithOptionsOAndFx_ShouldProcessFrameworks()
Assert.IsTrue(File.Exists(Path.Combine(outputDir, "index.xml")));
Assert.IsTrue(File.Exists(Path.Combine(outputDir, "ns-TestLibrary.xml")));
}

[Test]
public void Test_RunWithRefStructValidation()
{
// Arrange
var baseDir = Path.Combine(Path.GetDirectoryName(this.GetType().Module.Assembly.Location), "SampleClasses/TestUpdate");
var outputDir = Path.Combine(baseDir, "outputDir");
Directory.CreateDirectory(outputDir);

var args = new List<string> { "update", "-o", outputDir, "-fx", Path.Combine(baseDir) };
var updater = new MDocUpdater();

// Act
updater.Run(args);

// Assert
var IRefStructProcessorPath = Path.Combine(outputDir, "AllowsRefStructDemo", "IRefStructProcessor`1.xml");
var refStructHandlerPath = Path.Combine(outputDir, "AllowsRefStructDemo", "RefStructHandler.xml");
var ImmutablePath = Path.Combine(outputDir, "AllowsRefStructDemo", "Immutable.xml");

Assert.IsTrue(File.Exists(IRefStructProcessorPath));
Assert.IsTrue(File.Exists(refStructHandlerPath));

var IRefStructProcessorDoc = new XmlDocument();
IRefStructProcessorDoc.Load(IRefStructProcessorPath);
var IRefStructProcessorNode = IRefStructProcessorDoc.SelectSingleNode("//TypeParameters/TypeParameter/Constraints/ParameterAttribute[text()='AllowByRefLike']");
Assert.IsNotNull(IRefStructProcessorNode, "Missing <ParameterAttribute>AllowByRefLike</ParameterAttribute> in IRefStructProcessor`1.xml");
var IRefStructProcessorTypeSignatureNode = IRefStructProcessorDoc.SelectSingleNode("//TypeSignature[@Language='C#' and contains(@Value, 'where T : allows ref struct')]");
Assert.IsNotNull(IRefStructProcessorTypeSignatureNode, "Missing TypeSignature with 'where T : allows ref struct' in IRefStructProcessor`1.xml");

var refStructHandlerDoc = new XmlDocument();
refStructHandlerDoc.Load(refStructHandlerPath);
var refStructHandlerNode = refStructHandlerDoc.SelectSingleNode("//Members/Member/TypeParameters/TypeParameter/Constraints/ParameterAttribute[text()='AllowByRefLike']");
Assert.IsNotNull(refStructHandlerNode, "Missing <ParameterAttribute>AllowByRefLike</ParameterAttribute> in RefStructHandler.xml");
var refStructHandlerMemberSignatureNode = refStructHandlerDoc.SelectSingleNode("//Members/Member/MemberSignature[@Language='C#' and contains(@Value, 'where T : new(), allows ref struct')]");
Assert.IsNotNull(refStructHandlerMemberSignatureNode, "Missing MemberSignature with 'where T : allows ref struct' in RefStructHandler.xml");

var ImmutableDoc = new XmlDocument();
ImmutableDoc.Load(ImmutablePath);
var constraintsNodes = ImmutableDoc.SelectNodes("//Members/Member/TypeParameters/TypeParameter/Constraints");
Assert.IsTrue(constraintsNodes.Count == 1, "Multiple <Constraints> in Immutable.xml");
var allowByRefLikeNode = ImmutableDoc.SelectSingleNode("//Members/Member/TypeParameters/TypeParameter/Constraints/ParameterAttribute[text()='AllowByRefLike']");
var defaultConstructorNode = ImmutableDoc.SelectSingleNode("//Members/Member/TypeParameters/TypeParameter/Constraints/ParameterAttribute[text()='DefaultConstructorConstraint']");
Assert.IsNotNull(allowByRefLikeNode, "Missing <ParameterAttribute>AllowByRefLike</ParameterAttribute> in Immutable.xml");
Assert.IsNotNull(defaultConstructorNode, "Missing <ParameterAttribute>DefaultConstructorConstraint</ParameterAttribute> in Immutable.xml");
}
}
}
3 changes: 3 additions & 0 deletions mdoc/mdoc.Test/SampleClasses/TestUpdate/frameworks.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
<Framework Name="net-8.0" Source="net-8.0">
<assemblySearchPath>dependencies\net-8.0</assemblySearchPath>
</Framework>
<Framework Name="net-9.0" Source="net-9.0">
<assemblySearchPath>dependencies\net-9.0</assemblySearchPath>
</Framework>
</Frameworks>
Binary file not shown.
Binary file not shown.
8 changes: 8 additions & 0 deletions mdoc/mdoc.Test/mdoc.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@
<Link>SampleClasses\TestUpdate\net-8.0\TestLibrary.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SampleClasses\TestUpdate\net-8.0\AllowsRefStructDemo.dll">
<Link>SampleClasses\TestUpdate\net-8.0\AllowsRefStructDemo.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SampleClasses\TestUpdate\net-9.0\AllowsRefStructDemo.dll">
<Link>SampleClasses\TestUpdate\net-9.0\AllowsRefStructDemo.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SampleClasses\TestUpdate\frameworks.xml">
<Link>SampleClasses\TestUpdate\frameworks.xml</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Expand Down