Set file path from RazorSourceDocument in syntax tree
This commit is contained in:
parent
6fbbd5d148
commit
cab6eea663
|
|
@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
|
|
||||||
public virtual IEnumerable<TSymbol> TokenizeString(SourceLocation start, string input)
|
public virtual IEnumerable<TSymbol> TokenizeString(SourceLocation start, string input)
|
||||||
{
|
{
|
||||||
using (var reader = new SeekableTextReader(input))
|
using (var reader = new SeekableTextReader(input, start.FilePath))
|
||||||
{
|
{
|
||||||
var tok = CreateTokenizer(reader);
|
var tok = CreateTokenizer(reader);
|
||||||
TSymbol sym;
|
TSymbol sym;
|
||||||
|
|
|
||||||
|
|
@ -11,20 +11,23 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
internal class LineTrackingStringBuffer
|
internal class LineTrackingStringBuffer
|
||||||
{
|
{
|
||||||
private readonly IList<TextLine> _lines;
|
private readonly IList<TextLine> _lines;
|
||||||
|
private readonly string _filePath;
|
||||||
private TextLine _currentLine;
|
private TextLine _currentLine;
|
||||||
private TextLine _endLine;
|
private TextLine _endLine;
|
||||||
|
|
||||||
public LineTrackingStringBuffer(string content)
|
public LineTrackingStringBuffer(string content, string filePath)
|
||||||
: this(content.ToCharArray())
|
: this(content.ToCharArray(), filePath)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public LineTrackingStringBuffer(char[] content)
|
public LineTrackingStringBuffer(char[] content, string filePath)
|
||||||
{
|
{
|
||||||
_endLine = new TextLine(0, 0);
|
_endLine = new TextLine(0, 0);
|
||||||
_lines = new List<TextLine>() { _endLine };
|
_lines = new List<TextLine>() { _endLine };
|
||||||
|
|
||||||
Append(content);
|
Append(content);
|
||||||
|
|
||||||
|
_filePath = filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Length
|
public int Length
|
||||||
|
|
@ -34,7 +37,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
|
|
||||||
public SourceLocation EndLocation
|
public SourceLocation EndLocation
|
||||||
{
|
{
|
||||||
get { return new SourceLocation(Length, _lines.Count - 1, _lines[_lines.Count - 1].Length); }
|
get { return new SourceLocation(_filePath, Length, _lines.Count - 1, _lines[_lines.Count - 1].Length); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharacterReference CharAt(int absoluteIndex)
|
public CharacterReference CharAt(int absoluteIndex)
|
||||||
|
|
@ -45,7 +48,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
throw new ArgumentOutOfRangeException(nameof(absoluteIndex));
|
throw new ArgumentOutOfRangeException(nameof(absoluteIndex));
|
||||||
}
|
}
|
||||||
var idx = absoluteIndex - line.Start;
|
var idx = absoluteIndex - line.Start;
|
||||||
return new CharacterReference(line.Content[idx], new SourceLocation(absoluteIndex, line.Index, idx));
|
return new CharacterReference(line.Content[idx], new SourceLocation(_filePath, absoluteIndex, line.Index, idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Append(char[] content)
|
private void Append(char[] content)
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
var chars = new char[source.Length];
|
var chars = new char[source.Length];
|
||||||
source.CopyTo(0, chars, 0, source.Length);
|
source.CopyTo(0, chars, 0, source.Length);
|
||||||
|
|
||||||
var reader = new SeekableTextReader(chars);
|
var reader = new SeekableTextReader(chars, source.FileName);
|
||||||
|
|
||||||
var context = new ParserContext(reader, Options.DesignTimeMode);
|
var context = new ParserContext(reader, Options.DesignTimeMode);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,20 +10,22 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
{
|
{
|
||||||
private readonly LineTrackingStringBuffer _buffer;
|
private readonly LineTrackingStringBuffer _buffer;
|
||||||
private int _position = 0;
|
private int _position = 0;
|
||||||
private SourceLocation _location = SourceLocation.Zero;
|
private SourceLocation _location;
|
||||||
private char? _current;
|
private char? _current;
|
||||||
|
|
||||||
public SeekableTextReader(string source) : this(source.ToCharArray()) { }
|
public SeekableTextReader(string source, string filePath) : this(source.ToCharArray(), filePath) { }
|
||||||
|
|
||||||
public SeekableTextReader(char[] source)
|
public SeekableTextReader(char[] source, string filePath)
|
||||||
{
|
{
|
||||||
if (source == null)
|
if (source == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(source));
|
throw new ArgumentNullException(nameof(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer = new LineTrackingStringBuffer(source);
|
_buffer = new LineTrackingStringBuffer(source, filePath);
|
||||||
UpdateState();
|
UpdateState();
|
||||||
|
|
||||||
|
_location = new SourceLocation(filePath, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceLocation Location => _location;
|
public SourceLocation Location => _location;
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
||||||
@section Baz {
|
@section Baz {
|
||||||
}
|
}
|
||||||
}";
|
}";
|
||||||
var sourceDocument = TestRazorSourceDocument.Create(content);
|
var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null);
|
||||||
var codeDocument = RazorCodeDocument.Create(sourceDocument);
|
var codeDocument = RazorCodeDocument.Create(sourceDocument);
|
||||||
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
|
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
||||||
@section Baz {
|
@section Baz {
|
||||||
}
|
}
|
||||||
}";
|
}";
|
||||||
var sourceDocument = TestRazorSourceDocument.Create(content);
|
var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null);
|
||||||
var codeDocument = RazorCodeDocument.Create(sourceDocument);
|
var codeDocument = RazorCodeDocument.Create(sourceDocument);
|
||||||
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
|
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
|
||||||
var erroredOriginalTree = RazorSyntaxTree.Create(
|
var erroredOriginalTree = RazorSyntaxTree.Create(
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
// Arrange
|
// Arrange
|
||||||
var engine = RazorEngine.Create();
|
var engine = RazorEngine.Create();
|
||||||
|
|
||||||
var document = RazorCodeDocument.Create(TestRazorSourceDocument.Create("@!!!"));
|
var document = RazorCodeDocument.Create(TestRazorSourceDocument.Create("@!!!", fileName: "test.cshtml"));
|
||||||
|
|
||||||
var expected = RazorDiagnostic.Create(new RazorError(
|
var expected = RazorDiagnostic.Create(new RazorError(
|
||||||
LegacyResources.FormatParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS("!"),
|
LegacyResources.FormatParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS("!"),
|
||||||
new SourceLocation(1, 0, 1),
|
new SourceLocation("test.cshtml", 1, 0, 1),
|
||||||
length: 1));
|
length: 1));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -100,11 +100,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
// Arrange
|
// Arrange
|
||||||
var engine = RazorEngine.CreateDesignTime();
|
var engine = RazorEngine.CreateDesignTime();
|
||||||
|
|
||||||
var document = RazorCodeDocument.Create(TestRazorSourceDocument.Create("@{"));
|
var document = RazorCodeDocument.Create(TestRazorSourceDocument.Create("@{", fileName: "test.cshtml"));
|
||||||
|
|
||||||
var expected = RazorDiagnostic.Create(new RazorError(
|
var expected = RazorDiagnostic.Create(new RazorError(
|
||||||
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(LegacyResources.BlockName_Code, "}", "{"),
|
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(LegacyResources.BlockName_Code, "}", "{"),
|
||||||
new SourceLocation(1, 0, 1),
|
new SourceLocation("test.cshtml", 1, 0, 1),
|
||||||
length: 1));
|
length: 1));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
|
||||||
|
|
@ -10,17 +10,17 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CtorInitializesProperties()
|
public void CtorInitializesProperties()
|
||||||
{
|
{
|
||||||
var buffer = new LineTrackingStringBuffer(string.Empty);
|
var buffer = new LineTrackingStringBuffer(string.Empty, "test.cshtml");
|
||||||
Assert.Equal(0, buffer.Length);
|
Assert.Equal(0, buffer.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CharAtCorrectlyReturnsLocation()
|
public void CharAtCorrectlyReturnsLocation()
|
||||||
{
|
{
|
||||||
var buffer = new LineTrackingStringBuffer("foo\rbar\nbaz\r\nbiz");
|
var buffer = new LineTrackingStringBuffer("foo\rbar\nbaz\r\nbiz", "test.cshtml");
|
||||||
LineTrackingStringBuffer.CharacterReference chr = buffer.CharAt(14);
|
var chr = buffer.CharAt(14);
|
||||||
Assert.Equal('i', chr.Character);
|
Assert.Equal('i', chr.Character);
|
||||||
Assert.Equal(new SourceLocation(14, 3, 1), chr.Location);
|
Assert.Equal(new SourceLocation("test.cshtml", 14, 3, 1), chr.Location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,26 +34,36 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
|
|
||||||
internal virtual RazorSyntaxTree ParseDocument(string document, bool designTime = false)
|
internal virtual RazorSyntaxTree ParseDocument(string document, bool designTime = false)
|
||||||
{
|
{
|
||||||
using (var reader = new SeekableTextReader(document))
|
var source = TestRazorSourceDocument.Create(document);
|
||||||
{
|
var reader = new SeekableTextReader(document, filePath: null);
|
||||||
var options = RazorParserOptions.CreateDefaultOptions();
|
|
||||||
options.DesignTimeMode = designTime;
|
|
||||||
|
|
||||||
var parser = new RazorParser(options);
|
var context = new ParserContext(reader, designTime);
|
||||||
|
|
||||||
var tree = parser.Parse(TestRazorSourceDocument.Create(document));
|
var codeParser = new CSharpCodeParser(context);
|
||||||
var defaultDirectivePass = new DefaultDirectiveSyntaxTreePass();
|
var markupParser = new HtmlMarkupParser(context);
|
||||||
tree = defaultDirectivePass.Execute(codeDocument: null, syntaxTree: tree);
|
|
||||||
|
|
||||||
return tree;
|
codeParser.HtmlParser = markupParser;
|
||||||
}
|
markupParser.CodeParser = codeParser;
|
||||||
|
|
||||||
|
markupParser.ParseDocument();
|
||||||
|
|
||||||
|
var root = context.Builder.Build();
|
||||||
|
var diagnostics = context.ErrorSink.Errors?.Select(error => RazorDiagnostic.Create(error));
|
||||||
|
var options = RazorParserOptions.CreateDefaultOptions();
|
||||||
|
options.DesignTimeMode = designTime;
|
||||||
|
|
||||||
|
var tree = RazorSyntaxTree.Create(root, source, diagnostics, options);
|
||||||
|
var defaultDirectivePass = new DefaultDirectiveSyntaxTreePass();
|
||||||
|
tree = defaultDirectivePass.Execute(codeDocument: null, syntaxTree: tree);
|
||||||
|
|
||||||
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual RazorSyntaxTree ParseHtmlBlock(string document, bool designTime = false)
|
internal virtual RazorSyntaxTree ParseHtmlBlock(string document, bool designTime = false)
|
||||||
{
|
{
|
||||||
var source = TestRazorSourceDocument.Create(document);
|
var source = TestRazorSourceDocument.Create(document);
|
||||||
|
|
||||||
using (var reader = new SeekableTextReader(document))
|
using (var reader = new SeekableTextReader(document, filePath: null))
|
||||||
{
|
{
|
||||||
var context = new ParserContext(reader, designTime);
|
var context = new ParserContext(reader, designTime);
|
||||||
|
|
||||||
|
|
@ -86,7 +96,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
{
|
{
|
||||||
var source = TestRazorSourceDocument.Create(document);
|
var source = TestRazorSourceDocument.Create(document);
|
||||||
|
|
||||||
using (var reader = new SeekableTextReader(document))
|
using (var reader = new SeekableTextReader(document, filePath: null))
|
||||||
{
|
{
|
||||||
var context = new ParserContext(reader, designTime);
|
var context = new ParserContext(reader, designTime);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
|
|
||||||
private IEnumerable<ISymbol> Tokenize(string content, bool markup)
|
private IEnumerable<ISymbol> Tokenize(string content, bool markup)
|
||||||
{
|
{
|
||||||
var tokenizer = MakeTokenizer(markup, new SeekableTextReader(content));
|
var tokenizer = MakeTokenizer(markup, new SeekableTextReader(content, filePath: null));
|
||||||
ISymbol symbol;
|
ISymbol symbol;
|
||||||
ISymbol last = null;
|
ISymbol last = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
private class ExposedTokenizer : Tokenizer<CSharpSymbol, CSharpSymbolType>
|
private class ExposedTokenizer : Tokenizer<CSharpSymbol, CSharpSymbolType>
|
||||||
{
|
{
|
||||||
public ExposedTokenizer(string input)
|
public ExposedTokenizer(string input)
|
||||||
: base(new SeekableTextReader(input))
|
: base(new SeekableTextReader(input, filePath: null))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||||
// Arrange
|
// Arrange
|
||||||
var success = true;
|
var success = true;
|
||||||
var output = new StringBuilder();
|
var output = new StringBuilder();
|
||||||
using (var source = new SeekableTextReader(input))
|
using (var source = new SeekableTextReader(input, filePath: null))
|
||||||
{
|
{
|
||||||
var tokenizer = (Tokenizer<TSymbol, TSymbolType>)CreateTokenizer(source);
|
var tokenizer = (Tokenizer<TSymbol, TSymbolType>)CreateTokenizer(source);
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Evolution.Test
|
namespace Microsoft.AspNetCore.Razor.Evolution.Test
|
||||||
|
|
@ -20,5 +22,39 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Test
|
||||||
Assert.NotNull(syntaxTree);
|
Assert.NotNull(syntaxTree);
|
||||||
Assert.Empty(syntaxTree.Diagnostics);
|
Assert.Empty(syntaxTree.Diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Parse_Persists_FilePath()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var filePath = "test.cshtml";
|
||||||
|
var source = TestRazorSourceDocument.Create("@if (true) { @if(false) { <div>@something.</div> } }", fileName: filePath);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var syntaxTree = RazorSyntaxTree.Parse(source);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(syntaxTree.Diagnostics);
|
||||||
|
Assert.NotNull(syntaxTree);
|
||||||
|
|
||||||
|
var spans = new List<SyntaxTreeNode>();
|
||||||
|
GetChildren(syntaxTree.Root);
|
||||||
|
Assert.All(spans, node => Assert.Equal(filePath, node.Start.FilePath));
|
||||||
|
|
||||||
|
void GetChildren(SyntaxTreeNode node)
|
||||||
|
{
|
||||||
|
if (node is Block block)
|
||||||
|
{
|
||||||
|
foreach (var child in block.Children)
|
||||||
|
{
|
||||||
|
GetChildren(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spans.Add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -385,7 +385,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
||||||
@addTagHelper *, TestAssembly
|
@addTagHelper *, TestAssembly
|
||||||
<form>
|
<form>
|
||||||
<input value='Hello' type='text' />";
|
<input value='Hello' type='text' />";
|
||||||
var sourceDocument = TestRazorSourceDocument.Create(content);
|
var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null);
|
||||||
var codeDocument = RazorCodeDocument.Create(sourceDocument);
|
var codeDocument = RazorCodeDocument.Create(sourceDocument);
|
||||||
|
|
||||||
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
|
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
|
||||||
|
|
@ -1334,7 +1334,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
||||||
<form>
|
<form>
|
||||||
<input value='Hello' type='text' />
|
<input value='Hello' type='text' />
|
||||||
</form>";
|
</form>";
|
||||||
var sourceDocument = TestRazorSourceDocument.Create(content);
|
var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null);
|
||||||
return sourceDocument;
|
return sourceDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,14 +52,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RazorSourceDocument Create(string content = "Hello, world!", Encoding encoding = null, bool normalizeNewLines = false)
|
public static RazorSourceDocument Create(string content = "Hello, world!", Encoding encoding = null, bool normalizeNewLines = false, string fileName = "test.cshtml")
|
||||||
{
|
{
|
||||||
if (normalizeNewLines)
|
if (normalizeNewLines)
|
||||||
{
|
{
|
||||||
content = NormalizeNewLines(content);
|
content = NormalizeNewLines(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TestRazorSourceDocument(content, encoding ?? Encoding.UTF8, "test.cshtml");
|
return new TestRazorSourceDocument(content, encoding ?? Encoding.UTF8, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string NormalizeNewLines(string content)
|
private static string NormalizeNewLines(string content)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue