Skip to content

Commit

Permalink
ExperimentalAttribute and required modifier support
Browse files Browse the repository at this point in the history
Changes made:
- Added support for ExperimentalAttribute to add tags to API members similar to ObsoleteAttribute in all presentation styles.  Closes #1093.
- Added support for the `required` modifier on fields and properties in the C# syntax generator.
- Made some usability improvements to the Entity References tool window (#1094).
  • Loading branch information
EWSoftware committed Feb 24, 2025
1 parent ccec05c commit 2f554ed
Show file tree
Hide file tree
Showing 31 changed files with 542 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
<introduction>
<para>The <ui>Entity References</ui> window allows you to insert MAML elements into conceptual
content topics that represent tokens, images, code entities (API members), code snippets, and links to
other conceptual topics.</para>
other conceptual topics. To open it in the standalone GUI, select the <ui>Entity References</ui> option on the
<ui>Window</ui> menu, click the related main toolbar button, or hit <ui>F3</ui>. In the Visual Studio extension,
it can be opened by selecting the <ui>Entity References Window</ui> option from the <ui>View</ui> | <ui>Other
Windows</ui> menu or from the <ui>Other Windows</ui> toolbar button dropdown.</para>
</introduction>

<section>
Expand Down
9 changes: 7 additions & 2 deletions SHFB/Deploy/Templates/MRefBuilder.config
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,11 @@
<type name="EventLogPermissionAttribute" expose="true"/>
<type name="PerformanceCounterPermissionAttribute" expose="true"/>
</namespace>
<!-- Attributes in System.Diagnostics.CodeAnalysis control interaction with FxCop. Don't show them. -->
<namespace name="System.Diagnostics.CodeAnalysis" expose="false" />
<!-- Most attributes in System.Diagnostics.CodeAnalysis control interaction with code analysis. Don't show them. -->
<namespace name="System.Diagnostics.CodeAnalysis" expose="false">
<!-- This is required to document experimental API members -->
<type name="ExperimentalAttribute" required="true" />
</namespace>
<!-- Attributes in System.EnterpriseServices control obscure details of COM+ interop. Don't show them. -->
<namespace name="System.EnterpriseServices" expose="false" />
<namespace name="System.Reflection" expose="true">
Expand Down Expand Up @@ -139,6 +142,8 @@
<type name="CallerLineNumberAttribute" expose="true" />
<type name="CallerMemberNameAttribute" expose="true" />
<type name="UnsafeValueTypeAttribute" expose="true" />
<!-- This is required to document required members -->
<type name="RequiredMemberAttribute" required="true" />
</namespace>
<!-- Attributes in System.Runtime.ConstrainedExecution control obscure details of compilation. Don't show them. -->
<namespace name="System.Runtime.ConstrainedExecution" expose="false" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// 10/08/2015 - EFW - Added support for writing out the value of constant fields
// 03/14/2021 - EFW - Added support for defaultValue element
// 09/08/2022 - EFW - Added support for init only setters
// 02/23/2025 - EFW - Added support for the required modifier

using System;
using System.Globalization;
Expand Down Expand Up @@ -671,6 +672,7 @@ private static void WriteProcedureModifiers(XPathNavigator reflection, SyntaxWri
bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractProcedureExpression);
bool isFinal = (bool)reflection.Evaluate(apiIsFinalExpression);
bool isOverride = (bool)reflection.Evaluate(apiIsOverrideExpression);
bool isRequired = reflection.SelectSingleNode(apiRequiredMemberAttribute) != null;

WriteVisibility(reflection, writer);
writer.WriteString(" ");
Expand Down Expand Up @@ -708,6 +710,12 @@ private static void WriteProcedureModifiers(XPathNavigator reflection, SyntaxWri
}
}
}

if(isRequired)
{
writer.WriteKeyword("required");
writer.WriteString(" ");
}
}
}

Expand All @@ -725,6 +733,7 @@ public override void WriteFieldSyntax(XPathNavigator reflection, SyntaxWriter wr
bool isLiteral = (bool)reflection.Evaluate(apiIsLiteralFieldExpression);
bool isInitOnly = (bool)reflection.Evaluate(apiIsInitOnlyFieldExpression);
bool isSerialized = (bool)reflection.Evaluate(apiIsSerializedFieldExpression);
bool isRequired = reflection.SelectSingleNode(apiRequiredMemberAttribute) != null;

// !EFW - Added support for fixed keyword
XPathNavigator fixedAttribute = reflection.SelectSingleNode(apiFixedAttribute);
Expand All @@ -746,6 +755,12 @@ public override void WriteFieldSyntax(XPathNavigator reflection, SyntaxWriter wr
writer.WriteString(" ");
}

if(isRequired)
{
writer.WriteKeyword("required");
writer.WriteString(" ");
}

if(isInitOnly)
{
writer.WriteKeyword("readonly");
Expand Down Expand Up @@ -851,12 +866,13 @@ private void WriteAttributes(XPathNavigator reflection, SyntaxWriter writer, str
{
XPathNavigator type = attribute.SelectSingleNode(attributeTypeExpression);

// !EFW - Ignore ExtensionAttribute, FixedBufferAttribute, ParamArrayAttribute, IsByRefLikeAttribute, IsReadOnlyAttribute too
// !EFW - Ignore these as they are handled by other means
if(type.GetAttribute("api", String.Empty) == "T:System.Runtime.CompilerServices.ExtensionAttribute" ||
type.GetAttribute("api", String.Empty) == "T:System.Runtime.CompilerServices.FixedBufferAttribute" ||
type.GetAttribute("api", String.Empty) == "T:System.Runtime.CompilerServices.IsByRefLikeAttribute" ||
type.GetAttribute("api", String.Empty) == "T:System.Runtime.CompilerServices.IsReadOnlyAttribute" ||
type.GetAttribute("api", String.Empty) == "T:System.ParamArrayAttribute")
type.GetAttribute("api", String.Empty) == "T:System.ParamArrayAttribute" ||
type.GetAttribute("api", String.Empty) == "T:System.Runtime.CompilerServices.RequiredMemberAttribute")
{
continue;
}
Expand Down
10 changes: 8 additions & 2 deletions SHFB/Source/MRefBuilder/MRefBuilder.config
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,11 @@
<type name="EventLogPermissionAttribute" expose="true"/>
<type name="PerformanceCounterPermissionAttribute" expose="true"/>
</namespace>
<!-- Attributes in System.Diagnostics.CodeAnalysis control interaction with FxCop. Don't show them. -->
<namespace name="System.Diagnostics.CodeAnalysis" expose="false" />
<!-- Most attributes in System.Diagnostics.CodeAnalysis control interaction with code analysis. Don't show them. -->
<namespace name="System.Diagnostics.CodeAnalysis" expose="false">
<!-- This is required to document experimental API members -->
<type name="ExperimentalAttribute" required="true" />
</namespace>
<!-- Attributes in System.EnterpriseServices control obscure details of COM+ interop. Don't show them. -->
<namespace name="System.EnterpriseServices" expose="false" />
<namespace name="System.Reflection" expose="true">
Expand Down Expand Up @@ -181,6 +184,8 @@
<type name="CallerLineNumberAttribute" expose="true" />
<type name="CallerMemberNameAttribute" expose="true" />
<type name="UnsafeValueTypeAttribute" expose="true" />
<!-- This is required to document required members -->
<type name="RequiredMemberAttribute" required="true" />
</namespace>
<!-- Attributes in System.Runtime.ConstrainedExecution control obscure details of compilation. Don't show them. -->
<namespace name="System.Runtime.ConstrainedExecution" expose="false" />
Expand All @@ -202,6 +207,7 @@
<type name="OptionalAttribute" required="true" />
<!-- This one is converted to method metadata so it cannot be excluded -->
<type name="PreserveSigAttribute" required="true"/>
<type name="ProgIdAttribute" required="true"/>
<!-- This one is converted to type metadata so it cannot be excluded -->
<type name="StructLayoutAttribute" required="true"/>
<type name="TypeIdentifierAttribute" expose="true" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// System : Sandcastle Tools Standard Presentation Styles
// File : Default2022Transformation.cs
// Author : Eric Woodruff ([email protected])
// Updated : 08/30/2024
// Note : Copyright 2022-2024, Eric Woodruff, All rights reserved
// Updated : 02/23/2025
// Note : Copyright 2022-2025, Eric Woodruff, All rights reserved
//
// This file contains the class used to generate a MAML or API HTML topic from the raw topic XML data for the
// Default 2022 presentation style.
Expand Down Expand Up @@ -1137,15 +1137,17 @@ private void RenderPageTitleAndLogo(XElement body)
//=====================================================================

/// <summary>
/// This is used to render the preliminary and obsolete API notices
/// This is used to render the preliminary, obsolete, and experimental API notices
/// </summary>
/// <param name="transformation">The topic transformation to use</param>
private static void RenderNotices(TopicTransformationCore transformation)
{
var preliminary = transformation.CommentsNode.Element("preliminary");
var obsolete = transformation.ReferenceNode.AttributeOfType("T:System.ObsoleteAttribute");
var experimental = transformation.ReferenceNode.AttributeOfType(
"T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute");

if(preliminary != null || obsolete != null)
if(preliminary != null || obsolete != null || experimental != null)
{
var currentElement = transformation.CurrentElement;
var notes = new XElement("span", new XAttribute("class", "tags"));
Expand All @@ -1164,6 +1166,13 @@ private static void RenderNotices(TopicTransformationCore transformation)
new XElement("include", new XAttribute("item", "boilerplate_obsoleteLong"))));
}

if(experimental != null)
{
notes.Add(new XElement("span",
new XAttribute("class", "tag is-warning is-medium"),
new XElement("include", new XAttribute("item", "boilerplate_experimentalLong"))));
}

transformation.CurrentElement = currentElement;
}
}
Expand Down Expand Up @@ -1606,8 +1615,9 @@ private static void RenderApiNamespaceList(TopicTransformationCore transformatio

var obsoleteAttr = e.AttributeOfType("T:System.ObsoleteAttribute");
var prelimComment = e.Element("preliminary");
var experimentalAttr = e.AttributeOfType("T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute");

if(obsoleteAttr != null || prelimComment != null)
if(obsoleteAttr != null || prelimComment != null || experimentalAttr != null)
{
if(!summaryCell.IsEmpty)
summaryCell.Add(new XElement("br"));
Expand All @@ -1620,6 +1630,14 @@ private static void RenderApiNamespaceList(TopicTransformationCore transformatio
new XAttribute("item", "boilerplate_obsoleteShort"))));
}

if(experimentalAttr != null)
{
summaryCell.Add(new XElement("span",
new XAttribute("class", "tag is-warning"),
new XElement("include",
new XAttribute("item", "boilerplate_experimentalShort"))));
}

if(prelimComment != null)
{
summaryCell.Add(new XElement("span",
Expand Down Expand Up @@ -1779,7 +1797,9 @@ private static void RenderApiEnumerationMembersList(TopicTransformationCore tran
thisTransform.RenderChildElements(summaryCell, remarks.Nodes());
}

if(e.AttributeOfType("T:System.ObsoleteAttribute") != null)
var obsoleteAttr = e.AttributeOfType("T:System.ObsoleteAttribute");

if(obsoleteAttr != null)
{
if(!summaryCell.IsEmpty)
summaryCell.Add(new XElement("br"));
Expand All @@ -1790,6 +1810,17 @@ private static void RenderApiEnumerationMembersList(TopicTransformationCore tran
new XAttribute("item", "boilerplate_obsoleteShort"))));
}

if(e.AttributeOfType("T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute") != null)
{
if(!summaryCell.IsEmpty && obsoleteAttr == null)
summaryCell.Add(new XElement("br"));

summaryCell.Add(new XElement("span",
new XAttribute("class", "tag is-warning"),
new XElement("include",
new XAttribute("item", "boilerplate_experimentalShort"))));
}

if(summaryCell.IsEmpty)
summaryCell.Add(Element.NonBreakingSpace);
}
Expand Down Expand Up @@ -2038,8 +2069,9 @@ private static void RenderApiTypeMemberLists(TopicTransformationCore transformat

var obsoleteAttr = e.AttributeOfType("T:System.ObsoleteAttribute");
var prelimComment = e.Element("preliminary");
var experimentalAttr = e.AttributeOfType("T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute");

if(obsoleteAttr != null || prelimComment != null)
if(obsoleteAttr != null || prelimComment != null || experimentalAttr != null)
{
if(!summaryCell.IsEmpty)
summaryCell.Add(new XElement("br"));
Expand All @@ -2052,6 +2084,14 @@ private static void RenderApiTypeMemberLists(TopicTransformationCore transformat
new XAttribute("item", "boilerplate_obsoleteShort"))));
}

if(experimentalAttr != null)
{
summaryCell.Add(new XElement("span",
new XAttribute("class", "tag is-warning"),
new XElement("include",
new XAttribute("item", "boilerplate_experimentalShort"))));
}

if(prelimComment != null)
{
summaryCell.Add(new XElement("span",
Expand Down
Loading

0 comments on commit 2f554ed

Please sign in to comment.