File: Language\SourceSpan.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 System.Globalization;
using Microsoft.Extensions.Internal;
 
namespace Microsoft.AspNetCore.Razor.Language;
 
public readonly struct SourceSpan : IEquatable<SourceSpan>
{
    public static readonly SourceSpan Undefined = new SourceSpan(SourceLocation.Undefined, 0);
 
    public SourceSpan(int absoluteIndex, int length)
        : this(null, absoluteIndex, -1, -1, length)
    {
    }
 
    public SourceSpan(SourceLocation location, int contentLength)
        : this(location.FilePath, location.AbsoluteIndex, location.LineIndex, location.CharacterIndex, contentLength, lineCount: 1, endCharacterIndex: 0)
    {
    }
 
    public SourceSpan(string filePath, int absoluteIndex, int lineIndex, int characterIndex, int length)
        : this(filePath: filePath, absoluteIndex: absoluteIndex, lineIndex: lineIndex, characterIndex: characterIndex, length: length, lineCount: 0, endCharacterIndex: 0)
    {
    }
 
    public SourceSpan(string filePath, int absoluteIndex, int lineIndex, int characterIndex, int length, int lineCount, int endCharacterIndex)
    {
        AbsoluteIndex = absoluteIndex;
        LineIndex = lineIndex;
        CharacterIndex = characterIndex;
        Length = length;
        FilePath = filePath;
        LineCount = lineCount;
        EndCharacterIndex = endCharacterIndex;
    }
 
    public SourceSpan(int absoluteIndex, int lineIndex, int characterIndex, int length)
        : this(filePath: null, absoluteIndex: absoluteIndex, lineIndex: lineIndex, characterIndex: characterIndex, length: length)
    {
    }
 
    public int Length { get; }
 
    public int AbsoluteIndex { get; }
 
    public int LineIndex { get; }
 
    public int CharacterIndex { get; }
 
    public int LineCount { get; }
 
    public int EndCharacterIndex { get; }
 
    public string FilePath { get; }
 
    public bool Equals(SourceSpan other)
    {
        return
            string.Equals(FilePath, other.FilePath, StringComparison.Ordinal) &&
            AbsoluteIndex == other.AbsoluteIndex &&
            LineIndex == other.LineIndex &&
            CharacterIndex == other.CharacterIndex &&
            Length == other.Length;
    }
 
    public override bool Equals(object obj)
    {
        return obj is SourceSpan span && Equals(span);
    }
 
    public override int GetHashCode()
    {
        var hash = HashCodeCombiner.Start();
        hash.Add(FilePath, StringComparer.Ordinal);
        hash.Add(AbsoluteIndex);
        hash.Add(LineIndex);
        hash.Add(CharacterIndex);
        hash.Add(Length);
 
        return hash;
    }
 
    public override string ToString()
    {
        return string.Format(
            CultureInfo.CurrentCulture, "({0}:{1},{2} [{3}] {4})",
            AbsoluteIndex,
            LineIndex,
            CharacterIndex,
            Length,
            FilePath);
    }
 
    internal readonly SourceSpan GetZeroWidthEndSpan()
    {
        return new SourceSpan(FilePath, AbsoluteIndex + Length, LineIndex, characterIndex: EndCharacterIndex, length: 0, lineCount: 0, EndCharacterIndex);
    }
 
    internal readonly SourceSpan Slice(int startIndex, int length)
    {
        return new SourceSpan(FilePath, AbsoluteIndex + startIndex, LineIndex, CharacterIndex + startIndex, length, LineCount, endCharacterIndex: CharacterIndex + startIndex + length);
    }
 
    public static bool operator ==(SourceSpan left, SourceSpan right)
    {
        return left.Equals(right);
    }
 
    public static bool operator !=(SourceSpan left, SourceSpan right)
    {
        return !left.Equals(right);
    }
 
    public readonly int CompareByStartThenLength(SourceSpan other)
    {
        var cmpByStart = AbsoluteIndex.CompareTo(other.AbsoluteIndex);
        if (cmpByStart != 0)
        {
            return cmpByStart;
        }
 
        return Length.CompareTo(other.Length);
    }
 
    public readonly SourceSpan WithFilePath(string filePath) => new(filePath, AbsoluteIndex, LineIndex, CharacterIndex, Length, LineCount, EndCharacterIndex);
    public readonly SourceSpan WithAbsoluteIndex(int absoluteIndex) => new(FilePath, absoluteIndex, LineIndex, CharacterIndex, Length, LineCount, EndCharacterIndex);
    public readonly SourceSpan WithLineIndex(int lineIndex) => new(FilePath, AbsoluteIndex, lineIndex, CharacterIndex, Length, LineCount, EndCharacterIndex);
    public readonly SourceSpan WithCharacterIndex(int characterIndex) => new(FilePath, AbsoluteIndex, LineIndex, characterIndex, Length, LineCount, EndCharacterIndex);
    public readonly SourceSpan WithLength(int length) => new(FilePath, AbsoluteIndex, LineIndex, CharacterIndex, length, LineCount, EndCharacterIndex);
    public readonly SourceSpan WithLineCount(int lineCount) => new(FilePath, AbsoluteIndex, LineIndex, CharacterIndex, Length, lineCount, EndCharacterIndex);
    public readonly SourceSpan WithEndCharacterIndex(int endCharacterIndex) => new(FilePath, AbsoluteIndex, LineIndex, CharacterIndex, Length, LineCount, endCharacterIndex);
}