/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxTriviaExtensions.cs
217 строк
7 KB
Cyrus Najmabadi
revert
10 ноя 2025, 21:00
10 ноя 2025, 21:00
c46c8fe
Код
Авторство
О чём код?
// 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.Linq; using System.Text; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Extensions; internal static class SyntaxTriviaExtensions { public static void Deconstruct(this SyntaxTrivia trivia, out SyntaxKind kind) => kind = trivia.Kind(); public static bool IsSingleOrMultiLineComment(this SyntaxTrivia trivia) => trivia.Kind() is SyntaxKind.MultiLineCommentTrivia or SyntaxKind.SingleLineCommentTrivia; public static bool IsRegularComment(this SyntaxTrivia trivia) => trivia.IsSingleOrMultiLineComment() || trivia.IsShebangDirective(); public static bool IsWhitespaceOrSingleOrMultiLineComment(this SyntaxTrivia trivia) => trivia.IsWhitespace() || trivia.IsSingleOrMultiLineComment(); public static bool IsRegularOrDocComment(this SyntaxTrivia trivia) => trivia.IsRegularComment() || trivia.IsDocComment(); public static bool IsSingleLineComment(this SyntaxTrivia trivia) => trivia.Kind() == SyntaxKind.SingleLineCommentTrivia; public static bool IsMultiLineComment(this SyntaxTrivia trivia) => trivia.Kind() == SyntaxKind.MultiLineCommentTrivia; public static bool IsShebangDirective(this SyntaxTrivia trivia) => trivia.Kind() == SyntaxKind.ShebangDirectiveTrivia; public static bool IsCompleteMultiLineComment(this SyntaxTrivia trivia) { if (trivia.Kind() != SyntaxKind.MultiLineCommentTrivia) return false; var text = trivia.ToFullString(); return text is [.., _, _, '*', '/']; } public static bool IsDocComment(this SyntaxTrivia trivia) => trivia.IsSingleLineDocComment() || trivia.IsMultiLineDocComment(); public static bool IsSingleLineDocComment(this SyntaxTrivia trivia) => trivia.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia; public static bool IsMultiLineDocComment(this SyntaxTrivia trivia) => trivia.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia; public static string GetCommentText(this SyntaxTrivia trivia) { var commentText = trivia.ToString(); if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia) { if (commentText.StartsWith("//", StringComparison.Ordinal)) { commentText = commentText[2..]; } return commentText.TrimStart(null); } else if (trivia.Kind() == SyntaxKind.MultiLineCommentTrivia) { var textBuilder = new StringBuilder(); if (commentText.EndsWith("*/", StringComparison.Ordinal)) { commentText = commentText[..^2]; } if (commentText.StartsWith("/*", StringComparison.Ordinal)) { commentText = commentText[2..]; } commentText = commentText.Trim(); var newLine = Environment.NewLine; var lines = commentText.Split([newLine], StringSplitOptions.None); foreach (var line in lines) { var trimmedLine = line.Trim(); // Note: we trim leading '*' characters in multi-line comments. // If the '*' was intentional, sorry, it's gone. if (trimmedLine.StartsWith("*", StringComparison.Ordinal)) { trimmedLine = trimmedLine.TrimStart('*'); trimmedLine = trimmedLine.TrimStart(null); } textBuilder.AppendLine(trimmedLine); } // remove last line break textBuilder.Remove(textBuilder.Length - newLine.Length, newLine.Length); return textBuilder.ToString(); } else { throw new InvalidOperationException(); } } public static string AsString(this IEnumerable<SyntaxTrivia> trivia) { Contract.ThrowIfNull(trivia); if (trivia.Any()) { var sb = new StringBuilder(); trivia.Select(t => t.ToFullString()).Do(s => sb.Append(s)); return sb.ToString(); } else { return string.Empty; } } public static int GetFullWidth(this IEnumerable<SyntaxTrivia> trivia) { Contract.ThrowIfNull(trivia); return trivia.Sum(t => t.FullWidth()); } public static SyntaxTriviaList AsTrivia(this string s) => SyntaxFactory.ParseLeadingTrivia(s ?? string.Empty); public static bool IsWhitespaceOrEndOfLine(this SyntaxTrivia trivia) => IsWhitespace(trivia) || IsEndOfLine(trivia); public static bool IsEndOfLine(this SyntaxTrivia trivia) => trivia.Kind() == SyntaxKind.EndOfLineTrivia; public static bool IsWhitespace(this SyntaxTrivia trivia) => trivia.Kind() == SyntaxKind.WhitespaceTrivia; public static SyntaxTrivia GetPreviousTrivia( this SyntaxTrivia trivia, SyntaxTree syntaxTree, CancellationToken cancellationToken, bool findInsideTrivia = false) { var span = trivia.FullSpan; if (span.Start == 0) { return default; } return syntaxTree.GetRoot(cancellationToken).FindTrivia(span.Start - 1, findInsideTrivia); } public static IEnumerable<SyntaxTrivia> FilterComments(this IEnumerable<SyntaxTrivia> trivia, bool addElasticMarker) { var previousIsSingleLineComment = false; foreach (var t in trivia) { if (previousIsSingleLineComment && t.IsEndOfLine()) { yield return t; } if (t.IsSingleOrMultiLineComment()) { yield return t; } previousIsSingleLineComment = t.IsSingleLineComment(); } if (addElasticMarker) { yield return SyntaxFactory.ElasticMarker; } } #if false public static int Width(this SyntaxTrivia trivia) { return trivia.Span.Length; } public static int FullWidth(this SyntaxTrivia trivia) { return trivia.FullSpan.Length; } #endif public static bool IsPragmaDirective(this SyntaxTrivia trivia, out bool isDisable, out bool isActive, out SeparatedSyntaxList<SyntaxNode> errorCodes) { if (trivia.IsKind(SyntaxKind.PragmaWarningDirectiveTrivia)) { var pragmaWarning = (PragmaWarningDirectiveTriviaSyntax)trivia.GetStructure(); isDisable = pragmaWarning.DisableOrRestoreKeyword.IsKind(SyntaxKind.DisableKeyword); isActive = pragmaWarning.IsActive; errorCodes = pragmaWarning.ErrorCodes; return true; } isDisable = false; isActive = false; errorCodes = default; return false; } }