From d602f9d770cf186f14446305bf596d04d32f08dd Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Fri, 5 Jan 2018 16:13:15 -0800 Subject: [PATCH] Add relative path to source document Adding this via a properties object that encompasses all of the optional properties. This way if we need to add more items that are optional we can continue to do so without overload explosion. --- .../DefaultRazorSourceLineCollection.cs | 6 +- .../LargeTextSourceDocument.cs | 12 +- .../Properties/Resources.Designer.cs | 14 +++ .../RazorSourceDocument.cs | 111 +++++++++++++++-- .../RazorSourceDocumentProperties.cs | 57 +++++++++ .../Resources.resx | 3 + .../StreamSourceDocument.cs | 18 ++- .../StringSourceDocument.cs | 14 ++- .../TextSnapshotSourceDocument.cs | 2 +- ...tRazorIntermediateNodeLoweringPhaseTest.cs | 14 +-- .../DefaultRazorTagHelperBinderPhaseTest.cs | 16 +-- .../IntegrationTests/BasicIntegrationTest.cs | 4 +- .../LargeTextSourceDocumentTest.cs | 30 +++-- .../RazorSourceDocumentTest.cs | 52 +++++--- .../RazorSyntaxTreeTest.cs | 2 +- .../StreamSourceDocumentTest.cs | 73 +++++++++-- .../StringSourceDocumentTest.cs | 116 +++++++++++------- .../Language/Legacy/ParserTestBase.cs | 6 +- .../Language/TestRazorProjectItem.cs | 4 +- .../Language/TestRazorSourceDocument.cs | 57 +++++++-- 20 files changed, 477 insertions(+), 134 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocumentProperties.cs diff --git a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorSourceLineCollection.cs b/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorSourceLineCollection.cs index 87749a73e6..37b5e156f1 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorSourceLineCollection.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorSourceLineCollection.cs @@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Razor.Language // We have an exact match for the start of a line. Debug.Assert(_lineStarts[index] == position); - return new SourceLocation(_document.FilePath, position, index, characterIndex: 0); + return new SourceLocation(_document.GetFilePathForDisplay(), position, index, characterIndex: 0); } @@ -59,12 +59,12 @@ namespace Microsoft.AspNetCore.Razor.Language if (index == -1) { // There's no preceding line, so it's based on the start of the string - return new SourceLocation(_document.FilePath, position, 0, position); + return new SourceLocation(_document.GetFilePathForDisplay(), position, 0, position); } else { var characterIndex = position - _lineStarts[index]; - return new SourceLocation(_document.FilePath, position, index, characterIndex); + return new SourceLocation(_document.GetFilePathForDisplay(), position, index, characterIndex); } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/LargeTextSourceDocument.cs b/src/Microsoft.AspNetCore.Razor.Language/LargeTextSourceDocument.cs index 20498f66b4..34e72ad984 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/LargeTextSourceDocument.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/LargeTextSourceDocument.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Razor.Language private readonly int _length; private byte[] _checksum; - public LargeTextSourceDocument(StreamReader reader, int chunkMaxLength, Encoding encoding, string fileName) + public LargeTextSourceDocument(StreamReader reader, int chunkMaxLength, Encoding encoding, RazorSourceDocumentProperties properties) { if (reader == null) { @@ -32,9 +32,15 @@ namespace Microsoft.AspNetCore.Razor.Language throw new ArgumentNullException(nameof(encoding)); } + if (properties == null) + { + throw new ArgumentNullException(nameof(properties)); + } + _chunkMaxLength = chunkMaxLength; Encoding = encoding; - FilePath = fileName; + FilePath = properties.FilePath; + RelativePath = properties.RelativePath; ReadChunks(reader, _chunkMaxLength, out _length, out _chunks); _lines = new DefaultRazorSourceLineCollection(this); @@ -59,6 +65,8 @@ namespace Microsoft.AspNetCore.Razor.Language public override RazorSourceLineCollection Lines => _lines; + public override string RelativePath { get; } + public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) { if (destination == null) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs index 0831a5ca2c..4c0119da51 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs @@ -1842,6 +1842,20 @@ namespace Microsoft.AspNetCore.Razor.Language internal static string FormatUnsupportedChecksumAlgorithm(object p0, object p1, object p2, object p3) => string.Format(CultureInfo.CurrentCulture, GetString("UnsupportedChecksumAlgorithm"), p0, p1, p2, p3); + /// + /// The '{0}.{1}' property must not be null. + /// + internal static string PropertyMustNotBeNull + { + get => GetString("PropertyMustNotBeNull"); + } + + /// + /// The '{0}.{1}' property must not be null. + /// + internal static string FormatPropertyMustNotBeNull(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("PropertyMustNotBeNull"), p0, p1); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocument.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocument.cs index b0bc48773f..920113efee 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocument.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocument.cs @@ -18,15 +18,33 @@ namespace Microsoft.AspNetCore.Razor.Language internal static readonly RazorSourceDocument[] EmptyArray = new RazorSourceDocument[0]; /// - /// Encoding of the file that the text was read from. + /// Gets the encoding of the text in the original source document. /// + /// + /// Depending on the method used to create a the encoding may be used to + /// read the file contents, or it may be solely informational. Refer to the documentation on the method + /// used to create the for details. + /// public abstract Encoding Encoding { get; } /// - /// Path of the file the content was read from. + /// Gets the file path of the orginal source document. /// + /// + /// The file path may be either an absolute path or project-relative path. An absolute path is required + /// to generate debuggable assemblies. + /// public abstract string FilePath { get; } + /// + /// Gets the project-relative path to the source file. May be null. + /// + /// + /// The relative path (if provided) is used for display (error messages). The project-relative path may also + /// be used to embed checksums of the original source documents to support runtime recompilation of Razor code. + /// + public virtual string RelativePath => null; + /// /// Gets a character at given position. /// @@ -72,6 +90,15 @@ namespace Microsoft.AspNetCore.Razor.Language return HashAlgorithmName.SHA1.Name; } + /// + /// Gets the file path in a format that should be used for display. + /// + /// The if set, or the . + public virtual string GetFilePathForDisplay() + { + return RelativePath ?? FilePath; + } + /// /// Reads the from the specified . /// @@ -85,7 +112,8 @@ namespace Microsoft.AspNetCore.Razor.Language throw new ArgumentNullException(nameof(stream)); } - return new StreamSourceDocument(stream, encoding: null, fileName: fileName); + var properties = new RazorSourceDocumentProperties(fileName, relativePath: null); + return new StreamSourceDocument(stream, null, properties); } /// @@ -107,7 +135,35 @@ namespace Microsoft.AspNetCore.Razor.Language throw new ArgumentNullException(nameof(encoding)); } - return new StreamSourceDocument(stream, encoding, fileName); + var properties = new RazorSourceDocumentProperties(fileName, relativePath: null); + return new StreamSourceDocument(stream, encoding, properties); + } + + /// + /// Reads the from the specified . + /// + /// The to read from. + /// The to use to read the . + /// Properties to configure the . + /// The . + public static RazorSourceDocument ReadFrom(Stream stream, Encoding encoding, RazorSourceDocumentProperties properties) + { + if (stream == null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (encoding == null) + { + throw new ArgumentNullException(nameof(encoding)); + } + + if (properties == null) + { + throw new ArgumentNullException(nameof(properties)); + } + + return new StreamSourceDocument(stream, encoding, properties); } /// @@ -122,22 +178,25 @@ namespace Microsoft.AspNetCore.Razor.Language throw new ArgumentNullException(nameof(projectItem)); } - var path = projectItem.PhysicalPath; - if (string.IsNullOrEmpty(path)) + // ProjectItem.PhysicalPath is usually an absolute (rooted) path. + var filePath = projectItem.PhysicalPath; + if (string.IsNullOrEmpty(filePath)) { - path = projectItem.FilePath; + // Fall back to the relative path only if necessary. + filePath = projectItem.FilePath; } - using (var inputStream = projectItem.Read()) + using (var stream = projectItem.Read()) { - return ReadFrom(inputStream, path); + // Autodetect the encoding. + return new StreamSourceDocument(stream, null, new RazorSourceDocumentProperties(filePath, projectItem.FilePath)); } } /// /// Creates a from the specified . /// - /// The template content. + /// The source document content. /// The file name of the . /// The . /// Uses @@ -147,7 +206,7 @@ namespace Microsoft.AspNetCore.Razor.Language /// /// Creates a from the specified . /// - /// The template content. + /// The source document content. /// The file name of the . /// The of the file was read from. /// The . @@ -163,7 +222,35 @@ namespace Microsoft.AspNetCore.Razor.Language throw new ArgumentNullException(nameof(encoding)); } - return new StringSourceDocument(content, encoding, fileName); + var properties = new RazorSourceDocumentProperties(fileName, relativePath: null); + return new StringSourceDocument(content, encoding, properties); + } + + /// + /// Creates a from the specified . + /// + /// The source document content. + /// The encoding of the source document. + /// Properties to configure the . + /// The . + public static RazorSourceDocument Create(string content, Encoding encoding, RazorSourceDocumentProperties properties) + { + if (content == null) + { + throw new ArgumentNullException(nameof(content)); + } + + if (encoding == null) + { + throw new ArgumentNullException(nameof(encoding)); + } + + if (properties == null) + { + throw new ArgumentNullException(nameof(properties)); + } + + return new StringSourceDocument(content, encoding, properties); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocumentProperties.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocumentProperties.cs new file mode 100644 index 0000000000..ed48c00181 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocumentProperties.cs @@ -0,0 +1,57 @@ +// 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. + +namespace Microsoft.AspNetCore.Razor.Language +{ + /// + /// Use to configure optional properties for creating a . + /// + public sealed class RazorSourceDocumentProperties + { + /// + /// A with default values. + /// + internal static readonly RazorSourceDocumentProperties Default = new RazorSourceDocumentProperties(); + + /// + /// Creates a new . + /// + public RazorSourceDocumentProperties() + { + } + + /// + /// Creates a new . + /// + /// + /// The path to the source file. Provide an rooted path if possible. May be null. + /// + /// + /// The project-relative path to the source file. May be null. Must be a non-rooted path. + /// + public RazorSourceDocumentProperties(string filePath, string relativePath) + { + // We don't do any magic or validation here since we don't need to do any I/O or interation + // with the file system. We didn't validate anything in 2.0 so we don't want any compat risk. + FilePath = filePath; + RelativePath = relativePath; + } + + /// + /// Gets the path to the source file. May be an absolute or project-relative path. May be null. + /// + /// + /// An absolute path must be provided to generate debuggable assemblies. + /// + public string FilePath { get; } + + /// + /// Gets the project-relative path to the source file. May be null. + /// + /// + /// The relative path (if provided) is used for display (error messages). The project-relative path may also + /// be used to embed checksums of the original source documents to support runtime recompilation of Razor code. + /// + public string RelativePath { get; } + } +} diff --git a/src/Microsoft.AspNetCore.Razor.Language/Resources.resx b/src/Microsoft.AspNetCore.Razor.Language/Resources.resx index 51ebede322..f706f89561 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Resources.resx +++ b/src/Microsoft.AspNetCore.Razor.Language/Resources.resx @@ -530,4 +530,7 @@ Instead, wrap the contents of the block in "{{}}": The hash algorithm '{0}' is not supported for checksum generation. Supported algorithms are: '{1}'. Set '{2}' to '{3}' to suppress automatic checksum generation. + + The '{0}.{1}' property must not be null. + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Language/StreamSourceDocument.cs b/src/Microsoft.AspNetCore.Razor.Language/StreamSourceDocument.cs index 2c0fab062c..1b9d239e7b 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/StreamSourceDocument.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/StreamSourceDocument.cs @@ -15,15 +15,21 @@ namespace Microsoft.AspNetCore.Razor.Language private readonly byte[] _checksum; - public StreamSourceDocument(Stream stream, Encoding encoding, string fileName) + public StreamSourceDocument(Stream stream, Encoding encoding, RazorSourceDocumentProperties properties) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } + if (properties == null) + { + throw new ArgumentNullException(nameof(properties)); + } + + // Notice we don't validate the encoding here. StreamSourceDocument can compute it. _checksum = ComputeChecksum(stream); - _innerSourceDocument = CreateInnerSourceDocument(stream, encoding, fileName); + _innerSourceDocument = CreateInnerSourceDocument(stream, encoding, properties); } public override char this[int position] => _innerSourceDocument[position]; @@ -36,6 +42,8 @@ namespace Microsoft.AspNetCore.Razor.Language public override RazorSourceLineCollection Lines => _innerSourceDocument.Lines; + public override string RelativePath => _innerSourceDocument.RelativePath; + public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) => _innerSourceDocument.CopyTo(sourceIndex, destination, destinationIndex, count); @@ -58,7 +66,7 @@ namespace Microsoft.AspNetCore.Razor.Language } } - private static RazorSourceDocument CreateInnerSourceDocument(Stream stream, Encoding encoding, string fileName) + private static RazorSourceDocument CreateInnerSourceDocument(Stream stream, Encoding encoding, RazorSourceDocumentProperties properties) { var streamLength = (int)stream.Length; var content = string.Empty; @@ -98,14 +106,14 @@ namespace Microsoft.AspNetCore.Razor.Language reader, LargeObjectHeapLimitInChars, contentEncoding, - fileName); + properties); } content = reader.ReadToEnd(); } } - return new StringSourceDocument(content, contentEncoding, fileName); + return new StringSourceDocument(content, contentEncoding, properties); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/StringSourceDocument.cs b/src/Microsoft.AspNetCore.Razor.Language/StringSourceDocument.cs index 5f528024c2..a89ac1b25a 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/StringSourceDocument.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/StringSourceDocument.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Razor.Language private readonly RazorSourceLineCollection _lines; private byte[] _checksum; - public StringSourceDocument(string content, Encoding encoding, string filePath) + public StringSourceDocument(string content, Encoding encoding, RazorSourceDocumentProperties properties) { if (content == null) { @@ -25,9 +25,15 @@ namespace Microsoft.AspNetCore.Razor.Language throw new ArgumentNullException(nameof(encoding)); } + if (properties == null) + { + throw new ArgumentNullException(nameof(properties)); + } + _content = content; Encoding = encoding; - FilePath = filePath; + FilePath = properties.FilePath; + RelativePath = properties.RelativePath; _lines = new DefaultRazorSourceLineCollection(this); } @@ -37,11 +43,13 @@ namespace Microsoft.AspNetCore.Razor.Language public override Encoding Encoding { get; } public override string FilePath { get; } - + public override int Length => _content.Length; public override RazorSourceLineCollection Lines => _lines; + public override string RelativePath { get; } + public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) { if (destination == null) diff --git a/src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotSourceDocument.cs b/src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotSourceDocument.cs index e965b7ae2e..ffe6c2f212 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotSourceDocument.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotSourceDocument.cs @@ -40,7 +40,7 @@ namespace Microsoft.VisualStudio.Editor.Razor public override RazorSourceLineCollection Lines => _lines; public override string FilePath { get; } - + public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) { if (destination == null) diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorIntermediateNodeLoweringPhaseTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorIntermediateNodeLoweringPhaseTest.cs index 1288b1b127..bb53e69947 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorIntermediateNodeLoweringPhaseTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorIntermediateNodeLoweringPhaseTest.cs @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Razor.Language b.AddDirective(directive); }); var options = RazorParserOptions.Create(builder => builder.Directives.Add(directive)); - var importSource = TestRazorSourceDocument.Create("@custom \"hello\"", fileName: "import.cshtml"); + var importSource = TestRazorSourceDocument.Create("@custom \"hello\"", filePath: "import.cshtml"); var codeDocument = TestRazorCodeDocument.Create("

