/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Portable/Syntax/InternalSyntax/SyntaxFactory.cs
349 строк
14 KB
Todd Grunke
Reduce allocations from creating MissingTokenWithTrivia objects (#75404)
08 окт 2024, 20:00
Не верифицирован
08 окт 2024, 20:00
a656d1a
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Collections.Generic; using System.Diagnostics; namespace Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax { using Microsoft.CodeAnalysis.Syntax.InternalSyntax; internal static partial class SyntaxFactory { private const string CrLf = "\r\n"; internal static readonly SyntaxTrivia CarriageReturnLineFeed = EndOfLine(CrLf); internal static readonly SyntaxTrivia LineFeed = EndOfLine("\n"); internal static readonly SyntaxTrivia CarriageReturn = EndOfLine("\r"); internal static readonly SyntaxTrivia Space = Whitespace(" "); internal static readonly SyntaxTrivia Tab = Whitespace("\t"); internal static readonly SyntaxTrivia ElasticCarriageReturnLineFeed = EndOfLine(CrLf, elastic: true); internal static readonly SyntaxTrivia ElasticLineFeed = EndOfLine("\n", elastic: true); internal static readonly SyntaxTrivia ElasticCarriageReturn = EndOfLine("\r", elastic: true); internal static readonly SyntaxTrivia ElasticSpace = Whitespace(" ", elastic: true); internal static readonly SyntaxTrivia ElasticTab = Whitespace("\t", elastic: true); internal static readonly SyntaxTrivia ElasticZeroSpace = Whitespace(string.Empty, elastic: true); private static SyntaxToken s_xmlCarriageReturnLineFeed; private static SyntaxToken XmlCarriageReturnLineFeed { get { return s_xmlCarriageReturnLineFeed ?? (s_xmlCarriageReturnLineFeed = XmlTextNewLine(CrLf)); } } // NOTE: it would be nice to have constants for OmittedArraySizeException and OmittedTypeArgument, // but it's non-trivial to introduce such constants, since they would make this class take a dependency // on the static fields of SyntaxToken (specifically, TokensWithNoTrivia via SyntaxToken.Create). That // could cause unpredictable behavior, since SyntaxToken's static constructor already depends on the // static fields of this class (specifically, ElasticZeroSpace). internal static SyntaxTrivia EndOfLine(string text, bool elastic = false) { SyntaxTrivia trivia = null; // use predefined trivia switch (text) { case "\r": trivia = elastic ? SyntaxFactory.ElasticCarriageReturn : SyntaxFactory.CarriageReturn; break; case "\n": trivia = elastic ? SyntaxFactory.ElasticLineFeed : SyntaxFactory.LineFeed; break; case "\r\n": trivia = elastic ? SyntaxFactory.ElasticCarriageReturnLineFeed : SyntaxFactory.CarriageReturnLineFeed; break; } // note: predefined trivia might not yet be defined during initialization if (trivia != null) { return trivia; } trivia = SyntaxTrivia.Create(SyntaxKind.EndOfLineTrivia, text); if (!elastic) { return trivia; } return trivia.WithAnnotationsGreen(new[] { SyntaxAnnotation.ElasticAnnotation }); } internal static SyntaxTrivia Whitespace(string text, bool elastic = false) { var trivia = SyntaxTrivia.Create(SyntaxKind.WhitespaceTrivia, text); if (!elastic) { return trivia; } return trivia.WithAnnotationsGreen(new[] { SyntaxAnnotation.ElasticAnnotation }); } internal static SyntaxTrivia Comment(string text) { if (text is ['/' or '@', '*', ..]) { return SyntaxTrivia.Create(SyntaxKind.MultiLineCommentTrivia, text); } else { return SyntaxTrivia.Create(SyntaxKind.SingleLineCommentTrivia, text); } } internal static SyntaxTrivia ConflictMarker(string text) => SyntaxTrivia.Create(SyntaxKind.ConflictMarkerTrivia, text); internal static SyntaxTrivia DisabledText(string text) { return SyntaxTrivia.Create(SyntaxKind.DisabledTextTrivia, text); } internal static SyntaxTrivia PreprocessingMessage(string text) { return SyntaxTrivia.Create(SyntaxKind.PreprocessingMessageTrivia, text); } public static SyntaxToken Token(SyntaxKind kind) { return SyntaxToken.Create(kind); } internal static SyntaxToken Token(GreenNode leading, SyntaxKind kind, GreenNode trailing) { return SyntaxToken.Create(kind, leading, trailing); } /// <summary> /// Creates a token whose <see cref="SyntaxToken.Text"/> and <see cref="SyntaxToken.ValueText"/> are the same. /// </summary> internal static SyntaxToken Token(GreenNode leading, SyntaxKind kind, string text, GreenNode trailing) { return Token(leading, kind, text, text, trailing); } internal static SyntaxToken Token(GreenNode leading, SyntaxKind kind, string text, string valueText, GreenNode trailing) { Debug.Assert(SyntaxFacts.IsAnyToken(kind)); Debug.Assert(kind != SyntaxKind.IdentifierToken); Debug.Assert(kind != SyntaxKind.CharacterLiteralToken); Debug.Assert(kind != SyntaxKind.NumericLiteralToken); string defaultText = SyntaxFacts.GetText(kind); return kind >= SyntaxToken.FirstTokenWithWellKnownText && kind <= SyntaxToken.LastTokenWithWellKnownText && text == defaultText && valueText == defaultText ? Token(leading, kind, trailing) : SyntaxToken.WithValue(kind, leading, text, valueText, trailing); } internal static SyntaxToken MissingToken(SyntaxKind kind) { return SyntaxToken.CreateMissing(kind); } internal static SyntaxToken MissingToken(GreenNode leading, SyntaxKind kind, GreenNode trailing) { return SyntaxToken.CreateMissing(kind, leading, trailing); } internal static SyntaxToken Identifier(string text) { return Identifier(SyntaxKind.IdentifierToken, null, text, text, null); } internal static SyntaxToken Identifier(GreenNode leading, string text, GreenNode trailing) { return Identifier(SyntaxKind.IdentifierToken, leading, text, text, trailing); } internal static SyntaxToken Identifier(SyntaxKind contextualKind, GreenNode leading, string text, string valueText, GreenNode trailing) { return SyntaxToken.Identifier(contextualKind, leading, text, valueText, trailing); } internal static SyntaxToken Literal(GreenNode leading, string text, int value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.NumericLiteralToken, leading, text, value, trailing); } internal static SyntaxToken Literal(GreenNode leading, string text, uint value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.NumericLiteralToken, leading, text, value, trailing); } internal static SyntaxToken Literal(GreenNode leading, string text, long value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.NumericLiteralToken, leading, text, value, trailing); } internal static SyntaxToken Literal(GreenNode leading, string text, ulong value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.NumericLiteralToken, leading, text, value, trailing); } internal static SyntaxToken Literal(GreenNode leading, string text, float value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.NumericLiteralToken, leading, text, value, trailing); } internal static SyntaxToken Literal(GreenNode leading, string text, double value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.NumericLiteralToken, leading, text, value, trailing); } internal static SyntaxToken Literal(GreenNode leading, string text, decimal value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.NumericLiteralToken, leading, text, value, trailing); } internal static SyntaxToken Literal(GreenNode leading, string text, string value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.StringLiteralToken, leading, text, value, trailing); } internal static SyntaxToken Literal(GreenNode leading, string text, SyntaxKind kind, string value, GreenNode trailing) { return SyntaxToken.WithValue(kind, leading, text, value, trailing); } internal static SyntaxToken Literal(GreenNode leading, string text, char value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.CharacterLiteralToken, leading, text, value, trailing); } internal static SyntaxToken BadToken(GreenNode leading, string text, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.BadToken, leading, text, text, trailing); } internal static SyntaxToken XmlTextLiteral(GreenNode leading, string text, string value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.XmlTextLiteralToken, leading, text, value, trailing); } internal static SyntaxToken XmlTextNewLine(GreenNode leading, string text, string value, GreenNode trailing) { if (leading == null && trailing == null && text == CrLf && value == CrLf) { return XmlCarriageReturnLineFeed; } return SyntaxToken.WithValue(SyntaxKind.XmlTextLiteralNewLineToken, leading, text, value, trailing); } internal static SyntaxToken XmlTextNewLine(string text) { return SyntaxToken.WithValue(SyntaxKind.XmlTextLiteralNewLineToken, null, text, text, null); } internal static SyntaxToken XmlEntity(GreenNode leading, string text, string value, GreenNode trailing) { return SyntaxToken.WithValue(SyntaxKind.XmlEntityLiteralToken, leading, text, value, trailing); } internal static SyntaxTrivia DocumentationCommentExteriorTrivia(string text) { return SyntaxTrivia.Create(SyntaxKind.DocumentationCommentExteriorTrivia, text); } public static SyntaxList<TNode> List<TNode>() where TNode : CSharpSyntaxNode { return default(SyntaxList<TNode>); } public static SyntaxList<TNode> List<TNode>(TNode node) where TNode : CSharpSyntaxNode { return new SyntaxList<TNode>(SyntaxList.List(node)); } public static SyntaxList<TNode> List<TNode>(TNode node0, TNode node1) where TNode : CSharpSyntaxNode { return new SyntaxList<TNode>(SyntaxList.List(node0, node1)); } internal static GreenNode ListNode(CSharpSyntaxNode node0, CSharpSyntaxNode node1) { return SyntaxList.List(node0, node1); } public static SyntaxList<TNode> List<TNode>(TNode node0, TNode node1, TNode node2) where TNode : CSharpSyntaxNode { return new SyntaxList<TNode>(SyntaxList.List(node0, node1, node2)); } internal static GreenNode ListNode(CSharpSyntaxNode node0, CSharpSyntaxNode node1, CSharpSyntaxNode node2) { return SyntaxList.List(node0, node1, node2); } public static SyntaxList<TNode> List<TNode>(params TNode[] nodes) where TNode : CSharpSyntaxNode { if (nodes != null) { return new SyntaxList<TNode>(SyntaxList.List(nodes)); } return default(SyntaxList<TNode>); } internal static GreenNode ListNode(params ArrayElement<GreenNode>[] nodes) { return SyntaxList.List(nodes); } public static SeparatedSyntaxList<TNode> SeparatedList<TNode>(TNode node) where TNode : CSharpSyntaxNode { return new SeparatedSyntaxList<TNode>(new SyntaxList<CSharpSyntaxNode>(node)); } public static SeparatedSyntaxList<TNode> SeparatedList<TNode>(SyntaxToken token) where TNode : CSharpSyntaxNode { return new SeparatedSyntaxList<TNode>(new SyntaxList<CSharpSyntaxNode>(token)); } public static SeparatedSyntaxList<TNode> SeparatedList<TNode>(TNode node1, SyntaxToken token, TNode node2) where TNode : CSharpSyntaxNode { return new SeparatedSyntaxList<TNode>(new SyntaxList<CSharpSyntaxNode>(SyntaxList.List(node1, token, node2))); } public static SeparatedSyntaxList<TNode> SeparatedList<TNode>(params CSharpSyntaxNode[] nodes) where TNode : CSharpSyntaxNode { if (nodes != null) { return new SeparatedSyntaxList<TNode>(SyntaxList.List(nodes)); } return default(SeparatedSyntaxList<TNode>); } internal static IEnumerable<SyntaxTrivia> GetWellKnownTrivia() { yield return CarriageReturnLineFeed; yield return LineFeed; yield return CarriageReturn; yield return Space; yield return Tab; yield return ElasticCarriageReturnLineFeed; yield return ElasticLineFeed; yield return ElasticCarriageReturn; yield return ElasticSpace; yield return ElasticTab; yield return ElasticZeroSpace; } internal static IEnumerable<SyntaxToken> GetWellKnownTokens() { return SyntaxToken.GetWellKnownTokens(); } } }