Clean up SourceLocation
This change makes SourceLocation public and moves some of the undesirable functions off of the class and into the .Legacy namespace.
This commit is contained in:
parent
e84bc66700
commit
6b075880ce
|
|
@ -1142,7 +1142,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
if (!seenClose)
|
||||
{
|
||||
Context.ErrorSink.OnError(
|
||||
SourceLocation.Advance(tag.Item2, "<"),
|
||||
SourceLocationTracker.Advance(tag.Item2, "<"),
|
||||
LegacyResources.FormatParseError_UnfinishedTag(tag.Item1.Content),
|
||||
Math.Max(tag.Item1.Content.Length, 1));
|
||||
}
|
||||
|
|
@ -1277,7 +1277,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
if (!Optional(HtmlSymbolType.CloseAngle))
|
||||
{
|
||||
Context.ErrorSink.OnError(
|
||||
SourceLocation.Advance(tagStart, "</"),
|
||||
SourceLocationTracker.Advance(tagStart, "</"),
|
||||
LegacyResources.FormatParseError_UnfinishedTag(ScriptTagName),
|
||||
ScriptTagName.Length);
|
||||
}
|
||||
|
|
@ -1335,14 +1335,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
if (currentTag != null)
|
||||
{
|
||||
Context.ErrorSink.OnError(
|
||||
SourceLocation.Advance(currentTag.Item2, "<"),
|
||||
SourceLocationTracker.Advance(currentTag.Item2, "<"),
|
||||
LegacyResources.FormatParseError_MissingEndTag(currentTag.Item1.Content),
|
||||
currentTag.Item1.Content.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.ErrorSink.OnError(
|
||||
SourceLocation.Advance(tagStart, "</"),
|
||||
SourceLocationTracker.Advance(tagStart, "</"),
|
||||
LegacyResources.FormatParseError_UnexpectedEndTag(tagName),
|
||||
tagName.Length);
|
||||
}
|
||||
|
|
@ -1360,7 +1360,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
}
|
||||
var tag = tags.Pop();
|
||||
Context.ErrorSink.OnError(
|
||||
SourceLocation.Advance(tag.Item2, "<"),
|
||||
SourceLocationTracker.Advance(tag.Item2, "<"),
|
||||
LegacyResources.FormatParseError_MissingEndTag(tag.Item1.Content),
|
||||
tag.Item1.Content.Length);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,194 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||
{
|
||||
/// <summary>
|
||||
/// A location in a Razor file.
|
||||
/// </summary>
|
||||
internal struct SourceLocation : IEquatable<SourceLocation>
|
||||
{
|
||||
/// <summary>
|
||||
/// An undefined <see cref="SourceLocation"/>.
|
||||
/// </summary>
|
||||
public static readonly SourceLocation Undefined =
|
||||
new SourceLocation(absoluteIndex: -1, lineIndex: -1, characterIndex: -1);
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="SourceLocation"/> with <see cref="AbsoluteIndex"/>, <see cref="LineIndex"/>, and
|
||||
/// <see cref="CharacterIndex"/> initialized to 0.
|
||||
/// </summary>
|
||||
public static readonly SourceLocation Zero =
|
||||
new SourceLocation(absoluteIndex: 0, lineIndex: 0, characterIndex: 0);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SourceLocation"/>.
|
||||
/// </summary>
|
||||
/// <param name="absoluteIndex">The absolute index.</param>
|
||||
/// <param name="lineIndex">The line index.</param>
|
||||
/// <param name="characterIndex">The character index.</param>
|
||||
public SourceLocation(int absoluteIndex, int lineIndex, int characterIndex)
|
||||
: this(filePath: null, absoluteIndex: absoluteIndex, lineIndex: lineIndex, characterIndex: characterIndex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SourceLocation"/>.
|
||||
/// </summary>
|
||||
/// <param name="filePath">The file path.</param>
|
||||
/// <param name="absoluteIndex">The absolute index.</param>
|
||||
/// <param name="lineIndex">The line index.</param>
|
||||
/// <param name="characterIndex">The character index.</param>
|
||||
public SourceLocation(string filePath, int absoluteIndex, int lineIndex, int characterIndex)
|
||||
{
|
||||
FilePath = filePath;
|
||||
AbsoluteIndex = absoluteIndex;
|
||||
LineIndex = lineIndex;
|
||||
CharacterIndex = characterIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Path of the file.
|
||||
/// </summary>
|
||||
/// <remarks>When <c>null</c>, the parser assumes the location is in the file currently being processed.
|
||||
/// </remarks>
|
||||
public string FilePath { get; set; }
|
||||
|
||||
/// <remarks>Set property is only accessible for deserialization purposes.</remarks>
|
||||
public int AbsoluteIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the 1-based index of the line referred to by this Source Location.
|
||||
/// </summary>
|
||||
/// <remarks>Set property is only accessible for deserialization purposes.</remarks>
|
||||
public int LineIndex { get; set; }
|
||||
|
||||
/// <remarks>Set property is only accessible for deserialization purposes.</remarks>
|
||||
public int CharacterIndex { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
"({0}:{1},{2})",
|
||||
AbsoluteIndex,
|
||||
LineIndex,
|
||||
CharacterIndex);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is SourceLocation &&
|
||||
Equals((SourceLocation)obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCodeCombiner = HashCodeCombiner.Start();
|
||||
hashCodeCombiner.Add(FilePath, StringComparer.Ordinal);
|
||||
hashCodeCombiner.Add(AbsoluteIndex);
|
||||
|
||||
return hashCodeCombiner;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(SourceLocation other)
|
||||
{
|
||||
// LineIndex and CharacterIndex can be calculated from AbsoluteIndex and the document content.
|
||||
return string.Equals(FilePath, other.FilePath, StringComparison.Ordinal) &&
|
||||
AbsoluteIndex == other.AbsoluteIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Advances the <see cref="SourceLocation"/> by the length of the <paramref name="text" />.
|
||||
/// </summary>
|
||||
/// <param name="left">The <see cref="SourceLocation"/> to advance.</param>
|
||||
/// <param name="text">The <see cref="string"/> to advance <paramref name="left"/> by.</param>
|
||||
/// <returns>The advanced <see cref="SourceLocation"/>.</returns>
|
||||
public static SourceLocation Advance(SourceLocation left, string text)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(text));
|
||||
}
|
||||
|
||||
var tracker = new SourceLocationTracker(left);
|
||||
tracker.UpdateLocation(text);
|
||||
return tracker.CurrentLocation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds two <see cref="SourceLocation"/>s.
|
||||
/// </summary>
|
||||
/// <param name="left">The left operand.</param>
|
||||
/// <param name="right">The right operand.</param>
|
||||
/// <returns>A <see cref="SourceLocation"/> that is the sum of the left and right operands.</returns>
|
||||
/// <exception cref="ArgumentException">if the <see cref="FilePath"/> of the left and right operands
|
||||
/// are different, and neither is null.</exception>
|
||||
public static SourceLocation operator +(SourceLocation left, SourceLocation right)
|
||||
{
|
||||
if (!string.Equals(left.FilePath, right.FilePath, StringComparison.Ordinal) &&
|
||||
left.FilePath != null &&
|
||||
right.FilePath != null)
|
||||
{
|
||||
// Throw if FilePath for left and right are different, and neither is null.
|
||||
throw new ArgumentException(
|
||||
LegacyResources.FormatSourceLocationFilePathDoesNotMatch(nameof(SourceLocation), "+"),
|
||||
nameof(right));
|
||||
}
|
||||
|
||||
var resultFilePath = left.FilePath ?? right.FilePath;
|
||||
if (right.LineIndex > 0)
|
||||
{
|
||||
// Column index doesn't matter
|
||||
return new SourceLocation(
|
||||
resultFilePath,
|
||||
left.AbsoluteIndex + right.AbsoluteIndex,
|
||||
left.LineIndex + right.LineIndex,
|
||||
right.CharacterIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new SourceLocation(
|
||||
resultFilePath,
|
||||
left.AbsoluteIndex + right.AbsoluteIndex,
|
||||
left.LineIndex + right.LineIndex,
|
||||
left.CharacterIndex + right.CharacterIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two <see cref="SourceLocation"/>s.
|
||||
/// </summary>
|
||||
/// <param name="left">The left operand.</param>
|
||||
/// <param name="right">The right operand.</param>
|
||||
/// <returns>A <see cref="SourceLocation"/> that is the difference of the left and right operands.</returns>
|
||||
/// <exception cref="ArgumentException">if the <see cref="FilePath"/> of the left and right operands
|
||||
/// are different.</exception>
|
||||
public static SourceLocation operator -(SourceLocation left, SourceLocation right)
|
||||
{
|
||||
if (!string.Equals(left.FilePath, right.FilePath, StringComparison.Ordinal))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
LegacyResources.FormatSourceLocationFilePathDoesNotMatch(nameof(SourceLocation), "-"),
|
||||
nameof(right));
|
||||
}
|
||||
|
||||
var characterIndex = left.LineIndex != right.LineIndex ?
|
||||
left.CharacterIndex : left.CharacterIndex - right.CharacterIndex;
|
||||
|
||||
return new SourceLocation(
|
||||
filePath: null,
|
||||
absoluteIndex: left.AbsoluteIndex - right.AbsoluteIndex,
|
||||
lineIndex: left.LineIndex - right.LineIndex,
|
||||
characterIndex: characterIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +40,18 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
}
|
||||
}
|
||||
|
||||
public static SourceLocation Advance(SourceLocation location, string text)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(text));
|
||||
}
|
||||
|
||||
var tracker = new SourceLocationTracker(location);
|
||||
tracker.UpdateLocation(text);
|
||||
return tracker.CurrentLocation;
|
||||
}
|
||||
|
||||
public void UpdateLocation(char characterRead, char nextCharacter)
|
||||
{
|
||||
UpdateCharacterCore(characterRead, nextCharacter);
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
i--;
|
||||
|
||||
name = nameBuilder.ToString();
|
||||
attributeValueStartLocation = SourceLocation.Advance(attributeValueStartLocation, name);
|
||||
attributeValueStartLocation = SourceLocationTracker.Advance(attributeValueStartLocation, name);
|
||||
}
|
||||
else if (symbol.Type == HtmlSymbolType.Equals)
|
||||
{
|
||||
|
|
@ -259,9 +259,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
symbolStartLocation = symbol.Start;
|
||||
}
|
||||
|
||||
attributeValueStartLocation =
|
||||
symbolStartLocation +
|
||||
new SourceLocation(absoluteIndex: 1, lineIndex: 0, characterIndex: 1);
|
||||
attributeValueStartLocation = new SourceLocation(
|
||||
symbolStartLocation.FilePath,
|
||||
symbolStartLocation.AbsoluteIndex + 1,
|
||||
symbolStartLocation.LineIndex,
|
||||
symbolStartLocation.CharacterIndex + 1);
|
||||
|
||||
afterEquals = true;
|
||||
}
|
||||
|
|
@ -274,7 +276,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
// parser currently does not know how to handle attributes in that format. This will be addressed
|
||||
// by https://github.com/aspnet/Razor/issues/123.
|
||||
|
||||
attributeValueStartLocation = SourceLocation.Advance(attributeValueStartLocation, symbol.Content);
|
||||
attributeValueStartLocation = SourceLocationTracker.Advance(attributeValueStartLocation, symbol.Content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
{
|
||||
// End tag TagHelper that states it shouldn't have an end tag.
|
||||
errorSink.OnError(
|
||||
SourceLocation.Advance(tagBlock.Start, "</"),
|
||||
SourceLocationTracker.Advance(tagBlock.Start, "</"),
|
||||
LegacyResources.FormatTagHelperParseTreeRewriter_EndTagTagHelperMustNotHaveAnEndTag(
|
||||
tagName,
|
||||
invalidDescriptor.TypeName,
|
||||
|
|
@ -295,7 +295,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
// Could not recover, the end tag helper has no corresponding start tag, create
|
||||
// an error based on the current childBlock.
|
||||
errorSink.OnError(
|
||||
SourceLocation.Advance(tagBlock.Start, "</"),
|
||||
SourceLocationTracker.Advance(tagBlock.Start, "</"),
|
||||
LegacyResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(tagName),
|
||||
tagName.Length);
|
||||
|
||||
|
|
@ -475,7 +475,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
{
|
||||
var trimmedStart = content.TrimStart();
|
||||
var whitespace = content.Substring(0, content.Length - trimmedStart.Length);
|
||||
var errorStart = SourceLocation.Advance(child.Start, whitespace);
|
||||
var errorStart = SourceLocationTracker.Advance(child.Start, whitespace);
|
||||
var length = trimmedStart.TrimEnd().Length;
|
||||
var allowedChildren = _currentTagHelperTracker.AllowedChildren;
|
||||
var allowedChildrenString = string.Join(", ", allowedChildren);
|
||||
|
|
@ -589,7 +589,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
{
|
||||
var advanceBy = IsEndTag(tagBlock) ? "</" : "<";
|
||||
|
||||
return SourceLocation.Advance(tagBlock.Start, advanceBy);
|
||||
return SourceLocationTracker.Advance(tagBlock.Start, advanceBy);
|
||||
}
|
||||
|
||||
private static bool IsPartialTag(Block tagBlock)
|
||||
|
|
@ -733,7 +733,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
var malformedTagHelper = ((TagHelperBlockTracker)tracker).Builder;
|
||||
|
||||
errorSink.OnError(
|
||||
SourceLocation.Advance(malformedTagHelper.Start, "<"),
|
||||
SourceLocationTracker.Advance(malformedTagHelper.Start, "<"),
|
||||
LegacyResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(
|
||||
malformedTagHelper.TagName),
|
||||
malformedTagHelper.TagName.Length);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
/// <summary>
|
||||
/// A location in a Razor file.
|
||||
/// </summary>
|
||||
public struct SourceLocation : IEquatable<SourceLocation>
|
||||
{
|
||||
/// <summary>
|
||||
/// An undefined <see cref="SourceLocation"/>.
|
||||
/// </summary>
|
||||
public static readonly SourceLocation Undefined =
|
||||
new SourceLocation(absoluteIndex: -1, lineIndex: -1, characterIndex: -1);
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="SourceLocation"/> with <see cref="AbsoluteIndex"/>, <see cref="LineIndex"/>, and
|
||||
/// <see cref="CharacterIndex"/> initialized to 0.
|
||||
/// </summary>
|
||||
public static readonly SourceLocation Zero =
|
||||
new SourceLocation(absoluteIndex: 0, lineIndex: 0, characterIndex: 0);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SourceLocation"/>.
|
||||
/// </summary>
|
||||
/// <param name="absoluteIndex">The absolute index.</param>
|
||||
/// <param name="lineIndex">The line index.</param>
|
||||
/// <param name="characterIndex">The character index.</param>
|
||||
public SourceLocation(int absoluteIndex, int lineIndex, int characterIndex)
|
||||
: this(filePath: null, absoluteIndex: absoluteIndex, lineIndex: lineIndex, characterIndex: characterIndex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SourceLocation"/>.
|
||||
/// </summary>
|
||||
/// <param name="filePath">The file path.</param>
|
||||
/// <param name="absoluteIndex">The absolute index.</param>
|
||||
/// <param name="lineIndex">The line index.</param>
|
||||
/// <param name="characterIndex">The character index.</param>
|
||||
public SourceLocation(string filePath, int absoluteIndex, int lineIndex, int characterIndex)
|
||||
{
|
||||
FilePath = filePath;
|
||||
AbsoluteIndex = absoluteIndex;
|
||||
LineIndex = lineIndex;
|
||||
CharacterIndex = characterIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Path of the file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// When <c>null</c>, the parser assumes the location is in the file currently being processed.
|
||||
/// </para>
|
||||
/// <para>Set property is only accessible for deserialization purposes.</para>
|
||||
/// </remarks>
|
||||
public string FilePath { get; set; }
|
||||
|
||||
/// <remarks>Set property is only accessible for deserialization purposes.</remarks>
|
||||
public int AbsoluteIndex { get; set; }
|
||||
|
||||
/// <remarks>Set property is only accessible for deserialization purposes.</remarks>
|
||||
public int LineIndex { get; set; }
|
||||
|
||||
/// <remarks>Set property is only accessible for deserialization purposes.</remarks>
|
||||
public int CharacterIndex { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
"({0}:{1},{2})",
|
||||
AbsoluteIndex,
|
||||
LineIndex,
|
||||
CharacterIndex);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is SourceLocation &&
|
||||
Equals((SourceLocation)obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCodeCombiner = HashCodeCombiner.Start();
|
||||
hashCodeCombiner.Add(FilePath, StringComparer.Ordinal);
|
||||
hashCodeCombiner.Add(AbsoluteIndex);
|
||||
|
||||
return hashCodeCombiner;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(SourceLocation other)
|
||||
{
|
||||
// LineIndex and CharacterIndex can be calculated from AbsoluteIndex and the document content.
|
||||
return string.Equals(FilePath, other.FilePath, StringComparison.Ordinal) &&
|
||||
AbsoluteIndex == other.AbsoluteIndex;
|
||||
}
|
||||
|
||||
public static bool operator==(SourceLocation left, SourceLocation right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(SourceLocation left, SourceLocation right)
|
||||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
absoluteIndex: 5 + attributeNameLength + newlineLength,
|
||||
lineIndex: 1,
|
||||
characterIndex: 2 + attributeNameLength);
|
||||
var prefixLocation2 = SourceLocation.Advance(suffixLocation1, "'");
|
||||
var prefixLocation2 = SourceLocationTracker.Advance(suffixLocation1, "'");
|
||||
var suffixLocation2 = new SourceLocation(
|
||||
absoluteIndex: 15 + attributeNameLength * 2 + newlineLength * 2,
|
||||
lineIndex: 2,
|
||||
|
|
@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
absoluteIndex: 7 + attributeNameLength + newlineLength,
|
||||
lineIndex: 1,
|
||||
characterIndex: 4 + attributeNameLength);
|
||||
var prefixLocation2 = SourceLocation.Advance(suffixLocation1, "'");
|
||||
var prefixLocation2 = SourceLocationTracker.Advance(suffixLocation1, "'");
|
||||
var suffixLocation2 = new SourceLocation(
|
||||
absoluteIndex: 17 + attributeNameLength * 2 + newlineLength * 2,
|
||||
lineIndex: 2,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
public SourceLocation Start { get; private set; }
|
||||
public string Content { get; }
|
||||
public Span Parent { get; set; }
|
||||
public int Offset { get; set; }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
|
|
@ -36,16 +35,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
return Content == null ? 0 : Content.GetHashCode();
|
||||
}
|
||||
|
||||
public void OffsetStart(SourceLocation documentStart)
|
||||
{
|
||||
Start = documentStart + Start;
|
||||
}
|
||||
|
||||
public void ChangeStart(SourceLocation newStart)
|
||||
{
|
||||
Start = newStart;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0} RAW - [{1}]", Start, Content);
|
||||
|
|
|
|||
|
|
@ -1,266 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||
{
|
||||
public class SourceLocationTest
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructorWithLineAndCharacterIndexSetsAssociatedProperties()
|
||||
{
|
||||
// Act
|
||||
var loc = new SourceLocation(0, 42, 24);
|
||||
|
||||
// Assert
|
||||
Assert.Null(loc.FilePath);
|
||||
Assert.Equal(0, loc.AbsoluteIndex);
|
||||
Assert.Equal(42, loc.LineIndex);
|
||||
Assert.Equal(24, loc.CharacterIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_SetsFilePathAndIndexes()
|
||||
{
|
||||
// Arrange
|
||||
var filePath = "some-file-path";
|
||||
var absoluteIndex = 133;
|
||||
var lineIndex = 23;
|
||||
var characterIndex = 12;
|
||||
|
||||
// Act
|
||||
var sourceLocation = new SourceLocation(filePath, absoluteIndex, lineIndex, characterIndex);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(filePath, sourceLocation.FilePath);
|
||||
Assert.Equal(absoluteIndex, sourceLocation.AbsoluteIndex);
|
||||
Assert.Equal(lineIndex, sourceLocation.LineIndex);
|
||||
Assert.Equal(characterIndex, sourceLocation.CharacterIndex);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("some-file")]
|
||||
public void GetHashCode_ReturnsSameValue_WhenEqual(string path)
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(path, 10, 3, 4);
|
||||
var sourceLocationB = new SourceLocation(path, 10, 3, 4);
|
||||
var sourceLocationC = new SourceLocation(path, 10, 45, 8754);
|
||||
|
||||
// Act
|
||||
var hashCodeA = sourceLocationA.GetHashCode();
|
||||
var hashCodeB = sourceLocationB.GetHashCode();
|
||||
var hashCodeC = sourceLocationC.GetHashCode();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hashCodeA, hashCodeB);
|
||||
Assert.Equal(hashCodeA, hashCodeC);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equals_ReturnsTrue_FilePathsNullAndAbsoluteIndicesMatch()
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(10, 3, 4);
|
||||
var sourceLocationB = new SourceLocation(10, 45, 8754);
|
||||
|
||||
// Act
|
||||
var result = sourceLocationA.Equals(sourceLocationB);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equals_ReturnsFalse_IfFilePathIsDifferent()
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(10, 3, 4);
|
||||
var sourceLocationB = new SourceLocation("different-file", 10, 3, 4);
|
||||
|
||||
// Act
|
||||
var result = sourceLocationA.Equals(sourceLocationB);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("some-file")]
|
||||
public void Equals_ReturnsTrue_IfFilePathAndIndexesAreSame(string path)
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(path, 10, 3, 4);
|
||||
var sourceLocationB = new SourceLocation(path, 10, 3, 4);
|
||||
var sourceLocationC = new SourceLocation("different-path", 10, 3, 4);
|
||||
|
||||
// Act
|
||||
var result1 = sourceLocationA.Equals(sourceLocationB);
|
||||
var result2 = sourceLocationA.Equals(sourceLocationC);
|
||||
|
||||
// Assert
|
||||
Assert.True(result1);
|
||||
Assert.False(result2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_Throws_IfFilePathsDoNotMatch()
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation("a-path", 1, 1, 1);
|
||||
var sourceLocationB = new SourceLocation("b-path", 1, 1, 1);
|
||||
|
||||
// Act and Assert
|
||||
ExceptionAssert.ThrowsArgument(
|
||||
() => { var result = sourceLocationA + sourceLocationB; },
|
||||
"right",
|
||||
$"Cannot perform '+' operations on 'SourceLocation' instances with different file paths.");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("same-path")]
|
||||
public void Add_IgnoresCharacterIndexIfRightLineIndexIsNonZero(string path)
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(path, 1, 2, 3);
|
||||
var sourceLocationB = new SourceLocation(path, 4, 5, 6);
|
||||
|
||||
// Act
|
||||
var result = sourceLocationA + sourceLocationB;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(path, result.FilePath);
|
||||
Assert.Equal(5, result.AbsoluteIndex);
|
||||
Assert.Equal(7, result.LineIndex);
|
||||
Assert.Equal(6, result.CharacterIndex);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("same-path")]
|
||||
public void Add_UsesCharacterIndexIfRightLineIndexIsZero(string path)
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(path, 2, 5, 3);
|
||||
var sourceLocationB = new SourceLocation(path, 4, 0, 6);
|
||||
|
||||
// Act
|
||||
var result = sourceLocationA + sourceLocationB;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(path, result.FilePath);
|
||||
Assert.Equal(6, result.AbsoluteIndex);
|
||||
Assert.Equal(5, result.LineIndex);
|
||||
Assert.Equal(9, result.CharacterIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_AllowsRightFilePathToBeNull_WhenLeftFilePathIsNonNull()
|
||||
{
|
||||
// Arrange
|
||||
var left = new SourceLocation("left-path", 7, 1, 7);
|
||||
var right = new SourceLocation(13, 1, 4);
|
||||
|
||||
// Act
|
||||
var result = left + right;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(left.FilePath, result.FilePath);
|
||||
Assert.Equal(20, result.AbsoluteIndex);
|
||||
Assert.Equal(2, result.LineIndex);
|
||||
Assert.Equal(4, result.CharacterIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_AllowsLeftFilePathToBeNull_WhenRightFilePathIsNonNull()
|
||||
{
|
||||
// Arrange
|
||||
var left = new SourceLocation(4, 5, 6);
|
||||
var right = new SourceLocation("right-path", 7, 8, 9);
|
||||
|
||||
// Act
|
||||
var result = left + right;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(right.FilePath, result.FilePath);
|
||||
Assert.Equal(11, result.AbsoluteIndex);
|
||||
Assert.Equal(13, result.LineIndex);
|
||||
Assert.Equal(9, result.CharacterIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Subtract_Throws_IfFilePathsDoNotMatch()
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation("a-path", 1, 1, 1);
|
||||
var sourceLocationB = new SourceLocation("b-path", 1, 1, 1);
|
||||
|
||||
// Act and Assert
|
||||
ExceptionAssert.ThrowsArgument(
|
||||
() => { var result = sourceLocationA - sourceLocationB; },
|
||||
"right",
|
||||
"Cannot perform '-' operations on 'SourceLocation' instances with different file paths.");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("same-path")]
|
||||
public void Subtract_UsesDifferenceOfCharacterIndexesIfLineIndexesAreSame(string path)
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(path, 1, 5, 3);
|
||||
var sourceLocationB = new SourceLocation(path, 5, 5, 6);
|
||||
|
||||
// Act
|
||||
var result = sourceLocationB - sourceLocationA;
|
||||
|
||||
// Assert
|
||||
Assert.Null(result.FilePath);
|
||||
Assert.Equal(4, result.AbsoluteIndex);
|
||||
Assert.Equal(0, result.LineIndex);
|
||||
Assert.Equal(3, result.CharacterIndex);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("same-path")]
|
||||
public void Subtract_UsesLeftCharacterIndexIfLineIndexesAreDifferent(string path)
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(path, 2, 0, 3);
|
||||
var sourceLocationB = new SourceLocation(path, 4, 5, 6);
|
||||
|
||||
// Act
|
||||
var result = sourceLocationB - sourceLocationA;
|
||||
|
||||
// Assert
|
||||
Assert.Null(result.FilePath);
|
||||
Assert.Equal(2, result.AbsoluteIndex);
|
||||
Assert.Equal(5, result.LineIndex);
|
||||
Assert.Equal(6, result.CharacterIndex);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("path-to-file")]
|
||||
public void Advance_PreservesSourceLocationFilePath(string path)
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocation = new SourceLocation(path, 15, 2, 8);
|
||||
|
||||
// Act
|
||||
var result = SourceLocation.Advance(sourceLocation, "Hello world");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(path, result.FilePath);
|
||||
Assert.Equal(26, result.AbsoluteIndex);
|
||||
Assert.Equal(2, result.LineIndex);
|
||||
Assert.Equal(19, result.CharacterIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,24 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
Assert.Equal(loc, new SourceLocationTracker(loc).CurrentLocation);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("path-to-file")]
|
||||
public void Advance_PreservesSourceLocationFilePath(string path)
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocation = new SourceLocation(path, 15, 2, 8);
|
||||
|
||||
// Act
|
||||
var result = SourceLocationTracker.Advance(sourceLocation, "Hello world");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(path, result.FilePath);
|
||||
Assert.Equal(26, result.AbsoluteIndex);
|
||||
Assert.Equal(2, result.LineIndex);
|
||||
Assert.Equal(19, result.CharacterIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpdateLocationAdvancesCorrectlyForMultiLineString()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3629,7 +3629,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
for (var i = 0; i < errors.Length; i++)
|
||||
{
|
||||
var error = errors[i];
|
||||
error.Location = SourceLocation.Advance(error.Location, "@{");
|
||||
error.Location = SourceLocationTracker.Advance(error.Location, "@{");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
public class SourceLocationTest
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructorWithLineAndCharacterIndexSetsAssociatedProperties()
|
||||
{
|
||||
// Act
|
||||
var loc = new SourceLocation(0, 42, 24);
|
||||
|
||||
// Assert
|
||||
Assert.Null(loc.FilePath);
|
||||
Assert.Equal(0, loc.AbsoluteIndex);
|
||||
Assert.Equal(42, loc.LineIndex);
|
||||
Assert.Equal(24, loc.CharacterIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_SetsFilePathAndIndexes()
|
||||
{
|
||||
// Arrange
|
||||
var filePath = "some-file-path";
|
||||
var absoluteIndex = 133;
|
||||
var lineIndex = 23;
|
||||
var characterIndex = 12;
|
||||
|
||||
// Act
|
||||
var sourceLocation = new SourceLocation(filePath, absoluteIndex, lineIndex, characterIndex);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(filePath, sourceLocation.FilePath);
|
||||
Assert.Equal(absoluteIndex, sourceLocation.AbsoluteIndex);
|
||||
Assert.Equal(lineIndex, sourceLocation.LineIndex);
|
||||
Assert.Equal(characterIndex, sourceLocation.CharacterIndex);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("some-file")]
|
||||
public void GetHashCode_ReturnsSameValue_WhenEqual(string path)
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(path, 10, 3, 4);
|
||||
var sourceLocationB = new SourceLocation(path, 10, 3, 4);
|
||||
var sourceLocationC = new SourceLocation(path, 10, 45, 8754);
|
||||
|
||||
// Act
|
||||
var hashCodeA = sourceLocationA.GetHashCode();
|
||||
var hashCodeB = sourceLocationB.GetHashCode();
|
||||
var hashCodeC = sourceLocationC.GetHashCode();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hashCodeA, hashCodeB);
|
||||
Assert.Equal(hashCodeA, hashCodeC);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equals_ReturnsTrue_FilePathsNullAndAbsoluteIndicesMatch()
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(10, 3, 4);
|
||||
var sourceLocationB = new SourceLocation(10, 45, 8754);
|
||||
|
||||
// Act
|
||||
var result = sourceLocationA.Equals(sourceLocationB);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equals_ReturnsFalse_IfFilePathIsDifferent()
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(10, 3, 4);
|
||||
var sourceLocationB = new SourceLocation("different-file", 10, 3, 4);
|
||||
|
||||
// Act
|
||||
var result = sourceLocationA.Equals(sourceLocationB);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("some-file")]
|
||||
public void Equals_ReturnsTrue_IfFilePathAndIndexesAreSame(string path)
|
||||
{
|
||||
// Arrange
|
||||
var sourceLocationA = new SourceLocation(path, 10, 3, 4);
|
||||
var sourceLocationB = new SourceLocation(path, 10, 3, 4);
|
||||
var sourceLocationC = new SourceLocation("different-path", 10, 3, 4);
|
||||
|
||||
// Act
|
||||
var result1 = sourceLocationA.Equals(sourceLocationB);
|
||||
var result2 = sourceLocationA.Equals(sourceLocationC);
|
||||
|
||||
// Assert
|
||||
Assert.True(result1);
|
||||
Assert.False(result2);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue