1748 lines
64 KiB
C#
1748 lines
64 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Resources;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Xml;
|
|
using System.Xml.Linq;
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Microsoft.CodeAnalysis.PooledObjects;
|
|
using Microsoft.CodeAnalysis.Text;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal class DocumentationCommentCompiler : CSharpSymbolVisitor
|
|
{
|
|
private readonly struct TemporaryStringBuilder(int indentDepth)
|
|
{
|
|
public readonly PooledStringBuilder Pooled = PooledStringBuilder.GetInstance();
|
|
|
|
public readonly int InitialIndentDepth = indentDepth;
|
|
}
|
|
|
|
[DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
|
|
private class DocumentationCommentWalker : CSharpSyntaxWalker
|
|
{
|
|
private readonly CSharpCompilation _compilation;
|
|
|
|
private readonly BindingDiagnosticBag _diagnostics;
|
|
|
|
private readonly Symbol _memberSymbol;
|
|
|
|
private readonly StringWriter _writer;
|
|
|
|
private readonly ArrayBuilder<CSharpSyntaxNode> _includeElementNodes;
|
|
|
|
private HashSet<ParameterSymbol> _documentedParameters;
|
|
|
|
private HashSet<TypeParameterSymbol> _documentedTypeParameters;
|
|
|
|
private DocumentationCommentWalker(CSharpCompilation compilation, BindingDiagnosticBag diagnostics, Symbol memberSymbol, StringWriter writer, ArrayBuilder<CSharpSyntaxNode> includeElementNodes, HashSet<ParameterSymbol> documentedParameters, HashSet<TypeParameterSymbol> documentedTypeParameters)
|
|
: base((SyntaxWalkerDepth)3)
|
|
{
|
|
_compilation = compilation;
|
|
_diagnostics = diagnostics;
|
|
_memberSymbol = memberSymbol;
|
|
_writer = writer;
|
|
_includeElementNodes = includeElementNodes;
|
|
_documentedParameters = documentedParameters;
|
|
_documentedTypeParameters = documentedTypeParameters;
|
|
}
|
|
|
|
public static void GetSubstitutedText(CSharpCompilation compilation, SynthesizedRecordPropertySymbol symbol, ArrayBuilder<XmlElementSyntax> paramElements, ArrayBuilder<CSharpSyntaxNode> includeElementNodes, StringBuilder builder)
|
|
{
|
|
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
|
|
StringWriter stringWriter = new StringWriter(builder, CultureInfo.InvariantCulture);
|
|
DocumentationCommentWalker documentationCommentWalker = new DocumentationCommentWalker(compilation, BindingDiagnosticBag.Discarded, symbol, stringWriter, includeElementNodes, null, null);
|
|
Enumerator<XmlElementSyntax> enumerator = paramElements.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
XmlElementSyntax current = enumerator.Current;
|
|
SyntaxToken lessThanToken = current.StartTag.LessThanToken;
|
|
if (!((SyntaxToken)(ref lessThanToken)).LeadingTrivia.Any(SyntaxKind.DocumentationCommentExteriorTrivia))
|
|
{
|
|
documentationCommentWalker.VisitToken(((SyntaxToken)(ref lessThanToken)).GetPreviousToken(false, false, false, false));
|
|
}
|
|
documentationCommentWalker.VisitToken(lessThanToken);
|
|
stringWriter.Write("summary");
|
|
documentationCommentWalker.VisitToken(current.StartTag.GreaterThanToken);
|
|
Enumerator<XmlNodeSyntax> enumerator2 = current.Content.GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
XmlNodeSyntax current2 = enumerator2.Current;
|
|
documentationCommentWalker.Visit((SyntaxNode?)(object)current2);
|
|
}
|
|
documentationCommentWalker.VisitToken(current.EndTag.LessThanSlashToken);
|
|
stringWriter.Write("summary");
|
|
SyntaxToken greaterThanToken = current.EndTag.GreaterThanToken;
|
|
documentationCommentWalker.VisitToken(greaterThanToken);
|
|
SyntaxToken nextToken = ((SyntaxToken)(ref greaterThanToken)).GetNextToken(false, false, false, false);
|
|
if (nextToken.IsKind(SyntaxKind.XmlTextLiteralNewLineToken))
|
|
{
|
|
documentationCommentWalker.VisitToken(nextToken);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static string GetSubstitutedText(CSharpCompilation compilation, BindingDiagnosticBag diagnostics, Symbol symbol, DocumentationCommentTriviaSyntax trivia, ArrayBuilder<CSharpSyntaxNode> includeElementNodes, ref HashSet<ParameterSymbol> documentedParameters, ref HashSet<TypeParameterSymbol> documentedTypeParameters)
|
|
{
|
|
PooledStringBuilder instance = PooledStringBuilder.GetInstance();
|
|
using (StringWriter writer = new StringWriter(instance.Builder, CultureInfo.InvariantCulture))
|
|
{
|
|
DocumentationCommentWalker documentationCommentWalker = new DocumentationCommentWalker(compilation, diagnostics, symbol, writer, includeElementNodes, documentedParameters, documentedTypeParameters);
|
|
documentationCommentWalker.Visit((SyntaxNode?)(object)trivia);
|
|
documentedParameters = documentationCommentWalker._documentedParameters;
|
|
documentedTypeParameters = documentationCommentWalker._documentedTypeParameters;
|
|
}
|
|
return instance.ToStringAndFree();
|
|
}
|
|
|
|
public override void DefaultVisit(SyntaxNode node)
|
|
{
|
|
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0182: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
|
|
SyntaxKind syntaxKind = node.Kind();
|
|
bool flag = node.SyntaxTree.ReportDocumentationCommentDiagnostics();
|
|
SyntaxToken val;
|
|
if (syntaxKind == SyntaxKind.XmlCrefAttribute)
|
|
{
|
|
XmlCrefAttributeSyntax xmlCrefAttributeSyntax = (XmlCrefAttributeSyntax)(object)node;
|
|
CrefSyntax cref = xmlCrefAttributeSyntax.Cref;
|
|
Binder binder = _compilation.GetBinderFactory(cref.SyntaxTree).GetBinder((SyntaxNode)(object)cref);
|
|
BindingDiagnosticBag bindingDiagnosticBag = (flag ? _diagnostics : BindingDiagnosticBag.GetInstance(withDiagnostics: false, ((BindingDiagnosticBag<AssemblySymbol>)(object)_diagnostics).AccumulatesDependencies));
|
|
string documentationCommentId = GetDocumentationCommentId(cref, binder, bindingDiagnosticBag);
|
|
if (!flag)
|
|
{
|
|
((BindingDiagnosticBag<AssemblySymbol>)(object)_diagnostics).AddRangeAndFree((BindingDiagnosticBag<AssemblySymbol>)(object)bindingDiagnosticBag);
|
|
}
|
|
if (_writer != null)
|
|
{
|
|
Visit((SyntaxNode?)(object)xmlCrefAttributeSyntax.Name);
|
|
VisitToken(xmlCrefAttributeSyntax.EqualsToken);
|
|
val = xmlCrefAttributeSyntax.StartQuoteToken;
|
|
((SyntaxToken)(ref val)).WriteTo((TextWriter)_writer, true, false);
|
|
_writer.Write(documentationCommentId);
|
|
val = xmlCrefAttributeSyntax.EndQuoteToken;
|
|
((SyntaxToken)(ref val)).WriteTo((TextWriter)_writer, false, true);
|
|
}
|
|
return;
|
|
}
|
|
if (flag && syntaxKind == SyntaxKind.XmlNameAttribute)
|
|
{
|
|
XmlNameAttributeSyntax xmlNameAttributeSyntax = (XmlNameAttributeSyntax)(object)node;
|
|
Binder binder2 = _compilation.GetBinderFactory(xmlNameAttributeSyntax.SyntaxTree).GetBinder((SyntaxNode)(object)xmlNameAttributeSyntax, ((SyntaxNode)xmlNameAttributeSyntax.Identifier).SpanStart);
|
|
BindName(xmlNameAttributeSyntax, binder2, _memberSymbol, ref _documentedParameters, ref _documentedTypeParameters, _diagnostics);
|
|
}
|
|
if (_includeElementNodes != null)
|
|
{
|
|
XmlNameSyntax xmlNameSyntax = null;
|
|
switch (syntaxKind)
|
|
{
|
|
case SyntaxKind.XmlEmptyElement:
|
|
xmlNameSyntax = ((XmlEmptyElementSyntax)(object)node).Name;
|
|
break;
|
|
case SyntaxKind.XmlElementStartTag:
|
|
xmlNameSyntax = ((XmlElementStartTagSyntax)(object)node).Name;
|
|
break;
|
|
}
|
|
if (xmlNameSyntax != null && xmlNameSyntax.Prefix == null)
|
|
{
|
|
val = xmlNameSyntax.LocalName;
|
|
if (DocumentationCommentXmlNames.ElementEquals(((SyntaxToken)(ref val)).ValueText, "include", false))
|
|
{
|
|
_includeElementNodes.Add((CSharpSyntaxNode)(object)node);
|
|
}
|
|
}
|
|
}
|
|
base.DefaultVisit(node);
|
|
}
|
|
|
|
public override void VisitToken(SyntaxToken token)
|
|
{
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
|
if (_writer != null)
|
|
{
|
|
((SyntaxToken)(ref token)).WriteTo((TextWriter)_writer);
|
|
}
|
|
base.VisitToken(token);
|
|
}
|
|
|
|
private string GetDebuggerDisplay()
|
|
{
|
|
return _writer.GetStringBuilder().ToString();
|
|
}
|
|
}
|
|
|
|
private class IncludeElementExpander
|
|
{
|
|
private readonly Symbol _memberSymbol;
|
|
|
|
private readonly ImmutableArray<CSharpSyntaxNode> _sourceIncludeElementNodes;
|
|
|
|
private readonly CSharpCompilation _compilation;
|
|
|
|
private readonly BindingDiagnosticBag _diagnostics;
|
|
|
|
private readonly CancellationToken _cancellationToken;
|
|
|
|
private int _nextSourceIncludeElementIndex;
|
|
|
|
private HashSet<Location> _inProgressIncludeElementNodes;
|
|
|
|
private HashSet<ParameterSymbol> _documentedParameters;
|
|
|
|
private HashSet<TypeParameterSymbol> _documentedTypeParameters;
|
|
|
|
private DocumentationCommentIncludeCache _includedFileCache;
|
|
|
|
private IncludeElementExpander(Symbol memberSymbol, ImmutableArray<CSharpSyntaxNode> sourceIncludeElementNodes, CSharpCompilation compilation, HashSet<ParameterSymbol> documentedParameters, HashSet<TypeParameterSymbol> documentedTypeParameters, DocumentationCommentIncludeCache includedFileCache, BindingDiagnosticBag diagnostics, CancellationToken cancellationToken)
|
|
{
|
|
_memberSymbol = memberSymbol;
|
|
_sourceIncludeElementNodes = sourceIncludeElementNodes;
|
|
_compilation = compilation;
|
|
_diagnostics = diagnostics;
|
|
_cancellationToken = cancellationToken;
|
|
_documentedParameters = documentedParameters;
|
|
_documentedTypeParameters = documentedTypeParameters;
|
|
_includedFileCache = includedFileCache;
|
|
_nextSourceIncludeElementIndex = 0;
|
|
}
|
|
|
|
public static void ProcessIncludes(string unprocessed, Symbol memberSymbol, ImmutableArray<CSharpSyntaxNode> sourceIncludeElementNodes, CSharpCompilation compilation, ref HashSet<ParameterSymbol> documentedParameters, ref HashSet<TypeParameterSymbol> documentedTypeParameters, ref DocumentationCommentIncludeCache includedFileCache, TextWriter writer, BindingDiagnosticBag diagnostics, CancellationToken cancellationToken)
|
|
{
|
|
if (sourceIncludeElementNodes.IsEmpty)
|
|
{
|
|
writer?.Write(unprocessed);
|
|
return;
|
|
}
|
|
XDocument node;
|
|
try
|
|
{
|
|
node = XDocument.Parse(unprocessed, LoadOptions.PreserveWhitespace);
|
|
}
|
|
catch (XmlException)
|
|
{
|
|
writer?.Write(unprocessed);
|
|
return;
|
|
}
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
IncludeElementExpander includeElementExpander = new IncludeElementExpander(memberSymbol, sourceIncludeElementNodes, compilation, documentedParameters, documentedTypeParameters, includedFileCache, diagnostics, cancellationToken);
|
|
XNode[] array = includeElementExpander.Rewrite(node, null, null);
|
|
foreach (XNode value in array)
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
writer?.Write(value);
|
|
}
|
|
documentedParameters = includeElementExpander._documentedParameters;
|
|
documentedTypeParameters = includeElementExpander._documentedTypeParameters;
|
|
includedFileCache = includeElementExpander._includedFileCache;
|
|
}
|
|
|
|
private XNode[] RewriteMany(XNode[] nodes, string currentXmlFilePath, CSharpSyntaxNode originatingSyntax)
|
|
{
|
|
ArrayBuilder<XNode> val = null;
|
|
foreach (XNode node in nodes)
|
|
{
|
|
if (val == null)
|
|
{
|
|
val = ArrayBuilder<XNode>.GetInstance();
|
|
}
|
|
val.AddRange(Rewrite(node, currentXmlFilePath, originatingSyntax));
|
|
}
|
|
if (val != null)
|
|
{
|
|
return val.ToArrayAndFree();
|
|
}
|
|
return Array.Empty<XNode>();
|
|
}
|
|
|
|
private XNode[] Rewrite(XNode node, string currentXmlFilePath, CSharpSyntaxNode originatingSyntax)
|
|
{
|
|
CancellationToken cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
string commentMessage = null;
|
|
if (node.NodeType == XmlNodeType.Element)
|
|
{
|
|
XElement xElement = (XElement)node;
|
|
if (ElementNameIs(xElement, "include"))
|
|
{
|
|
XNode[] array = RewriteIncludeElement(xElement, currentXmlFilePath, originatingSyntax, out commentMessage);
|
|
if (array != null)
|
|
{
|
|
return array;
|
|
}
|
|
}
|
|
}
|
|
if (node is XContainer xContainer)
|
|
{
|
|
IEnumerable<XNode> enumerable = xContainer.Nodes();
|
|
XContainer xContainer2 = XmlUtilities.Copy<XContainer>(xContainer, false);
|
|
if (enumerable != null)
|
|
{
|
|
XNode[] array2 = RewriteMany(enumerable.ToArray(), currentXmlFilePath, originatingSyntax);
|
|
object[] content = array2;
|
|
xContainer2.ReplaceNodes(content);
|
|
}
|
|
if (xContainer2.NodeType == XmlNodeType.Element && originatingSyntax != null)
|
|
{
|
|
XElement xElement2 = (XElement)xContainer2;
|
|
foreach (XAttribute item in xElement2.Attributes())
|
|
{
|
|
if (AttributeNameIs(item, "cref"))
|
|
{
|
|
BindAndReplaceCref(item, originatingSyntax);
|
|
}
|
|
else if (AttributeNameIs(item, "name"))
|
|
{
|
|
if (ElementNameIs(xElement2, "param") || ElementNameIs(xElement2, "paramref"))
|
|
{
|
|
BindName(item, originatingSyntax, isParameter: true, isTypeParameterRef: false);
|
|
}
|
|
else if (ElementNameIs(xElement2, "typeparam"))
|
|
{
|
|
BindName(item, originatingSyntax, isParameter: false, isTypeParameterRef: false);
|
|
}
|
|
else if (ElementNameIs(xElement2, "typeparamref"))
|
|
{
|
|
BindName(item, originatingSyntax, isParameter: false, isTypeParameterRef: true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (commentMessage != null)
|
|
{
|
|
XComment xComment = new XComment(commentMessage);
|
|
return new XNode[2] { xComment, xContainer2 };
|
|
}
|
|
return new XNode[1] { xContainer2 };
|
|
}
|
|
return new XNode[1] { XmlUtilities.Copy<XNode>(node, false) };
|
|
}
|
|
|
|
private static bool ElementNameIs(XElement element, string name)
|
|
{
|
|
if (string.IsNullOrEmpty(element.Name.NamespaceName))
|
|
{
|
|
return DocumentationCommentXmlNames.ElementEquals(element.Name.LocalName, name, false);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static bool AttributeNameIs(XAttribute attribute, string name)
|
|
{
|
|
if (string.IsNullOrEmpty(attribute.Name.NamespaceName))
|
|
{
|
|
return DocumentationCommentXmlNames.AttributeEquals(attribute.Name.LocalName, name);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private XNode[] RewriteIncludeElement(XElement includeElement, string currentXmlFilePath, CSharpSyntaxNode originatingSyntax, out string commentMessage)
|
|
{
|
|
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0215: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_021f: Expected O, but got Unknown
|
|
Location includeElementLocation = GetIncludeElementLocation(includeElement, ref currentXmlFilePath, ref originatingSyntax);
|
|
bool flag = originatingSyntax.SyntaxTree.ReportDocumentationCommentDiagnostics();
|
|
if (!EnterIncludeElement(includeElementLocation))
|
|
{
|
|
XAttribute xAttribute = includeElement.Attribute(XName.Get("file"));
|
|
XAttribute? xAttribute2 = includeElement.Attribute(XName.Get("path"));
|
|
string value = xAttribute.Value;
|
|
string value2 = xAttribute2.Value;
|
|
if (flag)
|
|
{
|
|
_diagnostics.Add(ErrorCode.WRN_FailedInclude, includeElementLocation, value, value2, new LocalizableErrorArgument(MessageID.IDS_OperationCausedStackOverflow));
|
|
}
|
|
commentMessage = ErrorFacts.GetMessage(MessageID.IDS_XMLNOINCLUDE, CultureInfo.CurrentUICulture);
|
|
return new XNode[2]
|
|
{
|
|
new XComment(commentMessage),
|
|
XmlUtilities.Copy<XElement>(includeElement, false)
|
|
};
|
|
}
|
|
DiagnosticBag instance = DiagnosticBag.GetInstance();
|
|
try
|
|
{
|
|
XAttribute xAttribute3 = includeElement.Attribute(XName.Get("file"));
|
|
XAttribute xAttribute4 = includeElement.Attribute(XName.Get("path"));
|
|
bool flag2 = xAttribute3 != null;
|
|
bool flag3 = xAttribute4 != null;
|
|
if (!flag2 || !flag3)
|
|
{
|
|
LocalizableErrorArgument localizableErrorArgument = (flag2 ? MessageID.IDS_XMLMISSINGINCLUDEPATH.Localize() : MessageID.IDS_XMLMISSINGINCLUDEFILE.Localize());
|
|
instance.Add(ErrorCode.WRN_InvalidInclude, includeElementLocation, localizableErrorArgument);
|
|
commentMessage = MakeCommentMessage(includeElementLocation, MessageID.IDS_XMLBADINCLUDE);
|
|
return null;
|
|
}
|
|
string value3 = xAttribute4.Value;
|
|
string value4 = xAttribute3.Value;
|
|
XmlReferenceResolver xmlReferenceResolver = ((CompilationOptions)_compilation.Options).XmlReferenceResolver;
|
|
if (xmlReferenceResolver == null)
|
|
{
|
|
instance.Add(ErrorCode.WRN_FailedInclude, includeElementLocation, value4, value3, (object)new CodeAnalysisResourcesLocalizableErrorArgument("XmlReferencesNotSupported"));
|
|
commentMessage = MakeCommentMessage(includeElementLocation, MessageID.IDS_XMLFAILEDINCLUDE);
|
|
return null;
|
|
}
|
|
string text = xmlReferenceResolver.ResolveReference(value4, currentXmlFilePath);
|
|
if (text == null)
|
|
{
|
|
instance.Add(ErrorCode.WRN_FailedInclude, includeElementLocation, value4, value3, (object)new CodeAnalysisResourcesLocalizableErrorArgument("FileNotFound"));
|
|
commentMessage = MakeCommentMessage(includeElementLocation, MessageID.IDS_XMLFAILEDINCLUDE);
|
|
return null;
|
|
}
|
|
if (_includedFileCache == null)
|
|
{
|
|
_includedFileCache = new DocumentationCommentIncludeCache(xmlReferenceResolver);
|
|
}
|
|
try
|
|
{
|
|
XDocument orMakeDocument;
|
|
try
|
|
{
|
|
orMakeDocument = _includedFileCache.GetOrMakeDocument(text);
|
|
}
|
|
catch (IOException ex)
|
|
{
|
|
instance.Add(ErrorCode.WRN_FailedInclude, includeElementLocation, value4, value3, ex.Message);
|
|
commentMessage = MakeCommentMessage(includeElementLocation, MessageID.IDS_XMLFAILEDINCLUDE);
|
|
return null;
|
|
}
|
|
string text2 = default(string);
|
|
bool flag4 = default(bool);
|
|
XElement[] array = XmlUtilities.TrySelectElements((XNode)orMakeDocument, value3, ref text2, ref flag4);
|
|
if (array == null)
|
|
{
|
|
instance.Add(ErrorCode.WRN_FailedInclude, includeElementLocation, value4, value3, text2);
|
|
commentMessage = MakeCommentMessage(includeElementLocation, MessageID.IDS_XMLFAILEDINCLUDE);
|
|
if (flag4)
|
|
{
|
|
return null;
|
|
}
|
|
if (includeElementLocation.IsInSource)
|
|
{
|
|
return new XNode[1]
|
|
{
|
|
new XComment(commentMessage)
|
|
};
|
|
}
|
|
commentMessage = null;
|
|
return Array.Empty<XNode>();
|
|
}
|
|
if (array != null && array.Length != 0)
|
|
{
|
|
XNode[] nodes = array;
|
|
XNode[] array2 = RewriteMany(nodes, text, originatingSyntax);
|
|
if (array2.Length != 0)
|
|
{
|
|
commentMessage = null;
|
|
return array2;
|
|
}
|
|
}
|
|
commentMessage = MakeCommentMessage(includeElementLocation, MessageID.IDS_XMLNOINCLUDE);
|
|
return null;
|
|
}
|
|
catch (XmlException ex2)
|
|
{
|
|
Location location = (Location)(object)XmlLocation.Create(ex2, text);
|
|
instance.Add(ErrorCode.WRN_XMLParseIncludeError, location, GetDescription(ex2));
|
|
if (includeElementLocation.IsInSource)
|
|
{
|
|
commentMessage = string.Format(ErrorFacts.GetMessage(MessageID.IDS_XMLIGNORED2, CultureInfo.CurrentUICulture), text);
|
|
return new XNode[1]
|
|
{
|
|
new XComment(commentMessage)
|
|
};
|
|
}
|
|
commentMessage = null;
|
|
return Array.Empty<XNode>();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (flag)
|
|
{
|
|
((BindingDiagnosticBag<AssemblySymbol>)(object)_diagnostics).AddRange(instance);
|
|
}
|
|
instance.Free();
|
|
LeaveIncludeElement(includeElementLocation);
|
|
}
|
|
}
|
|
|
|
private static string MakeCommentMessage(Location location, MessageID messageId)
|
|
{
|
|
if (location.IsInSource)
|
|
{
|
|
return ErrorFacts.GetMessage(messageId, CultureInfo.CurrentUICulture);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private bool EnterIncludeElement(Location location)
|
|
{
|
|
if (_inProgressIncludeElementNodes == null)
|
|
{
|
|
_inProgressIncludeElementNodes = new HashSet<Location>();
|
|
}
|
|
return _inProgressIncludeElementNodes.Add(location);
|
|
}
|
|
|
|
private bool LeaveIncludeElement(Location location)
|
|
{
|
|
return _inProgressIncludeElementNodes.Remove(location);
|
|
}
|
|
|
|
private Location GetIncludeElementLocation(XElement includeElement, ref string currentXmlFilePath, ref CSharpSyntaxNode originatingSyntax)
|
|
{
|
|
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
|
|
Location val = includeElement.Annotation<Location>();
|
|
if (val != (Location)null)
|
|
{
|
|
return val;
|
|
}
|
|
if (currentXmlFilePath == null)
|
|
{
|
|
originatingSyntax = _sourceIncludeElementNodes[_nextSourceIncludeElementIndex];
|
|
val = ((SyntaxNode)originatingSyntax).Location;
|
|
_nextSourceIncludeElementIndex++;
|
|
FileLinePositionSpan lineSpan = val.GetLineSpan();
|
|
currentXmlFilePath = ((FileLinePositionSpan)(ref lineSpan)).Path;
|
|
}
|
|
else
|
|
{
|
|
val = (Location)(object)XmlLocation.Create((XObject)includeElement, currentXmlFilePath);
|
|
}
|
|
includeElement.AddAnnotation(val);
|
|
return val;
|
|
}
|
|
|
|
private void BindAndReplaceCref(XAttribute attribute, CSharpSyntaxNode originatingSyntax)
|
|
{
|
|
CrefSyntax crefSyntax = SyntaxFactory.ParseCref(attribute.Value);
|
|
if (crefSyntax != null)
|
|
{
|
|
Location location = ((SyntaxNode)originatingSyntax).Location;
|
|
RecordSyntaxDiagnostics(crefSyntax, location);
|
|
MemberDeclarationSyntax associatedMemberForXmlSyntax = BinderFactory.GetAssociatedMemberForXmlSyntax(originatingSyntax);
|
|
Binder binder = BinderFactory.MakeCrefBinder(crefSyntax, associatedMemberForXmlSyntax, _compilation.GetBinderFactory(associatedMemberForXmlSyntax.SyntaxTree));
|
|
BindingDiagnosticBag instance = BindingDiagnosticBag.GetInstance(_diagnostics);
|
|
attribute.Value = GetDocumentationCommentId(crefSyntax, binder, instance);
|
|
RecordBindingDiagnostics(instance, location);
|
|
((BindingDiagnosticBag<AssemblySymbol>)(object)instance).Free();
|
|
}
|
|
}
|
|
|
|
private void BindName(XAttribute attribute, CSharpSyntaxNode originatingSyntax, bool isParameter, bool isTypeParameterRef)
|
|
{
|
|
XmlNameAttributeSyntax xmlNameAttributeSyntax = ParseNameAttribute(attribute.ToString(), attribute.Parent.Name.LocalName);
|
|
Location location = ((SyntaxNode)originatingSyntax).Location;
|
|
RecordSyntaxDiagnostics(xmlNameAttributeSyntax, location);
|
|
BinderFactory.GetAssociatedMemberForXmlSyntax(originatingSyntax);
|
|
BindingDiagnosticBag instance = BindingDiagnosticBag.GetInstance(_diagnostics);
|
|
Binder binder = MakeNameBinder(isParameter, isTypeParameterRef, _memberSymbol, _compilation, originatingSyntax.SyntaxTree);
|
|
DocumentationCommentCompiler.BindName(xmlNameAttributeSyntax, binder, _memberSymbol, ref _documentedParameters, ref _documentedTypeParameters, instance);
|
|
RecordBindingDiagnostics(instance, location);
|
|
((BindingDiagnosticBag<AssemblySymbol>)(object)instance).Free();
|
|
}
|
|
|
|
private static Binder MakeNameBinder(bool isParameter, bool isTypeParameterRef, Symbol memberSymbol, CSharpCompilation compilation, SyntaxTree syntaxTree)
|
|
{
|
|
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0032: Invalid comparison between Unknown and I4
|
|
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a9: Invalid comparison between Unknown and I4
|
|
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0045: Invalid comparison between Unknown and I4
|
|
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0037: Invalid comparison between Unknown and I4
|
|
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00af: Invalid comparison between Unknown and I4
|
|
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004b: Invalid comparison between Unknown and I4
|
|
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003d: Invalid comparison between Unknown and I4
|
|
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00b5: Invalid comparison between Unknown and I4
|
|
Binder binder = new BuckStopsHereBinder(compilation, FileIdentifier.Create(syntaxTree));
|
|
Symbol containingSymbol = memberSymbol.ContainingSymbol;
|
|
binder = binder.WithContainingMemberOrLambda(containingSymbol);
|
|
ImmutableArray<ParameterSymbol> parameters;
|
|
if (isParameter)
|
|
{
|
|
parameters = ImmutableArray<ParameterSymbol>.Empty;
|
|
SymbolKind kind = memberSymbol.Kind;
|
|
if ((int)kind <= 9)
|
|
{
|
|
if ((int)kind == 4)
|
|
{
|
|
goto IL_006b;
|
|
}
|
|
if ((int)kind == 9)
|
|
{
|
|
parameters = ((MethodSymbol)memberSymbol).Parameters;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((int)kind == 11)
|
|
{
|
|
goto IL_006b;
|
|
}
|
|
if ((int)kind == 15)
|
|
{
|
|
parameters = ((PropertySymbol)memberSymbol).Parameters;
|
|
}
|
|
}
|
|
goto IL_0086;
|
|
}
|
|
Symbol symbol = memberSymbol;
|
|
do
|
|
{
|
|
SymbolKind kind = symbol.Kind;
|
|
if ((int)kind == 4)
|
|
{
|
|
goto IL_00b7;
|
|
}
|
|
if ((int)kind != 9)
|
|
{
|
|
if ((int)kind == 11)
|
|
{
|
|
goto IL_00b7;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MethodSymbol methodSymbol = (MethodSymbol)symbol;
|
|
if (methodSymbol.Arity > 0)
|
|
{
|
|
binder = new WithMethodTypeParametersBinder(methodSymbol, binder);
|
|
}
|
|
}
|
|
goto IL_00f1;
|
|
IL_00b7:
|
|
NamedTypeSymbol namedTypeSymbol = (NamedTypeSymbol)symbol;
|
|
if (namedTypeSymbol.Arity > 0)
|
|
{
|
|
binder = new WithClassTypeParametersBinder(namedTypeSymbol, binder);
|
|
}
|
|
goto IL_00f1;
|
|
IL_00f1:
|
|
symbol = symbol.ContainingSymbol;
|
|
}
|
|
while (isTypeParameterRef && (object)symbol != null);
|
|
goto IL_0101;
|
|
IL_006b:
|
|
NamedTypeSymbol namedTypeSymbol2 = (NamedTypeSymbol)memberSymbol;
|
|
if (namedTypeSymbol2.IsDelegateType())
|
|
{
|
|
parameters = namedTypeSymbol2.DelegateInvokeMethod.Parameters;
|
|
}
|
|
goto IL_0086;
|
|
IL_0086:
|
|
if (parameters.Length > 0)
|
|
{
|
|
binder = new WithParametersBinder(parameters, binder);
|
|
}
|
|
goto IL_0101;
|
|
IL_0101:
|
|
return binder;
|
|
}
|
|
|
|
private static XmlNameAttributeSyntax ParseNameAttribute(string attributeText, string elementName)
|
|
{
|
|
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
|
|
SyntaxTriviaList val = SyntaxFactory.ParseLeadingTrivia($"/// <{elementName} {attributeText}/>", CSharpParseOptions.Default.WithDocumentationMode((DocumentationMode)2));
|
|
SyntaxTrivia val2 = ((SyntaxTriviaList)(ref val)).ElementAt(0);
|
|
return (XmlNameAttributeSyntax)((XmlEmptyElementSyntax)((DocumentationCommentTriviaSyntax)(object)((SyntaxTrivia)(ref val2)).GetStructure()).Content[1]).Attributes[0];
|
|
}
|
|
|
|
private void RecordSyntaxDiagnostics(CSharpSyntaxNode treelessSyntax, Location sourceLocation)
|
|
{
|
|
if (!((SyntaxNode)treelessSyntax).ContainsDiagnostics || !sourceLocation.SourceTree.ReportDocumentationCommentDiagnostics())
|
|
{
|
|
return;
|
|
}
|
|
foreach (Diagnostic diagnostic in CSharpSyntaxTree.Dummy.GetDiagnostics((SyntaxNode)(object)treelessSyntax))
|
|
{
|
|
((BindingDiagnosticBag)_diagnostics).Add(diagnostic.WithLocation(sourceLocation));
|
|
}
|
|
}
|
|
|
|
private void RecordBindingDiagnostics(BindingDiagnosticBag bindingDiagnostics, Location sourceLocation)
|
|
{
|
|
if (sourceLocation.SourceTree.ReportDocumentationCommentDiagnostics())
|
|
{
|
|
DiagnosticBag diagnosticBag = ((BindingDiagnosticBag)bindingDiagnostics).DiagnosticBag;
|
|
if (diagnosticBag != null && !diagnosticBag.IsEmptyWithoutResolution)
|
|
{
|
|
foreach (Diagnostic item in ((BindingDiagnosticBag)bindingDiagnostics).DiagnosticBag.AsEnumerable())
|
|
{
|
|
((BindingDiagnosticBag)_diagnostics).Add(item.WithLocation(sourceLocation));
|
|
}
|
|
}
|
|
}
|
|
((BindingDiagnosticBag<AssemblySymbol>)(object)_diagnostics).AddDependencies((BindingDiagnosticBag<AssemblySymbol>)(object)bindingDiagnostics, false);
|
|
}
|
|
}
|
|
|
|
private readonly string _assemblyName;
|
|
|
|
private readonly CSharpCompilation _compilation;
|
|
|
|
private readonly TextWriter _writer;
|
|
|
|
private readonly SyntaxTree _filterTree;
|
|
|
|
private readonly TextSpan? _filterSpanWithinTree;
|
|
|
|
private readonly bool _processIncludes;
|
|
|
|
private readonly bool _isForSingleSymbol;
|
|
|
|
private readonly BindingDiagnosticBag _diagnostics;
|
|
|
|
private readonly CancellationToken _cancellationToken;
|
|
|
|
private SyntaxNodeLocationComparer _lazyComparer;
|
|
|
|
private DocumentationCommentIncludeCache _includedFileCache;
|
|
|
|
private int _indentDepth;
|
|
|
|
private Stack<TemporaryStringBuilder> _temporaryStringBuilders;
|
|
|
|
private static readonly string[] s_newLineSequences = new string[3] { "\r\n", "\r", "\n" };
|
|
|
|
private IComparer<CSharpSyntaxNode> Comparer
|
|
{
|
|
get
|
|
{
|
|
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0019: Expected O, but got Unknown
|
|
if (_lazyComparer == null)
|
|
{
|
|
_lazyComparer = new SyntaxNodeLocationComparer((Compilation)(object)_compilation);
|
|
}
|
|
return (IComparer<CSharpSyntaxNode>)_lazyComparer;
|
|
}
|
|
}
|
|
|
|
private DocumentationCommentCompiler(string assemblyName, CSharpCompilation compilation, TextWriter writer, SyntaxTree filterTree, TextSpan? filterSpanWithinTree, bool processIncludes, bool isForSingleSymbol, BindingDiagnosticBag diagnostics, CancellationToken cancellationToken)
|
|
{
|
|
_assemblyName = assemblyName;
|
|
_compilation = compilation;
|
|
_writer = writer;
|
|
_filterTree = filterTree;
|
|
_filterSpanWithinTree = filterSpanWithinTree;
|
|
_processIncludes = processIncludes;
|
|
_isForSingleSymbol = isForSingleSymbol;
|
|
_diagnostics = diagnostics;
|
|
_cancellationToken = cancellationToken;
|
|
}
|
|
|
|
public static void WriteDocumentationCommentXml(CSharpCompilation compilation, string? assemblyName, Stream? xmlDocStream, BindingDiagnosticBag diagnostics, CancellationToken cancellationToken, SyntaxTree? filterTree = null, TextSpan? filterSpanWithinTree = null)
|
|
{
|
|
StreamWriter streamWriter = null;
|
|
if (xmlDocStream != null && xmlDocStream.CanWrite)
|
|
{
|
|
streamWriter = new StreamWriter(xmlDocStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false), 1024, leaveOpen: true);
|
|
}
|
|
try
|
|
{
|
|
using (streamWriter)
|
|
{
|
|
new DocumentationCommentCompiler(assemblyName ?? compilation.SourceAssembly.Name, compilation, streamWriter, filterTree, filterSpanWithinTree, processIncludes: true, isForSingleSymbol: false, diagnostics, cancellationToken).Visit(compilation.SourceAssembly.GlobalNamespace);
|
|
streamWriter?.Flush();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
diagnostics.Add(ErrorCode.ERR_DocFileGen, Location.None, ex.Message);
|
|
}
|
|
DiagnosticBag diagnosticBag = ((BindingDiagnosticBag)diagnostics).DiagnosticBag;
|
|
if (diagnosticBag == null)
|
|
{
|
|
return;
|
|
}
|
|
if (filterTree != null)
|
|
{
|
|
UnprocessedDocumentationCommentFinder.ReportUnprocessed(filterTree, filterSpanWithinTree, diagnosticBag, cancellationToken);
|
|
return;
|
|
}
|
|
ImmutableArray<SyntaxTree>.Enumerator enumerator = compilation.SyntaxTrees.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
UnprocessedDocumentationCommentFinder.ReportUnprocessed(enumerator.Current, null, diagnosticBag, cancellationToken);
|
|
}
|
|
}
|
|
|
|
internal static string GetDocumentationCommentXml(Symbol symbol, bool processIncludes, CancellationToken cancellationToken)
|
|
{
|
|
CSharpCompilation declaringCompilation = symbol.DeclaringCompilation;
|
|
PooledStringBuilder instance = PooledStringBuilder.GetInstance();
|
|
StringWriter stringWriter = new StringWriter(instance.Builder);
|
|
new DocumentationCommentCompiler(null, declaringCompilation, stringWriter, null, null, processIncludes, isForSingleSymbol: true, BindingDiagnosticBag.Discarded, cancellationToken).Visit(symbol);
|
|
stringWriter.Dispose();
|
|
return instance.ToStringAndFree();
|
|
}
|
|
|
|
public override void VisitNamespace(NamespaceSymbol symbol)
|
|
{
|
|
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
|
|
CancellationToken cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (symbol.IsGlobalNamespace)
|
|
{
|
|
WriteLine("<?xml version=\"1.0\"?>");
|
|
WriteLine("<doc>");
|
|
Indent();
|
|
if (!EnumBounds.IsNetModule(((CompilationOptions)_compilation.Options).OutputKind))
|
|
{
|
|
WriteLine("<assembly>");
|
|
Indent();
|
|
WriteLine("<name>{0}</name>", _assemblyName);
|
|
Unindent();
|
|
WriteLine("</assembly>");
|
|
}
|
|
WriteLine("<members>");
|
|
Indent();
|
|
}
|
|
ImmutableArray<Symbol>.Enumerator enumerator = symbol.GetMembers().GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
Symbol current = enumerator.Current;
|
|
cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
current.Accept(this);
|
|
}
|
|
if (symbol.IsGlobalNamespace)
|
|
{
|
|
Unindent();
|
|
WriteLine("</members>");
|
|
Unindent();
|
|
WriteLine("</doc>");
|
|
}
|
|
}
|
|
|
|
public override void VisitNamedType(NamedTypeSymbol symbol)
|
|
{
|
|
CancellationToken cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (_filterTree != null && !symbol.IsDefinedInSourceTree(_filterTree, _filterSpanWithinTree))
|
|
{
|
|
return;
|
|
}
|
|
DefaultVisit(symbol);
|
|
if (!_isForSingleSymbol)
|
|
{
|
|
ImmutableArray<Symbol>.Enumerator enumerator = symbol.GetMembers().GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
Symbol current = enumerator.Current;
|
|
cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
current.Accept(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void DefaultVisit(Symbol symbol)
|
|
{
|
|
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0115: Invalid comparison between Unknown and I4
|
|
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
|
|
CancellationToken cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (ShouldSkip(symbol) || (_filterTree != null && !symbol.IsDefinedInSourceTree(_filterTree, _filterSpanWithinTree)))
|
|
{
|
|
return;
|
|
}
|
|
bool flag = false;
|
|
if (symbol.IsPartialDefinition())
|
|
{
|
|
if (symbol is MethodSymbol { PartialImplementationPart: { } partialImplementationPart })
|
|
{
|
|
Visit(partialImplementationPart);
|
|
SyntaxTriviaList leadingTrivia = partialImplementationPart.GetNonNullSyntaxNode().GetLeadingTrivia();
|
|
Enumerator enumerator = ((SyntaxTriviaList)(ref leadingTrivia)).GetEnumerator();
|
|
while (((Enumerator)(ref enumerator)).MoveNext())
|
|
{
|
|
SyntaxKind syntaxKind = ((Enumerator)(ref enumerator)).Current.Kind();
|
|
if (syntaxKind - 8544 <= SyntaxKind.List)
|
|
{
|
|
flag = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
flag = !_isForSingleSymbol;
|
|
}
|
|
}
|
|
Symbol symbol2 = ((symbol is SynthesizedRecordPropertySymbol) ? symbol.ContainingType : symbol);
|
|
if (!TryGetDocumentationCommentNodes(symbol2, out var maxDocumentationMode, out var nodes))
|
|
{
|
|
string message = ErrorFacts.GetMessage(MessageID.IDS_XMLIGNORED, CultureInfo.CurrentUICulture);
|
|
WriteLine(string.Format(CultureInfo.CurrentUICulture, message, symbol.GetDocumentationCommentId()));
|
|
return;
|
|
}
|
|
if (nodes.IsEmpty)
|
|
{
|
|
if ((int)maxDocumentationMode >= 2 && RequiresDocumentationComment(symbol) && !symbol.IsPartialImplementation() && !flag)
|
|
{
|
|
Location locationInTreeReportingDocumentationCommentDiagnostics = GetLocationInTreeReportingDocumentationCommentDiagnostics(symbol);
|
|
if (locationInTreeReportingDocumentationCommentDiagnostics != (Location)null)
|
|
{
|
|
_diagnostics.Add(ErrorCode.WRN_MissingXMLComment, locationInTreeReportingDocumentationCommentDiagnostics, symbol);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (!TryProcessDocumentationCommentTriviaNodes(symbol, flag, nodes, out var withUnprocessedIncludes, out var haveParseError, out var documentedTypeParameters, out var documentedParameters, out var includeElementNodes))
|
|
{
|
|
return;
|
|
}
|
|
if (haveParseError)
|
|
{
|
|
string message2 = ErrorFacts.GetMessage(MessageID.IDS_XMLIGNORED, CultureInfo.CurrentUICulture);
|
|
WriteLine(string.Format(CultureInfo.CurrentUICulture, message2, symbol.GetDocumentationCommentId()));
|
|
return;
|
|
}
|
|
if (!includeElementNodes.IsDefaultOrEmpty)
|
|
{
|
|
cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
TextWriter writer = (flag ? null : _writer);
|
|
IncludeElementExpander.ProcessIncludes(withUnprocessedIncludes, symbol, includeElementNodes, _compilation, ref documentedParameters, ref documentedTypeParameters, ref _includedFileCache, writer, _diagnostics, _cancellationToken);
|
|
}
|
|
else if (_writer != null && !flag)
|
|
{
|
|
Write(withUnprocessedIncludes);
|
|
}
|
|
if (!(GetLocationInTreeReportingDocumentationCommentDiagnostics(symbol) != (Location)null))
|
|
{
|
|
return;
|
|
}
|
|
cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (documentedParameters != null)
|
|
{
|
|
ImmutableArray<ParameterSymbol>.Enumerator enumerator2 = GetParameters(symbol).GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
ParameterSymbol current = enumerator2.Current;
|
|
if (!documentedParameters.Contains(current))
|
|
{
|
|
Location firstLocation = current.GetFirstLocation();
|
|
_diagnostics.Add(ErrorCode.WRN_MissingParamTag, firstLocation, current.Name, symbol);
|
|
}
|
|
}
|
|
}
|
|
if (documentedTypeParameters == null)
|
|
{
|
|
return;
|
|
}
|
|
ImmutableArray<TypeParameterSymbol>.Enumerator enumerator3 = GetTypeParameters(symbol).GetEnumerator();
|
|
while (enumerator3.MoveNext())
|
|
{
|
|
TypeParameterSymbol current2 = enumerator3.Current;
|
|
if (!documentedTypeParameters.Contains(current2))
|
|
{
|
|
Location firstLocation2 = current2.GetFirstLocation();
|
|
_diagnostics.Add(ErrorCode.WRN_MissingTypeParamTag, firstLocation2, current2, symbol);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool ShouldSkip(Symbol symbol)
|
|
{
|
|
if (!symbol.IsImplicitlyDeclared && !symbol.IsAccessor())
|
|
{
|
|
return symbol is SynthesizedSimpleProgramEntryPointSymbol;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private bool TryProcessRecordPropertyDocumentation(SynthesizedRecordPropertySymbol recordPropertySymbol, ImmutableArray<DocumentationCommentTriviaSyntax> docCommentNodes, [NotNullWhen(true)] out string? withUnprocessedIncludes, out ImmutableArray<CSharpSyntaxNode> includeElementNodes)
|
|
{
|
|
CancellationToken cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ArrayBuilder<XmlElementSyntax> val = getMatchingParamTags(recordPropertySymbol.Name, docCommentNodes);
|
|
if (val == null)
|
|
{
|
|
withUnprocessedIncludes = null;
|
|
includeElementNodes = default(ImmutableArray<CSharpSyntaxNode>);
|
|
return false;
|
|
}
|
|
BeginTemporaryString();
|
|
WriteLine("<member name=\"{0}\">", recordPropertySymbol.GetDocumentationCommentId());
|
|
Indent();
|
|
PooledStringBuilder instance = PooledStringBuilder.GetInstance();
|
|
ArrayBuilder<CSharpSyntaxNode> val2 = (_processIncludes ? ArrayBuilder<CSharpSyntaxNode>.GetInstance() : null);
|
|
DocumentationCommentWalker.GetSubstitutedText(_compilation, recordPropertySymbol, val, val2, instance.Builder);
|
|
string substitutedText = instance.ToStringAndFree();
|
|
string indentedAndWrappedString = FormatComment(substitutedText);
|
|
Write(indentedAndWrappedString);
|
|
Unindent();
|
|
WriteLine("</member>");
|
|
withUnprocessedIncludes = GetAndEndTemporaryString();
|
|
includeElementNodes = val2?.ToImmutableAndFree() ?? default(ImmutableArray<CSharpSyntaxNode>);
|
|
val.Free();
|
|
return true;
|
|
static ArrayBuilder<XmlElementSyntax>? getMatchingParamTags(string propertyName, ImmutableArray<DocumentationCommentTriviaSyntax> immutableArray)
|
|
{
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
|
|
ArrayBuilder<XmlElementSyntax> val3 = null;
|
|
ImmutableArray<DocumentationCommentTriviaSyntax>.Enumerator enumerator = immutableArray.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
Enumerator<XmlNodeSyntax> enumerator2 = enumerator.Current.Content.GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
if (enumerator2.Current is XmlElementSyntax xmlElementSyntax)
|
|
{
|
|
Enumerator<XmlAttributeSyntax> enumerator3 = xmlElementSyntax.StartTag.Attributes.GetEnumerator();
|
|
while (enumerator3.MoveNext())
|
|
{
|
|
if (enumerator3.Current is XmlNameAttributeSyntax xmlNameAttributeSyntax && xmlNameAttributeSyntax.GetElementKind() == XmlNameAttributeElementKind.Parameter)
|
|
{
|
|
SyntaxToken identifier = xmlNameAttributeSyntax.Identifier.Identifier;
|
|
if (string.Equals(((SyntaxToken)(ref identifier)).ValueText, propertyName, StringComparison.Ordinal))
|
|
{
|
|
if (val3 == null)
|
|
{
|
|
val3 = ArrayBuilder<XmlElementSyntax>.GetInstance();
|
|
}
|
|
val3.Add(xmlElementSyntax);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return val3;
|
|
}
|
|
}
|
|
|
|
private bool TryProcessDocumentationCommentTriviaNodes(Symbol symbol, bool shouldSkipPartialDefinitionComments, ImmutableArray<DocumentationCommentTriviaSyntax> docCommentNodes, out string withUnprocessedIncludes, out bool haveParseError, out HashSet<TypeParameterSymbol> documentedTypeParameters, out HashSet<ParameterSymbol> documentedParameters, out ImmutableArray<CSharpSyntaxNode> includeElementNodes)
|
|
{
|
|
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00f3: Expected O, but got Unknown
|
|
bool flag = false;
|
|
ArrayBuilder<CSharpSyntaxNode> val = null;
|
|
documentedParameters = null;
|
|
documentedTypeParameters = null;
|
|
haveParseError = false;
|
|
if (symbol is SynthesizedRecordPropertySymbol recordPropertySymbol)
|
|
{
|
|
return TryProcessRecordPropertyDocumentation(recordPropertySymbol, docCommentNodes, out withUnprocessedIncludes, out includeElementNodes);
|
|
}
|
|
ImmutableArray<DocumentationCommentTriviaSyntax>.Enumerator enumerator = docCommentNodes.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
DocumentationCommentTriviaSyntax current = enumerator.Current;
|
|
CancellationToken cancellationToken = _cancellationToken;
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
bool flag2 = current.SyntaxTree.ReportDocumentationCommentDiagnostics();
|
|
if (!flag)
|
|
{
|
|
BeginTemporaryString();
|
|
if (_processIncludes)
|
|
{
|
|
val = ArrayBuilder<CSharpSyntaxNode>.GetInstance();
|
|
}
|
|
if (!shouldSkipPartialDefinitionComments || _processIncludes)
|
|
{
|
|
WriteLine("<member name=\"{0}\">", symbol.GetDocumentationCommentId());
|
|
Indent();
|
|
}
|
|
flag = true;
|
|
}
|
|
string substitutedText = DocumentationCommentWalker.GetSubstitutedText(_compilation, _diagnostics, symbol, current, val, ref documentedParameters, ref documentedTypeParameters);
|
|
string text = FormatComment(substitutedText);
|
|
XmlException ex = XmlDocumentationCommentTextReader.ParseAndGetException(text);
|
|
if (ex != null)
|
|
{
|
|
haveParseError = true;
|
|
if (flag2)
|
|
{
|
|
Location location = (Location)new SourceLocation(current.SyntaxTree, new TextSpan(((SyntaxNode)current).SpanStart, 0));
|
|
_diagnostics.Add(ErrorCode.WRN_XMLParseError, location, GetDescription(ex));
|
|
}
|
|
}
|
|
if (!shouldSkipPartialDefinitionComments || _processIncludes)
|
|
{
|
|
Write(text);
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
withUnprocessedIncludes = null;
|
|
includeElementNodes = default(ImmutableArray<CSharpSyntaxNode>);
|
|
return false;
|
|
}
|
|
if (!shouldSkipPartialDefinitionComments || _processIncludes)
|
|
{
|
|
Unindent();
|
|
WriteLine("</member>");
|
|
}
|
|
withUnprocessedIncludes = GetAndEndTemporaryString();
|
|
includeElementNodes = (_processIncludes ? val.ToImmutableAndFree() : default(ImmutableArray<CSharpSyntaxNode>));
|
|
return true;
|
|
}
|
|
|
|
private static Location GetLocationInTreeReportingDocumentationCommentDiagnostics(Symbol symbol)
|
|
{
|
|
ImmutableArray<Location>.Enumerator enumerator = symbol.Locations.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
Location current = enumerator.Current;
|
|
if (current.SourceTree.ReportDocumentationCommentDiagnostics())
|
|
{
|
|
return current;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static ImmutableArray<ParameterSymbol> GetParameters(Symbol symbol)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000a: Invalid comparison between Unknown and I4
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001a: Invalid comparison between Unknown and I4
|
|
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000e: Invalid comparison between Unknown and I4
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001f: Invalid comparison between Unknown and I4
|
|
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0013: Invalid comparison between Unknown and I4
|
|
SymbolKind kind = symbol.Kind;
|
|
if ((int)kind <= 9)
|
|
{
|
|
if ((int)kind == 5 || (int)kind == 9)
|
|
{
|
|
goto IL_0039;
|
|
}
|
|
}
|
|
else if ((int)kind != 11)
|
|
{
|
|
if ((int)kind == 15)
|
|
{
|
|
goto IL_0039;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MethodSymbol delegateInvokeMethod = ((NamedTypeSymbol)symbol).DelegateInvokeMethod;
|
|
if ((object)delegateInvokeMethod != null)
|
|
{
|
|
return delegateInvokeMethod.Parameters;
|
|
}
|
|
}
|
|
return ImmutableArray<ParameterSymbol>.Empty;
|
|
IL_0039:
|
|
return symbol.GetParameters();
|
|
}
|
|
|
|
private static ImmutableArray<TypeParameterSymbol> GetTypeParameters(Symbol symbol)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0009: Invalid comparison between Unknown and I4
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000e: Invalid comparison between Unknown and I4
|
|
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0013: Invalid comparison between Unknown and I4
|
|
SymbolKind kind = symbol.Kind;
|
|
if ((int)kind == 4 || (int)kind == 9 || (int)kind == 11)
|
|
{
|
|
return symbol.GetMemberTypeParameters();
|
|
}
|
|
return ImmutableArray<TypeParameterSymbol>.Empty;
|
|
}
|
|
|
|
private static bool RequiresDocumentationComment(Symbol symbol)
|
|
{
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0013: Invalid comparison between Unknown and I4
|
|
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0019: Invalid comparison between Unknown and I4
|
|
if (ShouldSkip(symbol))
|
|
{
|
|
return false;
|
|
}
|
|
while ((object)symbol != null)
|
|
{
|
|
Accessibility declaredAccessibility = symbol.DeclaredAccessibility;
|
|
if ((int)declaredAccessibility == 3 || declaredAccessibility - 5 <= 1)
|
|
{
|
|
symbol = symbol.ContainingType;
|
|
continue;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private bool TryGetDocumentationCommentNodes(Symbol symbol, out DocumentationMode maxDocumentationMode, out ImmutableArray<DocumentationCommentTriviaSyntax> nodes)
|
|
{
|
|
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0053: Invalid comparison between Unknown and I4
|
|
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
|
|
maxDocumentationMode = (DocumentationMode)0;
|
|
nodes = default(ImmutableArray<DocumentationCommentTriviaSyntax>);
|
|
ArrayBuilder<DocumentationCommentTriviaSyntax> val = null;
|
|
DiagnosticBag val2 = ((BindingDiagnosticBag)_diagnostics).DiagnosticBag ?? DiagnosticBag.GetInstance();
|
|
ImmutableArray<SyntaxReference>.Enumerator enumerator = symbol.DeclaringSyntaxReferences.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
SyntaxReference current = enumerator.Current;
|
|
DocumentationMode documentationMode = current.SyntaxTree.Options.DocumentationMode;
|
|
maxDocumentationMode = (DocumentationMode)(((int)documentationMode <= (int)maxDocumentationMode) ? ((int)maxDocumentationMode) : ((int)documentationMode));
|
|
ImmutableArray<DocumentationCommentTriviaSyntax>.Enumerator enumerator2 = SourceDocumentationCommentUtils.GetDocumentationCommentTriviaFromSyntaxNode((CSharpSyntaxNode)(object)current.GetSyntax(default(CancellationToken)), val2).GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
DocumentationCommentTriviaSyntax current2 = enumerator2.Current;
|
|
if (ContainsXmlParseDiagnostic(current2))
|
|
{
|
|
val?.Free();
|
|
return false;
|
|
}
|
|
if (val == null)
|
|
{
|
|
val = ArrayBuilder<DocumentationCommentTriviaSyntax>.GetInstance();
|
|
}
|
|
val.Add(current2);
|
|
}
|
|
}
|
|
if (val2 != ((BindingDiagnosticBag)_diagnostics).DiagnosticBag)
|
|
{
|
|
val2.Free();
|
|
}
|
|
if (val == null)
|
|
{
|
|
nodes = ImmutableArray<DocumentationCommentTriviaSyntax>.Empty;
|
|
}
|
|
else
|
|
{
|
|
val.Sort((IComparer<DocumentationCommentTriviaSyntax>)Comparer);
|
|
nodes = val.ToImmutableAndFree();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static bool ContainsXmlParseDiagnostic(DocumentationCommentTriviaSyntax node)
|
|
{
|
|
if (!((SyntaxNode)node).ContainsDiagnostics)
|
|
{
|
|
return false;
|
|
}
|
|
foreach (Diagnostic diagnostic in node.GetDiagnostics())
|
|
{
|
|
if (diagnostic.Code == 1570)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private string FormatComment(string substitutedText)
|
|
{
|
|
BeginTemporaryString();
|
|
if (TrimmedStringStartsWith(substitutedText, "///"))
|
|
{
|
|
WriteFormattedSingleLineComment(substitutedText);
|
|
}
|
|
else
|
|
{
|
|
string[] array = substitutedText.Split(s_newLineSequences, StringSplitOptions.None);
|
|
int num = array.Length;
|
|
if (string.IsNullOrEmpty(array[num - 1]))
|
|
{
|
|
num--;
|
|
}
|
|
WriteFormattedMultiLineComment(array, num);
|
|
}
|
|
return GetAndEndTemporaryString();
|
|
}
|
|
|
|
private static int GetIndexOfFirstNonWhitespaceChar(string str)
|
|
{
|
|
return GetIndexOfFirstNonWhitespaceChar(str, 0, str.Length);
|
|
}
|
|
|
|
private static int GetIndexOfFirstNonWhitespaceChar(string str, int start, int end)
|
|
{
|
|
while (start < end && SyntaxFacts.IsWhitespace(str[start]))
|
|
{
|
|
start++;
|
|
}
|
|
return start;
|
|
}
|
|
|
|
private static bool TrimmedStringStartsWith(string str, string prefix)
|
|
{
|
|
int indexOfFirstNonWhitespaceChar = GetIndexOfFirstNonWhitespaceChar(str);
|
|
if (str.Length - indexOfFirstNonWhitespaceChar < prefix.Length)
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < prefix.Length; i++)
|
|
{
|
|
if (prefix[i] != str[i + indexOfFirstNonWhitespaceChar])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static int IndexOfNewLine(string str, int start, out int newLineLength)
|
|
{
|
|
while (start < str.Length)
|
|
{
|
|
switch (str[start])
|
|
{
|
|
case '\r':
|
|
if (start + 1 < str.Length && str[start + 1] == '\n')
|
|
{
|
|
newLineLength = 2;
|
|
}
|
|
else
|
|
{
|
|
newLineLength = 1;
|
|
}
|
|
return start;
|
|
case '\n':
|
|
newLineLength = 1;
|
|
return start;
|
|
}
|
|
start++;
|
|
}
|
|
newLineLength = 0;
|
|
return start;
|
|
}
|
|
|
|
private void WriteFormattedSingleLineComment(string text)
|
|
{
|
|
bool flag = true;
|
|
int num = 0;
|
|
while (num < text.Length)
|
|
{
|
|
int newLineLength;
|
|
int num2 = IndexOfNewLine(text, num, out newLineLength);
|
|
int indexOfFirstNonWhitespaceChar = GetIndexOfFirstNonWhitespaceChar(text, num, num2);
|
|
if (num2 - indexOfFirstNonWhitespaceChar < 4 || !SyntaxFacts.IsWhitespace(text[indexOfFirstNonWhitespaceChar + 3]))
|
|
{
|
|
flag = false;
|
|
break;
|
|
}
|
|
num = num2 + newLineLength;
|
|
}
|
|
int num3 = (flag ? 4 : 3);
|
|
int num4 = 0;
|
|
while (num4 < text.Length)
|
|
{
|
|
int newLineLength2;
|
|
int num5 = IndexOfNewLine(text, num4, out newLineLength2);
|
|
int num6 = GetIndexOfFirstNonWhitespaceChar(text, num4, num5) + num3;
|
|
WriteSubStringLine(text, num6, num5 - num6);
|
|
num4 = num5 + newLineLength2;
|
|
}
|
|
}
|
|
|
|
private void WriteFormattedMultiLineComment(string[] lines, int numLines)
|
|
{
|
|
bool flag = lines[0].Trim() == "/**";
|
|
bool flag2 = lines[numLines - 1].Trim() == "*/";
|
|
if (flag2)
|
|
{
|
|
numLines--;
|
|
}
|
|
int startIndex = 0;
|
|
if (numLines > 1)
|
|
{
|
|
string text = FindMultiLineCommentPattern(lines[1]);
|
|
if (text != null)
|
|
{
|
|
bool flag3 = true;
|
|
for (int i = 2; i < numLines; i++)
|
|
{
|
|
string text2 = LongestCommonPrefix(text, lines[i]);
|
|
if (string.IsNullOrWhiteSpace(text2))
|
|
{
|
|
flag3 = false;
|
|
break;
|
|
}
|
|
text = text2;
|
|
}
|
|
if (flag3)
|
|
{
|
|
startIndex = text.Length;
|
|
}
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
string text3 = lines[0].TrimStart(null);
|
|
if (!flag2 && numLines == 1)
|
|
{
|
|
text3 = TrimEndOfMultiLineComment(text3);
|
|
}
|
|
WriteLine(text3.Substring(text3.StartsWith("/** ") ? 4 : (text3.StartsWith("/**") ? 3 : (text3.StartsWith("* ") ? 2 : (text3.StartsWith("*") ? 1 : 0)))));
|
|
}
|
|
for (int j = 1; j < numLines; j++)
|
|
{
|
|
string text4 = lines[j].Substring(startIndex);
|
|
if (!flag2 && j == numLines - 1)
|
|
{
|
|
text4 = TrimEndOfMultiLineComment(text4);
|
|
}
|
|
WriteLine(text4);
|
|
}
|
|
}
|
|
|
|
private static string TrimEndOfMultiLineComment(string trimmed)
|
|
{
|
|
int num = trimmed.IndexOf("*/", StringComparison.Ordinal);
|
|
if (num >= 0)
|
|
{
|
|
trimmed = trimmed.Substring(0, num);
|
|
}
|
|
return trimmed;
|
|
}
|
|
|
|
private static string FindMultiLineCommentPattern(string line)
|
|
{
|
|
int num = 0;
|
|
bool flag = false;
|
|
foreach (char c in line)
|
|
{
|
|
if (SyntaxFacts.IsWhitespace(c))
|
|
{
|
|
num++;
|
|
continue;
|
|
}
|
|
if (flag || c != '*')
|
|
{
|
|
break;
|
|
}
|
|
num++;
|
|
flag = true;
|
|
}
|
|
if (!flag)
|
|
{
|
|
return null;
|
|
}
|
|
return line.Substring(0, num);
|
|
}
|
|
|
|
private static string LongestCommonPrefix(string str1, string str2)
|
|
{
|
|
int i = 0;
|
|
for (int num = Math.Min(str1.Length, str2.Length); i < num && str1[i] == str2[i]; i++)
|
|
{
|
|
}
|
|
return str1.Substring(0, i);
|
|
}
|
|
|
|
private static string GetDocumentationCommentId(CrefSyntax crefSyntax, Binder binder, BindingDiagnosticBag diagnostics)
|
|
{
|
|
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
|
|
if (((SyntaxNode)crefSyntax).ContainsDiagnostics)
|
|
{
|
|
return ToBadCrefString(crefSyntax);
|
|
}
|
|
Symbol ambiguityWinner;
|
|
ImmutableArray<Symbol> immutableArray = binder.BindCref(crefSyntax, out ambiguityWinner, diagnostics);
|
|
Symbol symbol;
|
|
switch (immutableArray.Length)
|
|
{
|
|
case 0:
|
|
return ToBadCrefString(crefSyntax);
|
|
case 1:
|
|
symbol = immutableArray[0];
|
|
break;
|
|
default:
|
|
symbol = ambiguityWinner;
|
|
break;
|
|
}
|
|
if ((int)symbol.Kind == 0)
|
|
{
|
|
symbol = ((AliasSymbol)symbol).GetAliasTarget(null);
|
|
}
|
|
if (symbol is NamespaceSymbol ns)
|
|
{
|
|
diagnostics.AddAssembliesUsedByNamespaceReference(ns);
|
|
}
|
|
else
|
|
{
|
|
diagnostics.AddDependencies((symbol as TypeSymbol) ?? symbol.ContainingType);
|
|
}
|
|
return symbol.OriginalDefinition.GetDocumentationCommentId();
|
|
}
|
|
|
|
private static string ToBadCrefString(CrefSyntax cref)
|
|
{
|
|
using StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
|
|
((SyntaxNode)cref).WriteTo((TextWriter)stringWriter);
|
|
return "!:" + stringWriter.ToString().Replace("{", "<").Replace("}", ">");
|
|
}
|
|
|
|
private static void BindName(XmlNameAttributeSyntax syntax, Binder binder, Symbol memberSymbol, ref HashSet<ParameterSymbol> documentedParameters, ref HashSet<TypeParameterSymbol> documentedTypeParameters, BindingDiagnosticBag diagnostics)
|
|
{
|
|
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
|
|
XmlNameAttributeElementKind elementKind = syntax.GetElementKind();
|
|
switch (elementKind)
|
|
{
|
|
case XmlNameAttributeElementKind.Parameter:
|
|
if (documentedParameters == null)
|
|
{
|
|
documentedParameters = new HashSet<ParameterSymbol>();
|
|
}
|
|
break;
|
|
case XmlNameAttributeElementKind.TypeParameter:
|
|
if (documentedTypeParameters == null)
|
|
{
|
|
documentedTypeParameters = new HashSet<TypeParameterSymbol>();
|
|
}
|
|
break;
|
|
}
|
|
IdentifierNameSyntax identifier = syntax.Identifier;
|
|
if (((SyntaxNode)identifier).ContainsDiagnostics)
|
|
{
|
|
return;
|
|
}
|
|
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = binder.GetNewCompoundUseSiteInfo(diagnostics);
|
|
ImmutableArray<Symbol> immutableArray = binder.BindXmlNameAttribute(syntax, ref useSiteInfo);
|
|
((BindingDiagnosticBag<AssemblySymbol>)(object)diagnostics).Add((SyntaxNode)(object)syntax, useSiteInfo);
|
|
if (immutableArray.IsEmpty)
|
|
{
|
|
switch (elementKind)
|
|
{
|
|
case XmlNameAttributeElementKind.Parameter:
|
|
diagnostics.Add(ErrorCode.WRN_UnmatchedParamTag, ((SyntaxNode)identifier).Location, identifier);
|
|
break;
|
|
case XmlNameAttributeElementKind.ParameterReference:
|
|
diagnostics.Add(ErrorCode.WRN_UnmatchedParamRefTag, ((SyntaxNode)identifier).Location, identifier, memberSymbol);
|
|
break;
|
|
case XmlNameAttributeElementKind.TypeParameter:
|
|
diagnostics.Add(ErrorCode.WRN_UnmatchedTypeParamTag, ((SyntaxNode)identifier).Location, identifier);
|
|
break;
|
|
case XmlNameAttributeElementKind.TypeParameterReference:
|
|
diagnostics.Add(ErrorCode.WRN_UnmatchedTypeParamRefTag, ((SyntaxNode)identifier).Location, identifier, memberSymbol);
|
|
break;
|
|
default:
|
|
throw ExceptionUtilities.UnexpectedValue((object)elementKind);
|
|
}
|
|
return;
|
|
}
|
|
ImmutableArray<Symbol>.Enumerator enumerator = immutableArray.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
Symbol current = enumerator.Current;
|
|
switch (elementKind)
|
|
{
|
|
case XmlNameAttributeElementKind.Parameter:
|
|
{
|
|
ParameterSymbol parameterSymbol = (ParameterSymbol)current;
|
|
if (!parameterSymbol.ContainingSymbol.IsAccessor() && !documentedParameters.Add(parameterSymbol))
|
|
{
|
|
diagnostics.Add(ErrorCode.WRN_DuplicateParamTag, ((SyntaxNode)syntax).Location, identifier);
|
|
}
|
|
break;
|
|
}
|
|
case XmlNameAttributeElementKind.TypeParameter:
|
|
if (!documentedTypeParameters.Add((TypeParameterSymbol)current))
|
|
{
|
|
diagnostics.Add(ErrorCode.WRN_DuplicateTypeParamTag, ((SyntaxNode)syntax).Location, identifier);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void BeginTemporaryString()
|
|
{
|
|
if (_temporaryStringBuilders == null)
|
|
{
|
|
_temporaryStringBuilders = new Stack<TemporaryStringBuilder>();
|
|
}
|
|
_temporaryStringBuilders.Push(new TemporaryStringBuilder(_indentDepth));
|
|
}
|
|
|
|
private string GetAndEndTemporaryString()
|
|
{
|
|
TemporaryStringBuilder temporaryStringBuilder = _temporaryStringBuilders.Pop();
|
|
_indentDepth = temporaryStringBuilder.InitialIndentDepth;
|
|
return temporaryStringBuilder.Pooled.ToStringAndFree();
|
|
}
|
|
|
|
private void Indent()
|
|
{
|
|
_indentDepth++;
|
|
}
|
|
|
|
private void Unindent()
|
|
{
|
|
_indentDepth--;
|
|
}
|
|
|
|
private void Write(string indentedAndWrappedString)
|
|
{
|
|
if (_temporaryStringBuilders != null && _temporaryStringBuilders.Count > 0)
|
|
{
|
|
_temporaryStringBuilders.Peek().Pooled.Builder.Append(indentedAndWrappedString);
|
|
}
|
|
else if (_writer != null)
|
|
{
|
|
_writer.Write(indentedAndWrappedString);
|
|
}
|
|
}
|
|
|
|
private void WriteLine(string message)
|
|
{
|
|
Stack<TemporaryStringBuilder> temporaryStringBuilders = _temporaryStringBuilders;
|
|
if (temporaryStringBuilders != null && temporaryStringBuilders.Count > 0)
|
|
{
|
|
StringBuilder builder = _temporaryStringBuilders.Peek().Pooled.Builder;
|
|
builder.Append(MakeIndent(_indentDepth));
|
|
builder.AppendLine(message);
|
|
}
|
|
else if (_writer != null)
|
|
{
|
|
_writer.Write(MakeIndent(_indentDepth));
|
|
_writer.WriteLine(message);
|
|
}
|
|
}
|
|
|
|
private void WriteSubStringLine(string message, int start, int length)
|
|
{
|
|
Stack<TemporaryStringBuilder> temporaryStringBuilders = _temporaryStringBuilders;
|
|
if (temporaryStringBuilders != null && temporaryStringBuilders.Count > 0)
|
|
{
|
|
StringBuilder builder = _temporaryStringBuilders.Peek().Pooled.Builder;
|
|
builder.Append(MakeIndent(_indentDepth));
|
|
builder.Append(message, start, length);
|
|
builder.AppendLine();
|
|
}
|
|
else if (_writer != null)
|
|
{
|
|
_writer.Write(MakeIndent(_indentDepth));
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
_writer.Write(message[start + i]);
|
|
}
|
|
_writer.WriteLine();
|
|
}
|
|
}
|
|
|
|
private void WriteLine(string format, params object[] args)
|
|
{
|
|
WriteLine(string.Format(format, args));
|
|
}
|
|
|
|
private static string MakeIndent(int depth)
|
|
{
|
|
return depth switch
|
|
{
|
|
0 => "",
|
|
1 => " ",
|
|
2 => " ",
|
|
3 => " ",
|
|
_ => new string(' ', depth * 4),
|
|
};
|
|
}
|
|
|
|
private static string GetDescription(XmlException e)
|
|
{
|
|
string message = e.Message;
|
|
try
|
|
{
|
|
string text = string.Format(new ResourceManager("System.Xml", typeof(XmlException).GetTypeInfo().Assembly).GetString("Xml_MessageWithErrorPosition"), "", e.LineNumber, e.LinePosition);
|
|
int num = message.IndexOf(text, StringComparison.Ordinal);
|
|
return (num < 0) ? message : message.Remove(num, text.Length);
|
|
}
|
|
catch
|
|
{
|
|
return message;
|
|
}
|
|
}
|
|
}
|