| File: SyntaxExtensions.cs | Web Access |
| Project: src\runtime\src\libraries\System.Runtime.InteropServices\gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj (Microsoft.Interop.SourceGeneration) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Microsoft.Interop { public static class SyntaxExtensions { private static FixedStatementSyntax AddStatementWithoutEmptyStatements(this FixedStatementSyntax fixedStatement, StatementSyntax childStatement) { if (fixedStatement.Statement.IsKind(SyntaxKind.EmptyStatement)) { return fixedStatement.WithStatement(childStatement); } BlockSyntax block; if (fixedStatement.Statement.IsKind(SyntaxKind.Block)) { block = (BlockSyntax)fixedStatement.Statement; if (block.Statements.Count == 0) { return fixedStatement.WithStatement(childStatement); } } else { block = SyntaxFactory.Block(fixedStatement.Statement); } if (childStatement.IsKind(SyntaxKind.Block)) { block = block.WithStatements(block.Statements.AddRange(((BlockSyntax)childStatement).Statements)); } else { block = block.AddStatements(childStatement); } return fixedStatement.WithStatement(block); } public static StatementSyntax NestFixedStatements(this ImmutableArray<FixedStatementSyntax> fixedStatements, StatementSyntax innerStatement) { StatementSyntax nestedStatement = innerStatement; if (!fixedStatements.IsEmpty) { int i = fixedStatements.Length - 1; nestedStatement = fixedStatements[i].AddStatementWithoutEmptyStatements(WrapStatementInBlock(nestedStatement)); i--; for (; i >= 0; i--) { nestedStatement = fixedStatements[i].AddStatementWithoutEmptyStatements(nestedStatement); } } return nestedStatement; static StatementSyntax WrapStatementInBlock(StatementSyntax statement) { if (statement.IsKind(SyntaxKind.Block)) { return statement; } return SyntaxFactory.Block(statement); } } public static SyntaxTokenList StripTriviaFromTokens(this SyntaxTokenList tokenList) { SyntaxToken[] strippedTokens = new SyntaxToken[tokenList.Count]; for (int i = 0; i < tokenList.Count; i++) { strippedTokens[i] = tokenList[i].WithoutTrivia(); } return new SyntaxTokenList(strippedTokens); } public static SyntaxTokenList StripAccessibilityModifiers(this SyntaxTokenList tokenList) { List<SyntaxToken> strippedTokens = new(); for (int i = 0; i < tokenList.Count; i++) { if (tokenList[i].Kind() is SyntaxKind.PublicKeyword or SyntaxKind.InternalKeyword or SyntaxKind.ProtectedKeyword or SyntaxKind.PrivateKeyword) { continue; } strippedTokens.Add(tokenList[i]); } return new SyntaxTokenList(strippedTokens); } public static SyntaxTokenList AddToModifiers(this SyntaxTokenList modifiers, SyntaxKind modifierToAdd) { if (modifiers.IndexOf(modifierToAdd) >= 0) { return modifiers; } // https://github.com/dotnet/csharplang/blob/main/meetings/2018/LDM-2018-04-04.md#ordering-of-ref-and-partial-keywords int idxPartial = modifiers.IndexOf(SyntaxKind.PartialKeyword); int idxRef = modifiers.IndexOf(SyntaxKind.RefKeyword); int idxInsert = (idxPartial, idxRef) switch { (-1, -1) => modifiers.Count, (-1, _) => idxRef, (_, -1) => idxPartial, (_, _) => Math.Min(idxPartial, idxRef) }; return modifiers.Insert(idxInsert, SyntaxFactory.Token(modifierToAdd)); } public static bool IsInPartialContext(this TypeDeclarationSyntax syntax, [NotNullWhen(false)] out SyntaxToken? nonPartialIdentifier) { for (SyntaxNode? parentNode = syntax; parentNode is TypeDeclarationSyntax typeDecl; parentNode = parentNode.Parent) { if (!typeDecl.Modifiers.Any(SyntaxKind.PartialKeyword)) { nonPartialIdentifier = typeDecl.Identifier; return false; } } nonPartialIdentifier = null; return true; } } }