| File: Syntax\InternalSyntax\SyntaxFirstTokenReplacer.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// 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.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax { internal class SyntaxFirstTokenReplacer : CSharpSyntaxRewriter { private readonly SyntaxToken _oldToken; private readonly SyntaxToken _newToken; private readonly int _diagnosticOffsetDelta; private bool _foundOldToken; private SyntaxFirstTokenReplacer(SyntaxToken oldToken, SyntaxToken newToken, int diagnosticOffsetDelta) { _oldToken = oldToken; _newToken = newToken; _diagnosticOffsetDelta = diagnosticOffsetDelta; _foundOldToken = false; } internal static TRoot Replace<TRoot>(TRoot root, SyntaxToken oldToken, SyntaxToken newToken, int diagnosticOffsetDelta) where TRoot : CSharpSyntaxNode { var replacer = new SyntaxFirstTokenReplacer(oldToken, newToken, diagnosticOffsetDelta); var newRoot = (TRoot)replacer.Visit(root); Debug.Assert(replacer._foundOldToken); return newRoot; } public override CSharpSyntaxNode Visit(CSharpSyntaxNode node) { if (node != null) { if (!_foundOldToken) { var token = node as SyntaxToken; if (token != null) { Debug.Assert(token == _oldToken); _foundOldToken = true; return _newToken; // NB: diagnostic offsets have already been updated (by SyntaxParser.AddSkippedSyntax) } return UpdateDiagnosticOffset(base.Visit(node), _diagnosticOffsetDelta); } } return node; } private static TSyntax UpdateDiagnosticOffset<TSyntax>(TSyntax node, int diagnosticOffsetDelta) where TSyntax : CSharpSyntaxNode { DiagnosticInfo[] oldDiagnostics = node.GetDiagnostics(); if (oldDiagnostics == null || oldDiagnostics.Length == 0) { return node; } var numDiagnostics = oldDiagnostics.Length; DiagnosticInfo[] newDiagnostics = new DiagnosticInfo[numDiagnostics]; for (int i = 0; i < numDiagnostics; i++) { DiagnosticInfo oldDiagnostic = oldDiagnostics[i]; SyntaxDiagnosticInfo oldSyntaxDiagnostic = oldDiagnostic as SyntaxDiagnosticInfo; newDiagnostics[i] = oldSyntaxDiagnostic == null ? oldDiagnostic : new SyntaxDiagnosticInfo( oldSyntaxDiagnostic.Offset + diagnosticOffsetDelta, oldSyntaxDiagnostic.Width, (ErrorCode)oldSyntaxDiagnostic.Code, oldSyntaxDiagnostic.Arguments); } return node.WithDiagnosticsGreen(newDiagnostics); } } }