File: Language\SourceChange.cs
Web Access
Project: src\src\Razor\src\Compiler\Microsoft.CodeAnalysis.Razor.Compiler\src\Microsoft.CodeAnalysis.Razor.Compiler.csproj (Microsoft.CodeAnalysis.Razor.Compiler)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#nullable disable
 
using System;
using Microsoft.AspNetCore.Razor.Language.Syntax;
using Microsoft.Extensions.Internal;
 
namespace Microsoft.AspNetCore.Razor.Language;
 
public sealed class SourceChange : IEquatable<SourceChange>
{
    public SourceChange(int absoluteIndex, int length, string newText)
    {
        if (absoluteIndex < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(absoluteIndex));
        }
 
        if (length < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(length));
        }
 
        if (newText == null)
        {
            throw new ArgumentNullException(nameof(newText));
        }
 
        Span = new SourceSpan(absoluteIndex, length);
        NewText = newText;
    }
 
    public SourceChange(SourceSpan span, string newText)
    {
        if (newText == null)
        {
            throw new ArgumentNullException(nameof(newText));
        }
 
        Span = span;
        NewText = newText;
    }
 
    public bool IsDelete => Span.Length > 0 && NewText.Length == 0;
 
    public bool IsInsert => Span.Length == 0 && NewText.Length > 0;
 
    public bool IsReplace => Span.Length > 0 && NewText.Length > 0;
 
    public SourceSpan Span { get; }
 
    public string NewText { get; }
 
    internal string GetEditedContent(SyntaxNode node)
    {
        if (node == null)
        {
            throw new ArgumentNullException(nameof(node));
        }
 
        var offset = GetOffset(node);
        return GetEditedContent(node.GetContent(), offset);
    }
 
    internal string GetEditedContent(string text, int offset)
    {
        if (text == null)
        {
            throw new ArgumentNullException(nameof(text));
        }
 
        return text.Remove(offset, Span.Length).Insert(offset, NewText);
    }
 
    internal int GetOffset(SyntaxNode node)
    {
        if (node == null)
        {
            throw new ArgumentNullException(nameof(node));
        }
 
        var start = Span.AbsoluteIndex;
        var end = Span.AbsoluteIndex + Span.Length;
 
        if (start < node.Position ||
            start > node.EndPosition ||
            end < node.Position ||
            end > node.EndPosition)
        {
            throw new InvalidOperationException(Resources.FormatInvalidOperation_SpanIsNotChangeOwner(node, this));
        }
 
        return start - node.Position;
    }
 
    internal string GetOriginalText(SyntaxNode node)
    {
        if (node == null)
        {
            throw new ArgumentNullException(nameof(node));
        }
 
        if (node.Width == 0)
        {
            return string.Empty;
        }
 
        var offset = GetOffset(node);
        return node.GetContent().Substring(offset, Span.Length);
    }
 
    public bool Equals(SourceChange other)
    {
        return
            other != null &&
            Span.Equals(other.Span) &&
            string.Equals(NewText, other.NewText, StringComparison.Ordinal);
    }
 
    public override bool Equals(object obj)
    {
        return Equals(obj as SourceChange);
    }
 
    public override int GetHashCode()
    {
        var hash = HashCodeCombiner.Start();
        hash.Add(Span);
        hash.Add(NewText, StringComparer.Ordinal);
        return hash;
    }
 
    public override string ToString()
    {
        return Span.ToString() + " : " + NewText;
    }
}