NonDirective

"); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source, options)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSource, options) }); @@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Razor.Language b.AddDirective(directive); }); var options = RazorParserOptions.Create(builder => builder.Directives.Add(directive)); - var importSource = TestRazorSourceDocument.Create("@custom \"hello\"", fileName: "import.cshtml"); + var importSource = TestRazorSourceDocument.Create("@custom \"hello\"", filePath: "import.cshtml"); var codeDocument = TestRazorCodeDocument.Create("@custom \"world\""); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source, options)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSource, options) }); @@ -100,8 +100,8 @@ namespace Microsoft.AspNetCore.Razor.Language b.AddDirective(directive); }); var options = RazorParserOptions.Create(builder => builder.Directives.Add(directive)); - var importSource1 = TestRazorSourceDocument.Create("@custom \"hello\"", fileName: "import1.cshtml"); - var importSource2 = TestRazorSourceDocument.Create("@custom \"world\"", fileName: "import2.cshtml"); + var importSource1 = TestRazorSourceDocument.Create("@custom \"hello\"", filePath: "import1.cshtml"); + var importSource2 = TestRazorSourceDocument.Create("@custom \"world\"", filePath: "import2.cshtml"); var codeDocument = TestRazorCodeDocument.Create("

NonDirective

"); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source, options)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSource1, options), RazorSyntaxTree.Parse(importSource2, options) }); @@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.Razor.Language var importSource = TestRazorSourceDocument.Create( @"@code ""code block"" { } @razor ""razor block"" { }", - fileName: "testImports.cshtml"); + filePath: "testImports.cshtml"); var codeDocument = TestRazorCodeDocument.Create("

NonDirective

"); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source, options)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSource, options) }); @@ -166,7 +166,7 @@ namespace Microsoft.AspNetCore.Razor.Language b.AddDirective(directive); }); var options = RazorParserOptions.Create(builder => builder.Directives.Add(directive)); - var importSource = TestRazorSourceDocument.Create("@custom { }", fileName: "import.cshtml"); + var importSource = TestRazorSourceDocument.Create("@custom { }", filePath: "import.cshtml"); var codeDocument = TestRazorCodeDocument.Create("

NonDirective

"); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source, options)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSource, options) }); @@ -196,7 +196,7 @@ namespace Microsoft.AspNetCore.Razor.Language b.AddDirective(directive); }); var options = RazorParserOptions.Create(builder => builder.Directives.Add(directive)); - var importSource = TestRazorSourceDocument.Create("@custom { }", fileName: "import.cshtml"); + var importSource = TestRazorSourceDocument.Create("@custom { }", filePath: "import.cshtml"); var codeDocument = TestRazorCodeDocument.Create("

NonDirective

"); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source, options)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSource, options) }); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs index eaead88382..d4fd3c1910 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs @@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Razor.Language var content = @" @addTagHelper """; - var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null); + var sourceDocument = TestRazorSourceDocument.Create(content, filePath: null); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); @@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.Razor.Language var content = @" @removeTagHelper """; - var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null); + var sourceDocument = TestRazorSourceDocument.Create(content, filePath: null); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); @@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.Razor.Language var content = @" @tagHelperPrefix """; - var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null); + var sourceDocument = TestRazorSourceDocument.Create(content, filePath: null); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); @@ -413,7 +413,7 @@ namespace Microsoft.AspNetCore.Razor.Language @addTagHelper *, TestAssembly
"; - var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null); + var sourceDocument = TestRazorSourceDocument.Create(content, filePath: null); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); @@ -540,7 +540,7 @@ namespace Microsoft.AspNetCore.Razor.Language string expectedPrefix) { // Arrange - var sourceDocument = TestRazorSourceDocument.Create(source, fileName: "TestFile"); + var sourceDocument = TestRazorSourceDocument.Create(source, filePath: "TestFile"); var parser = new RazorParser(); var syntaxTree = parser.Parse(sourceDocument); var visitor = new DefaultRazorTagHelperBinderPhase.DirectiveVisitor(tagHelpers: new List()); @@ -706,7 +706,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var expected = (TagHelperDescriptor[])expectedDescriptors; - var sourceDocument = TestRazorSourceDocument.Create(source, fileName: "TestFile"); + var sourceDocument = TestRazorSourceDocument.Create(source, filePath: "TestFile"); var parser = new RazorParser(); var syntaxTree = parser.Parse(sourceDocument); var visitor = new DefaultRazorTagHelperBinderPhase.DirectiveVisitor((TagHelperDescriptor[])tagHelpers); @@ -850,7 +850,7 @@ namespace Microsoft.AspNetCore.Razor.Language object tagHelpers) { // Arrange - var sourceDocument = TestRazorSourceDocument.Create(source, fileName: "TestFile"); + var sourceDocument = TestRazorSourceDocument.Create(source, filePath: "TestFile"); var parser = new RazorParser(); var syntaxTree = parser.Parse(sourceDocument); var visitor = new DefaultRazorTagHelperBinderPhase.DirectiveVisitor((TagHelperDescriptor[])tagHelpers); @@ -885,7 +885,7 @@ namespace Microsoft.AspNetCore.Razor.Language "; - var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null); + var sourceDocument = TestRazorSourceDocument.Create(content, filePath: null); return sourceDocument; } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/IntegrationTests/BasicIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/IntegrationTests/BasicIntegrationTest.cs index 7f88e16eca..56c22c8105 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/IntegrationTests/BasicIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/IntegrationTests/BasicIntegrationTest.cs @@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests // Arrange var engine = RazorEngine.Create(); - var document = RazorCodeDocument.Create(TestRazorSourceDocument.Create("@!!!", fileName: "test.cshtml")); + var document = RazorCodeDocument.Create(TestRazorSourceDocument.Create("@!!!", filePath: "test.cshtml")); var expected = RazorDiagnosticFactory.CreateParsing_UnexpectedCharacterAtStartOfCodeBlock( new SourceSpan(new SourceLocation("test.cshtml", 1, 0, 1), contentLength: 1), @@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests // Arrange var engine = RazorEngine.CreateDesignTime(); - var document = RazorCodeDocument.Create(TestRazorSourceDocument.Create("@{", fileName: "test.cshtml")); + var document = RazorCodeDocument.Create(TestRazorSourceDocument.Create("@{", filePath: "test.cshtml")); var expected = RazorDiagnosticFactory.CreateParsing_ExpectedEndOfBlockBeforeEOF( new SourceSpan(new SourceLocation("test.cshtml", 1, 0, 1), contentLength: 1), Resources.BlockName_Code, "}", "{"); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/LargeTextSourceDocumentTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/LargeTextSourceDocumentTest.cs index bf61974524..fb47799b23 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/LargeTextSourceDocumentTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/LargeTextSourceDocumentTest.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var contentString = "Hello World"; var stream = TestRazorSourceDocument.CreateStreamContent(contentString); var reader = new StreamReader(stream, detectEncodingFromByteOrderMarks: true); - var document = new LargeTextSourceDocument(reader, 5, Encoding.UTF8, "file.cshtml"); + var document = new LargeTextSourceDocument(reader, 5, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var firstChecksum = document.GetChecksum(); @@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var contentString = "Hello World"; var stream = TestRazorSourceDocument.CreateStreamContent(contentString); var reader = new StreamReader(stream, detectEncodingFromByteOrderMarks: true); - var document = new LargeTextSourceDocument(reader, 5, Encoding.UTF8, "file.cshtml"); + var document = new LargeTextSourceDocument(reader, 5, Encoding.UTF8, RazorSourceDocumentProperties.Default); var expectedChecksum = new byte[] { 10, 77, 85, 168, 215, 120, 229, 2, 47, 171, 112, 25, 119, 197, 216, 64, 187, 196, 134, 208 }; // Act @@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var contentString = "Hello World"; var stream = TestRazorSourceDocument.CreateStreamContent(contentString, Encoding.UTF32); var reader = new StreamReader(stream, detectEncodingFromByteOrderMarks: true); - var document = new LargeTextSourceDocument(reader, 5, Encoding.UTF32, "file.cshtml"); + var document = new LargeTextSourceDocument(reader, 5, Encoding.UTF32, RazorSourceDocumentProperties.Default); var expectedChecksum = new byte[] { 108, 172, 130, 171, 42, 19, 155, 176, 211, 80, 224, 121, 169, 133, 25, 134, 48, 228, 199, 141 }; // Act @@ -81,7 +81,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var stream = TestRazorSourceDocument.CreateStreamContent(new string(content)); var reader = new StreamReader(stream, true); - var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, "file.cshtml"); + var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var output = new char[contentLength]; @@ -106,12 +106,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var reader = new StreamReader(stream, true); // Act - var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, filePath); + var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: filePath, relativePath: null)); // Assert Assert.Equal(filePath, document.FilePath); } + [Theory] + [InlineData("test.cshtml")] + [InlineData(null)] + public void RelativePath(string relativePath) + { + // Arrange + var stream = TestRazorSourceDocument.CreateStreamContent("abc"); + var reader = new StreamReader(stream, true); + + // Act + var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: null, relativePath: relativePath)); + + // Assert + Assert.Equal(relativePath, document.RelativePath); + } + [Fact] public void Lines() { @@ -120,7 +136,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var reader = new StreamReader(stream, true); // Act - var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, "file.cshtml"); + var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Assert Assert.Equal(3, document.Lines.Count); @@ -142,7 +158,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var stream = TestRazorSourceDocument.CreateStreamContent("abcdefghijklmnopqrstuvwxyz"); var reader = new StreamReader(stream, true); - var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, "file.cshtml"); + var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var destination = new char[1000]; diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSourceDocumentTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSourceDocumentTest.cs index 7288f8a43c..18d68a8d44 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSourceDocumentTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSourceDocumentTest.cs @@ -37,6 +37,22 @@ namespace Microsoft.AspNetCore.Razor.Language Assert.Same(Encoding.UTF32, Assert.IsType(document).Encoding); } + [Fact] + public void ReadFrom_WithProperties() + { + // Arrange + var content = TestRazorSourceDocument.CreateStreamContent(encoding: Encoding.UTF32); + var properties = new RazorSourceDocumentProperties("c:\\myapp\\filePath.cshtml", "filePath.cshtml"); + + // Act + var document = RazorSourceDocument.ReadFrom(content, Encoding.UTF32, properties); + + // Assert + Assert.Equal("c:\\myapp\\filePath.cshtml", document.FilePath); + Assert.Equal("filePath.cshtml", document.RelativePath); + Assert.Same(Encoding.UTF32, Assert.IsType(document).Encoding); + } + [Fact] public void ReadFrom_EmptyStream_WithEncoding() { @@ -51,31 +67,18 @@ namespace Microsoft.AspNetCore.Razor.Language Assert.Same(Encoding.UTF32, Assert.IsType(document).Encoding); } - [Fact] - public void ReadFrom_UsesProjectItemPhysicalPath() - { - // Arrange - var projectItem = new TestRazorProjectItem("/test-path", "some-physical-path"); - - // Act - var document = RazorSourceDocument.ReadFrom(projectItem); - - // Assert - Assert.Equal(projectItem.PhysicalPath, document.FilePath); - Assert.Equal(projectItem.Content, ReadContent(document)); - } - [Fact] public void ReadFrom_ProjectItem() { // Arrange - var projectItem = new TestRazorProjectItem("/test-path"); + var projectItem = new TestRazorProjectItem("filePath.cshtml", "c:\\myapp\\filePath.cshtml", "c:\\myapp\\"); // Act var document = RazorSourceDocument.ReadFrom(projectItem); // Assert - Assert.Equal(projectItem.FilePath, document.FilePath); + Assert.Equal("c:\\myapp\\filePath.cshtml", document.FilePath); + Assert.Equal("filePath.cshtml", document.RelativePath); Assert.Equal(projectItem.Content, ReadContent(document)); } @@ -112,6 +115,23 @@ namespace Microsoft.AspNetCore.Razor.Language Assert.Same(encoding, document.Encoding); } + [Fact] + public void Create_WithProperties() + { + // Arrange + var content = "Hello world"; + var properties = new RazorSourceDocumentProperties("c:\\myapp\\filePath.cshtml", "filePath.cshtml"); + + // Act + var document = RazorSourceDocument.Create(content, Encoding.UTF32, properties); + + // Assert + Assert.Equal("c:\\myapp\\filePath.cshtml", document.FilePath); + Assert.Equal("filePath.cshtml", document.RelativePath); + Assert.Equal(content, ReadContent(document)); + Assert.Same(Encoding.UTF32, Assert.IsType(document).Encoding); + } + private static string ReadContent(RazorSourceDocument razorSourceDocument) { var buffer = new char[razorSourceDocument.Length]; diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSyntaxTreeTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSyntaxTreeTest.cs index 54466376cd..09b36651ce 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSyntaxTreeTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSyntaxTreeTest.cs @@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test { // Arrange var filePath = "test.cshtml"; - var source = TestRazorSourceDocument.Create("@if (true) { @if(false) {
@something.
} }", fileName: filePath); + var source = TestRazorSourceDocument.Create("@if (true) { @if(false) {
@something.
} }", filePath: filePath); // Act var syntaxTree = RazorSyntaxTree.Parse(source); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/StreamSourceDocumentTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/StreamSourceDocumentTest.cs index 84163a1c57..f377450320 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/StreamSourceDocumentTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/StreamSourceDocumentTest.cs @@ -10,13 +10,69 @@ namespace Microsoft.AspNetCore.Razor.Language { public class StreamSourceDocumentTest { + [Fact] + public void FilePath() + { + // Arrange + var content = "Hello World!"; + var stream = CreateBOMStream(content, Encoding.UTF8); + + // Act + var document = new StreamSourceDocument(stream, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: "file.cshtml", relativePath: null)); + + // Assert + Assert.Equal("file.cshtml", document.FilePath); + } + + [Fact] + public void FilePath_Null() + { + // Arrange + var content = "Hello World!"; + var stream = CreateBOMStream(content, Encoding.UTF8); + + // Act + var document = new StreamSourceDocument(stream, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: null, relativePath: null)); + + // Assert + Assert.Null(document.FilePath); + } + + [Fact] + public void RelativePath() + { + // Arrange + var content = "Hello World!"; + var stream = CreateBOMStream(content, Encoding.UTF8); + + // Act + var document = new StreamSourceDocument(stream, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: null, relativePath: "file.cshtml")); + + // Assert + Assert.Equal("file.cshtml", document.RelativePath); + } + + [Fact] + public void RelativePath_Null() + { + // Arrange + var content = "Hello World!"; + var stream = CreateBOMStream(content, Encoding.UTF8); + + // Act + var document = new StreamSourceDocument(stream, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: null, relativePath: null)); + + // Assert + Assert.Null(document.RelativePath); + } + [Fact] public void GetChecksum_ReturnsCopiedChecksum() { // Arrange var content = "Hello World!"; var stream = CreateBOMStream(content, Encoding.UTF8); - var document = new StreamSourceDocument(stream, Encoding.UTF8, "file.cshtml"); + var document = new StreamSourceDocument(stream, null, RazorSourceDocumentProperties.Default); // Act var firstChecksum = document.GetChecksum(); @@ -33,7 +89,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello World!"; var stream = CreateBOMStream(content, Encoding.UTF8); - var document = new StreamSourceDocument(stream, Encoding.UTF8, "file.cshtml"); + var document = new StreamSourceDocument(stream, Encoding.UTF8, RazorSourceDocumentProperties.Default); var expectedChecksum = new byte[] { 70, 180, 84, 105, 70, 79, 152, 31, 71, 157, 46, 159, 50, 83, 1, 243, 222, 48, 90, 18 }; // Act @@ -49,7 +105,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello World!"; var stream = CreateBOMStream(content, Encoding.UTF32); - var document = new StreamSourceDocument(stream, encoding: null, fileName: "file.cshtml"); + var document = new StreamSourceDocument(stream, null, RazorSourceDocumentProperties.Default); var expectedChecksum = new byte[] { 159, 154, 109, 89, 250, 163, 165, 108, 2, 112, 34, 4, 247, 161, 82, 168, 77, 213, 107, 71 }; // Act @@ -66,11 +122,10 @@ namespace Microsoft.AspNetCore.Razor.Language var content = TestRazorSourceDocument.CreateStreamContent(encoding: Encoding.UTF32); // Act - var document = new StreamSourceDocument(content, encoding: null, fileName: "file.cshtml"); + var document = new StreamSourceDocument(content, null, RazorSourceDocumentProperties.Default); // Assert Assert.IsType(document); - Assert.Equal("file.cshtml", document.FilePath); Assert.Equal(Encoding.UTF32, document.Encoding); } @@ -81,11 +136,10 @@ namespace Microsoft.AspNetCore.Razor.Language var content = TestRazorSourceDocument.CreateStreamContent(content: string.Empty, encoding: Encoding.UTF32); // Act - var document = new StreamSourceDocument(content, encoding: null, fileName: "file.cshtml"); + var document = new StreamSourceDocument(content, null, RazorSourceDocumentProperties.Default); // Assert Assert.IsType(document); - Assert.Equal("file.cshtml", document.FilePath); Assert.Equal(Encoding.UTF32, document.Encoding); } @@ -98,7 +152,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Act & Assert var exception = Assert.Throws( - () => new StreamSourceDocument(content, Encoding.UTF8, "file.cshtml")); + () => new StreamSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default)); Assert.Equal(expectedMessage, exception.Message); } @@ -115,12 +169,11 @@ namespace Microsoft.AspNetCore.Razor.Language var stream = TestRazorSourceDocument.CreateStreamContent(content); // Act - var document = new StreamSourceDocument(stream, encoding: null, fileName: "file.cshtml"); + var document = new StreamSourceDocument(stream, null, RazorSourceDocumentProperties.Default); // Assert var streamDocument = Assert.IsType(document); Assert.IsType(streamDocument._innerSourceDocument); - Assert.Equal("file.cshtml", document.FilePath); Assert.Same(Encoding.UTF8, document.Encoding); Assert.Equal(content, ReadContent(document)); } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/StringSourceDocumentTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/StringSourceDocumentTest.cs index 16acfc8be9..8306d2bf80 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/StringSourceDocumentTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/StringSourceDocumentTest.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "Hello World!"; - var document = new StringSourceDocument(content, Encoding.UTF8, "file.cshtml"); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var firstChecksum = document.GetChecksum(); @@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "Hello World!"; - var document = new StringSourceDocument(content, Encoding.UTF8, "file.cshtml"); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); var expectedChecksum = new byte[] { 46, 247, 189, 230, 8, 206, 84, 4, 233, 125, 95, 4, 47, 149, 248, 159, 28, 35, 40, 113 }; // Act @@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "Hello World!"; - var document = new StringSourceDocument(content, Encoding.UTF32, "file.cshtml"); + var document = new StringSourceDocument(content, Encoding.UTF32, RazorSourceDocumentProperties.Default); var expectedChecksum = new byte[] { 8, 149, 159, 15, 242, 255, 115, 227, 219, 78, 61, 53, 127, 239, 77, 239, 215, 140, 248, 44 }; // Act @@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var expectedContent = "Hello, World!"; var indexerBuffer = new char[expectedContent.Length]; - var document = new StringSourceDocument(expectedContent, Encoding.UTF8, filePath: "file.cshtml"); + var document = new StringSourceDocument(expectedContent, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act for (var i = 0; i < document.Length; i++) @@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var expectedContent = "Hello, World!"; - var document = new StringSourceDocument(expectedContent, Encoding.UTF8, filePath: "file.cshtml"); + var document = new StringSourceDocument(expectedContent, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act & Assert Assert.Equal(expectedContent.Length, document.Length); @@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Razor.Language var content = "Hello, World!"; // Act - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: "file.cshtml"); + var document = new StringSourceDocument(content, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: "file.cshtml", relativePath: null)); // Assert Assert.Equal("file.cshtml", document.FilePath); @@ -104,18 +104,44 @@ namespace Microsoft.AspNetCore.Razor.Language var content = "Hello, World!"; // Act - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: null, relativePath: null)); // Assert Assert.Null(document.FilePath); } + [Fact] + public void RelativePath() + { + // Arrange + var content = "Hello, World!"; + + // Act + var document = new StringSourceDocument(content, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: null, relativePath: "file.cshtml")); + + // Assert + Assert.Equal("file.cshtml", document.RelativePath); + } + + [Fact] + public void RelativePath_Null() + { + // Arrange + var content = "Hello, World!"; + + // Act + var document = new StringSourceDocument(content, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: null, relativePath: null)); + + // Assert + Assert.Null(document.RelativePath); + } + [Fact] public void CopyTo_PartialCopyFromStart() { // Arrange var content = "Hello, World!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); var expectedContent = "Hello"; var charBuffer = new char[expectedContent.Length]; @@ -132,7 +158,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "Hello, World!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); var expectedContent = "$Hello"; var charBuffer = new char[expectedContent.Length]; charBuffer[0] = '$'; @@ -150,7 +176,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "Hello, World!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); var expectedContent = "World"; var charBuffer = new char[expectedContent.Length]; @@ -162,28 +188,12 @@ namespace Microsoft.AspNetCore.Razor.Language Assert.Equal(expectedContent, copiedContent); } - [Fact] - public void CopyTo_WithEncoding() - { - // Arrange - var content = "Hi"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); - var charBuffer = new char[2]; - - // Act - document.CopyTo(0, charBuffer, 0, 2); - - // Assert - var copiedContent = new string(charBuffer); - Assert.Equal("Hi", copiedContent); - } - [Fact] public void CopyTo_CanCopyMultipleTimes() { // Arrange var content = "Hi"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act & Assert // @@ -202,7 +212,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = string.Empty; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = document.Lines.Count; @@ -216,7 +226,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = string.Empty; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = document.Lines.GetLineLength(0); @@ -230,7 +240,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "hello\n"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = document.Lines.GetLineLength(0); @@ -244,7 +254,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "hello\r\n"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = document.Lines.GetLineLength(0); @@ -263,7 +273,7 @@ namespace Microsoft.AspNetCore.Razor.Language .Append("jumps over the lazy dog.") .ToString(); - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = GetAllSourceMappings(document); @@ -278,7 +288,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\r\nWorld!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = GetAllSourceMappings(document); @@ -293,7 +303,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\rWorld!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = GetAllSourceMappings(document); @@ -309,7 +319,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\rBig\r\nWorld!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = GetAllSourceMappings(document); @@ -324,7 +334,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nWorld!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = GetAllSourceMappings(document); @@ -339,7 +349,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\u0085World!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = GetAllSourceMappings(document); @@ -354,7 +364,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\u2028World!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = GetAllSourceMappings(document); @@ -369,7 +379,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\u2029World!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = GetAllSourceMappings(document); @@ -384,7 +394,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello, World!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: "Hi.cshtml"); + var document = new StringSourceDocument(content, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: "Hi.cshtml", relativePath: null)); // Act var actual = document.Lines.GetLocation(1); @@ -394,6 +404,22 @@ namespace Microsoft.AspNetCore.Razor.Language Assert.Equal(1, actual.AbsoluteIndex); } + [Fact] + public void Lines_GetLocation_PrefersRelativePath() + { + // Arrange + var content = "Hello, World!"; + + var document = new StringSourceDocument(content, Encoding.UTF8, new RazorSourceDocumentProperties(filePath: "Hi.cshtml", relativePath: "Bye.cshtml")); + + // Act + var actual = document.Lines.GetLocation(1); + + // Assert + Assert.Equal("Bye.cshtml", actual.FilePath); + Assert.Equal(1, actual.AbsoluteIndex); + } + // Beginnings of lines are special because the BinarySearch in the implementation // will succeed. It's a different code path. [Fact] @@ -402,7 +428,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nBig\r\nWorld!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = document.Lines.GetLocation(0); @@ -418,7 +444,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nBig\r\nWorld!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = document.Lines.GetLocation(5); @@ -434,7 +460,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nBig\r\nWorld!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = document.Lines.GetLocation(7); @@ -450,7 +476,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nBig\r\nWorld!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = document.Lines.GetLocation(11); @@ -466,7 +492,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nBig\r\nWorld!"; - var document = new StringSourceDocument(content, Encoding.UTF8, filePath: null); + var document = new StringSourceDocument(content, Encoding.UTF8, RazorSourceDocumentProperties.Default); // Act var actual = document.Lines.GetLocation(16); diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs index 319dd201c1..1f9ec8a407 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs @@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy { directives = directives ?? Array.Empty(); - var source = TestRazorSourceDocument.Create(document, fileName: null); + var source = TestRazorSourceDocument.Create(document, filePath: null); var options = CreateParserOptions(directives, designTime); var context = new ParserContext(source, options); @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy { directives = directives ?? Array.Empty(); - var source = TestRazorSourceDocument.Create(document, fileName: null); + var source = TestRazorSourceDocument.Create(document, filePath: null); var options = CreateParserOptions(directives, designTime); var context = new ParserContext(source, options); @@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy { directives = directives ?? Array.Empty(); - var source = TestRazorSourceDocument.Create(document, fileName: null); + var source = TestRazorSourceDocument.Create(document, filePath: null); var options = CreateParserOptions(directives, designTime); var context = new ParserContext(source, options); diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorProjectItem.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorProjectItem.cs index 3e0bd1e44f..52c5f77825 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorProjectItem.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorProjectItem.cs @@ -9,11 +9,11 @@ namespace Microsoft.AspNetCore.Razor.Language public class TestRazorProjectItem : RazorProjectItem { public TestRazorProjectItem( - string path, + string filePath, string physicalPath = null, string basePath = "/") { - FilePath = path; + FilePath = filePath; PhysicalPath = physicalPath; BasePath = basePath; } diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorSourceDocument.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorSourceDocument.cs index 57a5fb196e..e731b03594 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorSourceDocument.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorSourceDocument.cs @@ -11,12 +11,35 @@ namespace Microsoft.AspNetCore.Razor.Language { public static class TestRazorSourceDocument { - public static RazorSourceDocument CreateResource(string path, Type type, Encoding encoding = null, bool normalizeNewLines = false) + public static RazorSourceDocument CreateResource(string resourcePath, Type type, Encoding encoding = null, bool normalizeNewLines = false) { - return CreateResource(path, type.GetTypeInfo().Assembly, encoding, normalizeNewLines); + return CreateResource(resourcePath, type.GetTypeInfo().Assembly, encoding, normalizeNewLines); } - public static RazorSourceDocument CreateResource(string path, Assembly assembly, Encoding encoding = null, bool normalizeNewLines = false) + public static RazorSourceDocument CreateResource(string resourcePath, Assembly assembly, Encoding encoding = null, bool normalizeNewLines = false) + { + var file = TestFile.Create(resourcePath, assembly); + + using (var input = file.OpenRead()) + using (var reader = new StreamReader(input)) + { + var content = reader.ReadToEnd(); + if (normalizeNewLines) + { + content = NormalizeNewLines(content); + } + + var properties = new RazorSourceDocumentProperties(resourcePath, resourcePath); + return new StringSourceDocument(content, encoding ?? Encoding.UTF8, properties); + } + } + + public static RazorSourceDocument CreateResource( + string path, + Assembly assembly, + Encoding encoding, + RazorSourceDocumentProperties properties, + bool normalizeNewLines = false) { var file = TestFile.Create(path, assembly); @@ -28,8 +51,8 @@ namespace Microsoft.AspNetCore.Razor.Language { content = NormalizeNewLines(content); } - - return new StringSourceDocument(content, encoding ?? Encoding.UTF8, path); + + return new StringSourceDocument(content, encoding ?? Encoding.UTF8, properties); } } @@ -52,14 +75,34 @@ namespace Microsoft.AspNetCore.Razor.Language return stream; } - public static RazorSourceDocument Create(string content = "Hello, world!", Encoding encoding = null, bool normalizeNewLines = false, string fileName = "test.cshtml") + public static RazorSourceDocument Create( + string content = "Hello, world!", + Encoding encoding = null, + bool normalizeNewLines = false, + string filePath = "test.cshtml", + string relativePath = "test.cshtml") { if (normalizeNewLines) { content = NormalizeNewLines(content); } - return new StringSourceDocument(content, encoding ?? Encoding.UTF8, fileName); + var properties = new RazorSourceDocumentProperties(filePath, relativePath); + return new StringSourceDocument(content, encoding ?? Encoding.UTF8, properties); + } + + public static RazorSourceDocument Create( + string content, + RazorSourceDocumentProperties properties, + Encoding encoding = null, + bool normalizeNewLines = false) + { + if (normalizeNewLines) + { + content = NormalizeNewLines(content); + } + + return new StringSourceDocument(content, encoding ?? Encoding.UTF8, properties); } private static string NormalizeNewLines(string content)