Set file path from RazorSourceDocument in syntax tree

This commit is contained in:
Ajay Bhargav Baaskaran 2017-03-21 17:19:21 -07:00
parent 6fbbd5d148
commit cab6eea663
14 changed files with 91 additions and 40 deletions

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
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);
TSymbol sym;

View File

@ -11,20 +11,23 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
internal class LineTrackingStringBuffer
{
private readonly IList<TextLine> _lines;
private readonly string _filePath;
private TextLine _currentLine;
private TextLine _endLine;
public LineTrackingStringBuffer(string content)
: this(content.ToCharArray())
public LineTrackingStringBuffer(string content, string filePath)
: this(content.ToCharArray(), filePath)
{
}
public LineTrackingStringBuffer(char[] content)
public LineTrackingStringBuffer(char[] content, string filePath)
{
_endLine = new TextLine(0, 0);
_lines = new List<TextLine>() { _endLine };
Append(content);
_filePath = filePath;
}
public int Length
@ -34,7 +37,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
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)
@ -45,7 +48,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
throw new ArgumentOutOfRangeException(nameof(absoluteIndex));
}
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)

View File

@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
var chars = new char[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);

View File

@ -10,20 +10,22 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
{
private readonly LineTrackingStringBuffer _buffer;
private int _position = 0;
private SourceLocation _location = SourceLocation.Zero;
private SourceLocation _location;
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)
{
throw new ArgumentNullException(nameof(source));
}
_buffer = new LineTrackingStringBuffer(source);
_buffer = new LineTrackingStringBuffer(source, filePath);
UpdateState();
_location = new SourceLocation(filePath, 0, 0, 0);
}
public SourceLocation Location => _location;

View File

@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
@section Baz {
}
}";
var sourceDocument = TestRazorSourceDocument.Create(content);
var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
@section Baz {
}
}";
var sourceDocument = TestRazorSourceDocument.Create(content);
var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
var erroredOriginalTree = RazorSyntaxTree.Create(

View File

@ -78,11 +78,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
// Arrange
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(
LegacyResources.FormatParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS("!"),
new SourceLocation(1, 0, 1),
new SourceLocation("test.cshtml", 1, 0, 1),
length: 1));
// Act
@ -100,11 +100,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
// Arrange
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(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(LegacyResources.BlockName_Code, "}", "{"),
new SourceLocation(1, 0, 1),
new SourceLocation("test.cshtml", 1, 0, 1),
length: 1));
// Act

View File

@ -10,17 +10,17 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
[Fact]
public void CtorInitializesProperties()
{
var buffer = new LineTrackingStringBuffer(string.Empty);
var buffer = new LineTrackingStringBuffer(string.Empty, "test.cshtml");
Assert.Equal(0, buffer.Length);
}
[Fact]
public void CharAtCorrectlyReturnsLocation()
{
var buffer = new LineTrackingStringBuffer("foo\rbar\nbaz\r\nbiz");
LineTrackingStringBuffer.CharacterReference chr = buffer.CharAt(14);
var buffer = new LineTrackingStringBuffer("foo\rbar\nbaz\r\nbiz", "test.cshtml");
var chr = buffer.CharAt(14);
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);
}
}
}

View File

@ -34,26 +34,36 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
internal virtual RazorSyntaxTree ParseDocument(string document, bool designTime = false)
{
using (var reader = new SeekableTextReader(document))
{
var options = RazorParserOptions.CreateDefaultOptions();
options.DesignTimeMode = designTime;
var source = TestRazorSourceDocument.Create(document);
var reader = new SeekableTextReader(document, filePath: null);
var parser = new RazorParser(options);
var context = new ParserContext(reader, designTime);
var tree = parser.Parse(TestRazorSourceDocument.Create(document));
var defaultDirectivePass = new DefaultDirectiveSyntaxTreePass();
tree = defaultDirectivePass.Execute(codeDocument: null, syntaxTree: tree);
var codeParser = new CSharpCodeParser(context);
var markupParser = new HtmlMarkupParser(context);
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)
{
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);
@ -86,7 +96,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
{
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);

View File

@ -227,7 +227,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
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 last = null;

View File

@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
private class ExposedTokenizer : Tokenizer<CSharpSymbol, CSharpSymbolType>
{
public ExposedTokenizer(string input)
: base(new SeekableTextReader(input))
: base(new SeekableTextReader(input, filePath: null))
{
}

View File

@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
// Arrange
var success = true;
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 counter = 0;

View File

@ -1,6 +1,8 @@
// 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.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Evolution.Test
@ -20,5 +22,39 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Test
Assert.NotNull(syntaxTree);
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);
}
}
}
}
}

View File

@ -385,7 +385,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
@addTagHelper *, TestAssembly
<form>
<input value='Hello' type='text' />";
var sourceDocument = TestRazorSourceDocument.Create(content);
var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
@ -1334,7 +1334,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
<form>
<input value='Hello' type='text' />
</form>";
var sourceDocument = TestRazorSourceDocument.Create(content);
var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null);
return sourceDocument;
}

View File

@ -52,14 +52,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution
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)
{
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)