Browse Source

Feat/improved clean comment pass (#1928)

* Code cleanup

* Improved XML style comment parsing

* Fix test errors
pull/1931/head
Jelle 3 months ago committed by GitHub
parent
commit
f89209c8e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 52
      src/AST/Comment.cs
  2. 4
      src/CppParser/Comments.cpp
  3. 23
      src/Generator.Tests/Passes/TestPasses.cs
  4. 212
      src/Generator/Generators/CSharp/CSharpCommentPrinter.cs
  5. 4
      src/Generator/Generators/CodeGenerator.cs
  6. 107
      src/Generator/Passes/CleanCommentsPass.cs
  7. 2
      src/Generator/Passes/FixParameterUsageFromComments.cs
  8. 4
      src/Generator/Utils/HtmlEncoder.cs
  9. 2
      tests/dotnet/NamespacesDerived/NamespacesDerived.Tests.cs
  10. 37
      tests/dotnet/Native/Passes.h

52
src/AST/Comment.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace CppSharp.AST
{
@ -109,7 +110,7 @@ namespace CppSharp.AST @@ -109,7 +110,7 @@ namespace CppSharp.AST
T VisitTParamCommand(TParamCommandComment comment);
T VisitVerbatimBlock(VerbatimBlockComment comment);
T VisitVerbatimLine(VerbatimLineComment comment);
T VisitParagraphCommand(ParagraphComment comment);
T VisitParagraph(ParagraphComment comment);
T VisitFull(FullComment comment);
T VisitHTMLStartTag(HTMLStartTagComment comment);
T VisitHTMLEndTag(HTMLEndTagComment comment);
@ -129,20 +130,13 @@ namespace CppSharp.AST @@ -129,20 +130,13 @@ namespace CppSharp.AST
public static string GetMultiLineCommentPrologue(CommentKind kind)
{
switch (kind)
return kind switch
{
case CommentKind.BCPL:
case CommentKind.BCPLExcl:
return "//";
case CommentKind.C:
case CommentKind.JavaDoc:
case CommentKind.Qt:
return " *";
case CommentKind.BCPLSlash:
return "///";
default:
throw new ArgumentOutOfRangeException();
}
CommentKind.BCPL or CommentKind.BCPLExcl => "//",
CommentKind.C or CommentKind.JavaDoc or CommentKind.Qt => " *",
CommentKind.BCPLSlash => "///",
_ => throw new ArgumentOutOfRangeException()
};
}
public static string GetLineCommentPrologue(CommentKind kind)
@ -375,7 +369,7 @@ namespace CppSharp.AST @@ -375,7 +369,7 @@ namespace CppSharp.AST
public override void Visit<T>(ICommentVisitor<T> visitor)
{
visitor.VisitParagraphCommand(this);
visitor.VisitParagraph(this);
}
}
@ -416,10 +410,17 @@ namespace CppSharp.AST @@ -416,10 +410,17 @@ namespace CppSharp.AST
{
public string Name;
public string Value;
public override string ToString()
{
return $"{Name}=\"{Value}\"";
}
}
public List<Attribute> Attributes;
public bool SelfClosing { get; set; }
public HTMLStartTagComment()
{
Kind = DocumentationCommentKind.HTMLStartTagComment;
@ -430,6 +431,15 @@ namespace CppSharp.AST @@ -430,6 +431,15 @@ namespace CppSharp.AST
{
visitor.VisitHTMLStartTag(this);
}
public override string ToString()
{
var attrStr = string.Empty;
if (Attributes.Count != 0)
attrStr = " " + string.Join(' ', Attributes.Select(x => x.ToString()));
return $"<{TagName}{attrStr}{(SelfClosing ? "/" : "")}>";
}
}
/// <summary>
@ -446,6 +456,11 @@ namespace CppSharp.AST @@ -446,6 +456,11 @@ namespace CppSharp.AST
{
visitor.VisitHTMLEndTag(this);
}
public override string ToString()
{
return $"</{TagName}>";
}
}
/// <summary>
@ -464,6 +479,13 @@ namespace CppSharp.AST @@ -464,6 +479,13 @@ namespace CppSharp.AST
{
visitor.VisitText(this);
}
public override string ToString()
{
return Text;
}
public bool IsEmpty => string.IsNullOrEmpty(Text) && !HasTrailingNewline;
}
/// <summary>

4
src/CppParser/Comments.cpp

@ -263,8 +263,8 @@ void Parser::HandleComments(const clang::Decl* D, Declaration* Decl) @@ -263,8 +263,8 @@ void Parser::HandleComments(const clang::Decl* D, Declaration* Decl)
{
using namespace clang;
const clang::RawComment* RC = 0;
if (!(RC = c->getASTContext().getRawCommentForAnyRedecl(D)))
const clang::RawComment* RC = c->getASTContext().getRawCommentForAnyRedecl(D);
if (!RC)
return;
auto RawComment = WalkRawComment(RC);

23
src/Generator.Tests/Passes/TestPasses.cs

@ -123,10 +123,12 @@ namespace CppSharp.Generator.Tests.Passes @@ -123,10 +123,12 @@ namespace CppSharp.Generator.Tests.Passes
[Test]
public void TestCleanCommentsPass()
{
var c = AstContext.FindClass("TestCommentsPass").FirstOrDefault();
var c = AstContext.Class("TestCommentsPass");
var c2 = AstContext.Class("TestCommentsPass2");
passBuilder.AddPass(new CleanCommentsPass());
passBuilder.RunPasses(pass => pass.VisitDeclaration(c));
passBuilder.RunPasses(pass => pass.VisitClassDecl(c2));
var para = (ParagraphComment)c.Comment.FullComment.Blocks[0];
var textGenerator = new TextGenerator();
@ -134,6 +136,25 @@ namespace CppSharp.Generator.Tests.Passes @@ -134,6 +136,25 @@ namespace CppSharp.Generator.Tests.Passes
Assert.That(textGenerator.StringBuilder.ToString().Trim(),
Is.EqualTo("/// <summary>A simple test.</summary>"));
var textGenerator2 = new TextGenerator();
textGenerator2.Print(c2.Methods[0].Comment.FullComment, CommentKind.BCPLSlash);
Assert.That(textGenerator2.StringBuilder.ToString().Trim().Replace("\r\n", "\n"),
Is.EqualTo(
"/// <summary>Gets a value</summary>\n" +
"/// <returns>One</returns>"
));
var textGenerator3 = new TextGenerator();
textGenerator3.Print(c2.Methods[1].Comment.FullComment, CommentKind.BCPLSlash);
Assert.That(textGenerator3.StringBuilder.ToString().Trim().Replace("\r\n", "\n"),
Is.EqualTo(
"/// <summary>Sets a value. Get it with <see cref=\"GetValueWithComment\"/></summary>\n" +
"/// <param name=\"value\">The value to set</param>\n" +
"/// <returns>The parameter (typeof<float>)</returns>"
));
}
[Test]

212
src/Generator/Generators/CSharp/CSharpCommentPrinter.cs

@ -11,7 +11,7 @@ namespace CppSharp.Generators.CSharp @@ -11,7 +11,7 @@ namespace CppSharp.Generators.CSharp
{
public static void Print(this ITextGenerator textGenerator, Comment comment, CommentKind kind)
{
var sections = new List<Section> { new Section(CommentElement.Summary) };
var sections = new List<Section>();
GetCommentSections(comment, sections);
foreach (var section in sections)
TrimSection(section);
@ -23,18 +23,23 @@ namespace CppSharp.Generators.CSharp @@ -23,18 +23,23 @@ namespace CppSharp.Generators.CSharp
switch (comment.Kind)
{
case DocumentationCommentKind.FullComment:
var fullComment = (FullComment)comment;
foreach (var block in fullComment.Blocks)
{
foreach (var block in ((FullComment)comment).Blocks)
block.GetCommentSections(sections);
break;
}
case DocumentationCommentKind.BlockCommandComment:
{
var blockCommandComment = (BlockCommandComment)comment;
if (blockCommandComment.ParagraphComment == null)
break;
switch (blockCommandComment.CommandKind)
{
case CommentCommandKind.Brief:
sections.Add(new Section(CommentElement.Summary));
blockCommandComment.ParagraphComment.GetCommentSections(sections);
sections.Add(new Section(CommentElement.Remarks));
break;
case CommentCommandKind.Return:
case CommentCommandKind.Returns:
@ -49,6 +54,7 @@ namespace CppSharp.Generators.CSharp @@ -49,6 +54,7 @@ namespace CppSharp.Generators.CSharp
if (inlineContentComment.HasTrailingNewline)
lastBlockSection.NewLine();
}
break;
default:
sections.Add(new Section(CommentElement.Remarks));
@ -56,67 +62,79 @@ namespace CppSharp.Generators.CSharp @@ -56,67 +62,79 @@ namespace CppSharp.Generators.CSharp
break;
}
break;
}
case DocumentationCommentKind.ParamCommandComment:
{
var paramCommandComment = (ParamCommandComment)comment;
var param = new Section(CommentElement.Param);
sections.Add(param);
if (paramCommandComment.Arguments.Count > 0)
param.Attributes.Add(
string.Format("name=\"{0}\"", paramCommandComment.Arguments[0].Text));
param.Attributes.Add($"name=\"{paramCommandComment.Arguments[0].Text}\"");
if (paramCommandComment.ParagraphComment != null)
{
foreach (var inlineContentComment in paramCommandComment.ParagraphComment.Content)
{
inlineContentComment.GetCommentSections(sections);
if (inlineContentComment.HasTrailingNewline)
sections.Last().NewLine();
}
}
if (!string.IsNullOrEmpty(sections.Last().CurrentLine.ToString()))
sections.Add(new Section(CommentElement.Remarks));
break;
case DocumentationCommentKind.TParamCommandComment:
break;
case DocumentationCommentKind.VerbatimBlockComment:
break;
case DocumentationCommentKind.VerbatimLineComment:
break;
}
case DocumentationCommentKind.ParagraphComment:
var summaryParagraph = sections.Count == 1;
var paragraphComment = (ParagraphComment)comment;
{
bool assumeSummary = false;
if (sections.Count == 0)
{
assumeSummary = true;
sections.Add(new Section(CommentElement.Summary));
}
var lastParagraphSection = sections.Last();
var paragraphComment = (ParagraphComment)comment;
foreach (var inlineContentComment in paragraphComment.Content)
{
inlineContentComment.GetCommentSections(sections);
if (inlineContentComment.HasTrailingNewline)
lastParagraphSection.NewLine();
var newSection = sections.Last();
if (lastParagraphSection == newSection)
continue;
if (!string.IsNullOrEmpty(lastParagraphSection.CurrentLine.ToString()))
lastParagraphSection.NewLine();
lastParagraphSection = newSection;
}
if (!string.IsNullOrEmpty(lastParagraphSection.CurrentLine.ToString()))
lastParagraphSection.NewLine();
if (sections[0].GetLines().Count > 0 && summaryParagraph)
{
sections[0].GetLines().AddRange(sections.Skip(1).SelectMany(s => s.GetLines()));
sections.RemoveRange(1, sections.Count - 1);
// The next paragraph should be a remarks section
if (assumeSummary)
sections.Add(new Section(CommentElement.Remarks));
}
break;
case DocumentationCommentKind.HTMLTagComment:
break;
case DocumentationCommentKind.HTMLStartTagComment:
break;
case DocumentationCommentKind.HTMLEndTagComment:
break;
}
case DocumentationCommentKind.TextComment:
var lastTextsection = sections.Last();
lastTextsection.CurrentLine.Append(GetText(comment,
lastTextsection.Type == CommentElement.Returns ||
lastTextsection.Type == CommentElement.Param).Trim());
break;
case DocumentationCommentKind.InlineContentComment:
{
var lastTextSection = sections.Last();
lastTextSection.CurrentLine
.Append(
GetText(comment, lastTextSection.Type is CommentElement.Returns or CommentElement.Param)
.TrimStart()
);
break;
}
case DocumentationCommentKind.InlineCommandComment:
{
var lastInlineSection = sections.Last();
var inlineCommand = (InlineCommandComment)comment;
@ -125,9 +143,50 @@ namespace CppSharp.Generators.CSharp @@ -125,9 +143,50 @@ namespace CppSharp.Generators.CSharp
var argText = $" <c>{inlineCommand.Arguments[0].Text}</c> ";
lastInlineSection.CurrentLine.Append(argText);
}
break;
}
case DocumentationCommentKind.HTMLStartTagComment:
{
var startTag = (HTMLStartTagComment)comment;
var sectionType = CommentElementFromTag(startTag.TagName);
if (IsInlineCommentElement(sectionType))
{
var lastSection = sections.Last();
lastSection.CurrentLine.Append(startTag);
break;
}
sections.Add(new Section(sectionType)
{
Attributes = startTag.Attributes.Select(a => a.ToString()).ToList()
});
break;
}
case DocumentationCommentKind.HTMLEndTagComment:
{
var endTag = (HTMLEndTagComment)comment;
var sectionType = CommentElementFromTag(endTag.TagName);
if (IsInlineCommentElement(sectionType))
{
var lastSection = sections.Last();
lastSection.CurrentLine.Append(endTag);
}
break;
}
case DocumentationCommentKind.HTMLTagComment:
case DocumentationCommentKind.TParamCommandComment:
case DocumentationCommentKind.VerbatimBlockComment:
case DocumentationCommentKind.VerbatimLineComment:
case DocumentationCommentKind.InlineContentComment:
case DocumentationCommentKind.VerbatimBlockLineComment:
case DocumentationCommentKind.BlockContentComment:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
@ -139,10 +198,10 @@ namespace CppSharp.Generators.CSharp @@ -139,10 +198,10 @@ namespace CppSharp.Generators.CSharp
text = text.Trim();
if (Helpers.RegexTag.IsMatch(text))
return String.Empty;
return string.Empty;
return HtmlEncoder.HtmlEncode(
text.Length > 1 && text[0] == ' ' && text[1] != ' ' ? text.Substring(1) : text);
text.Length > 1 && text[0] == ' ' && text[1] != ' ' ? text[1..] : text);
}
private static void TrimSection(Section section)
@ -166,22 +225,25 @@ namespace CppSharp.Generators.CSharp @@ -166,22 +225,25 @@ namespace CppSharp.Generators.CSharp
private static void FormatComment(ITextGenerator textGenerator, List<Section> sections, CommentKind kind)
{
var commentPrefix = Comment.GetMultiLineCommentPrologue(kind);
sections.Sort((x, y) => x.Type.CompareTo(y.Type));
var remarks = sections.Where(s => s.Type == CommentElement.Remarks).ToList();
if (remarks.Any())
if (remarks.Count != 0)
remarks.First().GetLines().AddRange(remarks.Skip(1).SelectMany(s => s.GetLines()));
if (remarks.Count > 1)
sections.RemoveRange(sections.IndexOf(remarks.First()) + 1, remarks.Count - 1);
var commentPrefix = Comment.GetMultiLineCommentPrologue(kind);
foreach (var section in sections.Where(s => s.HasLines))
{
var lines = section.GetLines();
var tag = section.Type.ToString().ToLowerInvariant();
var attributes = string.Empty;
if (section.Attributes.Any())
if (section.Attributes.Count != 0)
attributes = ' ' + string.Join(" ", section.Attributes);
textGenerator.Write($"{commentPrefix} <{tag}{attributes}>");
if (lines.Count == 1)
{
@ -205,13 +267,13 @@ namespace CppSharp.Generators.CSharp @@ -205,13 +267,13 @@ namespace CppSharp.Generators.CSharp
Type = type;
}
public StringBuilder CurrentLine { get; set; } = new StringBuilder();
public StringBuilder CurrentLine { get; set; } = new();
public CommentElement Type { get; set; }
public List<string> Attributes { get; } = new List<string>();
public List<string> Attributes { get; init; } = new();
private List<string> lines { get; } = new List<string>();
private List<string> lines { get; } = new();
public bool HasLines => lines.Any();
@ -229,15 +291,71 @@ namespace CppSharp.Generators.CSharp @@ -229,15 +291,71 @@ namespace CppSharp.Generators.CSharp
}
}
private static CommentElement CommentElementFromTag(string tag)
{
return tag.ToLowerInvariant() switch
{
"c" => CommentElement.C,
"code" => CommentElement.Code,
"example" => CommentElement.Example,
"exception" => CommentElement.Exception,
"include" => CommentElement.Include,
"list" => CommentElement.List,
"para" => CommentElement.Para,
"param" => CommentElement.Param,
"paramref" => CommentElement.ParamRef,
"permission" => CommentElement.Permission,
"remarks" => CommentElement.Remarks,
"return" or "returns" => CommentElement.Returns,
"summary" => CommentElement.Summary,
"typeparam" => CommentElement.TypeParam,
"typeparamref" => CommentElement.TypeParamRef,
"value" => CommentElement.Value,
"seealso" => CommentElement.SeeAlso,
"see" => CommentElement.See,
"inheritdoc" => CommentElement.InheritDoc,
_ => CommentElement.Unknown
};
}
/// <summary>From https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/documentation-comments#d3-recommended-tags</summary>
/// <remarks>Enum value is equal to sorting priority</remarks>
private enum CommentElement
{
Summary,
Typeparam,
Param,
Returns,
Exception,
Remarks,
Example
C = 1000, // Set text in a code-like font
Code = 1001, // Set one or more lines of source code or program output
Example = 11, // Indicate an example
Exception = 8, // Identifies the exceptions a method can throw
Include = 1, // Includes XML from an external file
List = 1002, // Create a list or table
Para = 1003, // Permit structure to be added to text
Param = 5, // Describe a parameter for a method or constructor
ParamRef = 1004, // Identify that a word is a parameter name
Permission = 7, // Document the security accessibility of a member
Remarks = 9, // Describe additional information about a type
Returns = 6, // Describe the return value of a method
See = 1005, // Specify a link
SeeAlso = 10, // Generate a See Also entry
Summary = 2, // Describe a type or a member of a type
TypeParam = 4, // Describe a type parameter for a generic type or method
TypeParamRef = 1006, // Identify that a word is a type parameter name
Value = 3, // Describe a property
InheritDoc = 0, // Inherit documentation from a base class
Unknown = 9999, // Unknown tag
}
private static bool IsInlineCommentElement(CommentElement element) =>
element switch
{
CommentElement.C => true,
CommentElement.Code => true,
CommentElement.List => true,
CommentElement.Para => true,
CommentElement.ParamRef => true,
CommentElement.See => true,
CommentElement.TypeParamRef => true,
CommentElement.Unknown => true, // Print unknown tags as inline
_ => ((int)element) >= 1000
};
}
}

4
src/Generator/Generators/CodeGenerator.cs

@ -1333,8 +1333,8 @@ namespace CppSharp.Generators @@ -1333,8 +1333,8 @@ namespace CppSharp.Generators
public static class Helpers
{
public static Regex RegexTag = new Regex(@"^(<|</)[a-zA-Z][\w\-]*?>?$");
public static Regex RegexCommentCommandLeftover = new Regex(@"^\S*");
public static Regex RegexTag = new(@"^(<|</)[a-zA-Z][\w\-]*?>?$");
public static Regex RegexCommentCommandLeftover = new(@"^\S*");
public static readonly string InternalStruct = Generator.GeneratedIdentifier("Internal");
public static readonly string InstanceField = Generator.GeneratedIdentifier("instance");
public static readonly string InstanceIdentifier = Generator.GeneratedIdentifier("Instance");

107
src/Generator/Passes/CleanCommentsPass.cs

@ -7,10 +7,6 @@ namespace CppSharp.Passes @@ -7,10 +7,6 @@ namespace CppSharp.Passes
{
public class CleanCommentsPass : TranslationUnitPass, ICommentVisitor<bool>
{
public CleanCommentsPass() => VisitOptions.ResetFlags(
VisitFlags.ClassBases | VisitFlags.FunctionReturnType |
VisitFlags.TemplateArguments);
public bool VisitBlockCommand(BlockCommandComment comment) => true;
public override bool VisitParameterDecl(Parameter parameter) =>
@ -21,12 +17,11 @@ namespace CppSharp.Passes @@ -21,12 +17,11 @@ namespace CppSharp.Passes
if (!base.VisitDeclaration(decl))
return false;
if (decl.Comment != null)
{
if (decl.Comment == null)
return true;
var fullComment = decl.Comment.FullComment;
VisitFull(fullComment);
}
return true;
}
@ -37,6 +32,7 @@ namespace CppSharp.Passes @@ -37,6 +32,7 @@ namespace CppSharp.Passes
return true;
}
#region Comments Visit
public bool VisitHTMLEndTag(HTMLEndTagComment comment) => true;
@ -44,27 +40,94 @@ namespace CppSharp.Passes @@ -44,27 +40,94 @@ namespace CppSharp.Passes
public bool VisitInlineCommand(InlineCommandComment comment) => true;
public bool VisitParagraphCommand(ParagraphComment comment)
public bool VisitParagraph(ParagraphComment comment)
{
for (int i = 0; i < comment.Content.Count; i++)
// Fix clang parsing html tags as TextComment's
var textComments = comment.Content
.Where(c => c.Kind == DocumentationCommentKind.TextComment)
.Cast<TextComment>()
.ToArray();
for (var i = 0; i < textComments.Length; ++i)
{
if (comment.Content[i].Kind == DocumentationCommentKind.InlineCommandComment &&
i + 1 < comment.Content.Count &&
comment.Content[i + 1].Kind == DocumentationCommentKind.TextComment)
TextComment textComment = textComments[i];
if (textComment.IsEmpty)
{
var textComment = (TextComment)comment.Content[i + 1];
textComment.Text = Helpers.RegexCommentCommandLeftover.Replace(
textComment.Text, string.Empty);
comment.Content.Remove(textComment);
continue;
}
if (!textComment.Text.StartsWith('<'))
continue;
if (textComment.Text.Length < 2 || i + 1 >= textComments.Length)
continue;
bool isEndTag = textComment.Text[1] == '/';
// Replace the TextComment node with a HTMLTagComment node
HTMLTagComment htmlTag = isEndTag ? new HTMLEndTagComment() : new HTMLStartTagComment();
htmlTag.TagName = textComment.Text[(1 + (isEndTag ? 1 : 0))..];
// Cleanup next element
TextComment next = textComments[i + 1];
int tagEnd = next.Text.IndexOf('>');
if (tagEnd == -1)
continue;
if (!isEndTag)
{
var startTag = (htmlTag as HTMLStartTagComment)!;
var tagRemains = next.Text[..tagEnd];
if (tagRemains.EndsWith('/'))
{
startTag.SelfClosing = true;
tagRemains = tagRemains[..^1];
}
var attributes = tagRemains.Split(' ', StringSplitOptions.RemoveEmptyEntries);
foreach (var attribute in attributes)
{
var args = attribute.Split('=');
startTag.Attributes.Add(new HTMLStartTagComment.Attribute
{
Name = args[0].Trim(),
Value = args.ElementAtOrDefault(1)?.Trim(' ', '"'),
});
}
}
// Strip tagRemains from next element
next.Text = next.Text[(tagEnd + 1)..];
if (string.IsNullOrEmpty(next.Text))
{
htmlTag.HasTrailingNewline = next.HasTrailingNewline;
comment.Content.Remove(next);
}
// Replace element
var insertPos = comment.Content.IndexOf(textComment);
comment.Content.RemoveAt(insertPos);
comment.Content.Insert(insertPos, htmlTag);
}
foreach (var item in comment.Content.Where(c => c.Kind == DocumentationCommentKind.TextComment))
for (int i = 0; i < comment.Content.Count; i++)
{
var textComment = (TextComment)item;
if (comment.Content[i].Kind != DocumentationCommentKind.InlineCommandComment)
continue;
if (i + 1 >= comment.Content.Count)
continue;
if (textComment.Text.StartsWith("<", StringComparison.Ordinal))
textComment.Text = $"{textComment.Text}>";
else if (textComment.Text.StartsWith(">", StringComparison.Ordinal))
textComment.Text = textComment.Text.Substring(1);
if (comment.Content[i + 1].Kind != DocumentationCommentKind.TextComment)
continue;
var textComment = (TextComment)comment.Content[i + 1];
textComment.Text = Helpers.RegexCommentCommandLeftover.Replace(
textComment.Text, string.Empty);
}
return true;
}

2
src/Generator/Passes/FixParameterUsageFromComments.cs

@ -71,7 +71,7 @@ namespace CppSharp.Passes @@ -71,7 +71,7 @@ namespace CppSharp.Passes
return true;
}
public bool VisitParagraphCommand(ParagraphComment comment)
public bool VisitParagraph(ParagraphComment comment)
{
return true;
}

4
src/Generator/Utils/HtmlEncoder.cs

@ -53,7 +53,7 @@ namespace System.Web.Util @@ -53,7 +53,7 @@ namespace System.Web.Util
return null;
if (s.Length == 0)
return String.Empty;
return string.Empty;
bool needEncode = s.Any(c => c == '&' || c == '"' || c == '<' || c == '>' || c > 159);
@ -93,7 +93,7 @@ namespace System.Web.Util @@ -93,7 +93,7 @@ namespace System.Web.Util
{
output.Append("&#");
output.Append(((int)ch).ToString(CultureInfo.InvariantCulture));
output.Append(";");
output.Append(';');
}
else
output.Append(ch);

2
tests/dotnet/NamespacesDerived/NamespacesDerived.Tests.cs

@ -157,7 +157,7 @@ public class NamespaceDerivedTests @@ -157,7 +157,7 @@ public class NamespaceDerivedTests
"The context of the specified window must not be current on any other",
"thread when this function is called.",
"This function must not be called from a callback.",
"_safety This function must only be called from the main thread.",
"This function must only be called from the main thread.",
"Added in version 3.0. Replaces `glfwCloseWindow`."
}));
XElement window = method.Element("param");

37
tests/dotnet/Native/Passes.h

@ -45,6 +45,43 @@ class TestCommentsPass @@ -45,6 +45,43 @@ class TestCommentsPass
{
};
/// <summary>A more complex test.</summary>
class TestCommentsPass2
{
public:
/// <summary>Gets a value</summary>
/// <returns>One</returns>
float GetValueWithComment()
{
return 1.0f;
}
/// <summary>Sets a value. Get it with <see cref="GetValueWithComment"/></summary>
/// <param name="value">The value to set</param>
/// <returns>The parameter (typeof<float>)</returns>
float SetValueWithParamComment(float value)
{
return value;
}
/// <summary>
/// This method changes the point's location by
/// the given x- and y-offsets.
/// For example:
/// <code>
/// Point p = new Point(3, 5);
/// p.Translate(-1, 3);
/// </code>
/// results in <c>p</c>'s having the value (2, 8).
/// <see cref="Move"/>
/// </summary>
/// <param name="dx">The relative x-offset.</param>
/// <param name="dy">The relative y-offset.</param>
void Translate(int dx, int dy)
{
}
};
struct TestReadOnlyProperties
{
int readOnlyProperty;

Loading…
Cancel
Save