Generate an expression to create line mappings for ModelChunk directives
This commit is contained in:
parent
89f58aa49f
commit
ff4100e292
|
|
@ -67,6 +67,29 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
return csharpCodeVisitor;
|
||||
}
|
||||
|
||||
protected override CSharpDesignTimeCodeVisitor CreateCSharpDesignTimeCodeVisitor(
|
||||
CSharpCodeVisitor csharpCodeVisitor,
|
||||
CSharpCodeWriter writer,
|
||||
CodeGeneratorContext context)
|
||||
{
|
||||
if (csharpCodeVisitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(csharpCodeVisitor));
|
||||
}
|
||||
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(writer));
|
||||
}
|
||||
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
return new MvcCSharpDesignTimeCodeVisitor(csharpCodeVisitor, writer, context);
|
||||
}
|
||||
|
||||
protected override void BuildConstructor(CSharpCodeWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
// 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.Diagnostics;
|
||||
using Microsoft.AspNet.Razor.Chunks;
|
||||
using Microsoft.AspNet.Razor.CodeGenerators;
|
||||
using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public class MvcCSharpDesignTimeCodeVisitor : CSharpDesignTimeCodeVisitor
|
||||
{
|
||||
private const string ModelVariable = "__modelHelper";
|
||||
private ModelChunk _modelChunk;
|
||||
|
||||
public MvcCSharpDesignTimeCodeVisitor(
|
||||
CSharpCodeVisitor csharpCodeVisitor,
|
||||
CSharpCodeWriter writer,
|
||||
CodeGeneratorContext context)
|
||||
: base(csharpCodeVisitor, writer, context)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void AcceptTreeCore(ChunkTree tree)
|
||||
{
|
||||
base.AcceptTreeCore(tree);
|
||||
|
||||
if (_modelChunk != null)
|
||||
{
|
||||
WriteModelChunkLineMapping();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Accept(Chunk chunk)
|
||||
{
|
||||
if (chunk is ModelChunk)
|
||||
{
|
||||
Visit((ModelChunk)chunk);
|
||||
}
|
||||
|
||||
base.Accept(chunk);
|
||||
}
|
||||
|
||||
private void Visit(ModelChunk chunk)
|
||||
{
|
||||
Debug.Assert(chunk != null);
|
||||
_modelChunk = chunk;
|
||||
}
|
||||
|
||||
private void WriteModelChunkLineMapping()
|
||||
{
|
||||
Debug.Assert(Context.Host.DesignTimeMode);
|
||||
|
||||
using (var lineMappingWriter =
|
||||
Writer.BuildLineMapping(_modelChunk.Start, _modelChunk.ModelType.Length, Context.SourceFile))
|
||||
{
|
||||
// var __modelHelper = default(MyModel);
|
||||
Writer.Write("var ")
|
||||
.Write(ModelVariable)
|
||||
.Write(" = default(");
|
||||
|
||||
lineMappingWriter.MarkLineMappingStart();
|
||||
Writer.Write(_modelChunk.ModelType);
|
||||
lineMappingWriter.MarkLineMappingEnd();
|
||||
|
||||
Writer.WriteLine(");");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,10 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
new SetBaseTypeChunk
|
||||
{
|
||||
// Microsoft.Aspnet.Mvc.Razor.RazorPage<TModel>
|
||||
TypeName = BaseType + ChunkHelper.TModelToken
|
||||
TypeName = BaseType + ChunkHelper.TModelToken,
|
||||
// Set the Start to Undefined to prevent Razor design time code generation from rendering a line mapping
|
||||
// for this chunk.
|
||||
Start = SourceLocation.Undefined
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -137,18 +137,18 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
generatedCharacterIndex: 14,
|
||||
contentLength: 85),
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 0,
|
||||
documentAbsoluteIndex: 7,
|
||||
documentLineIndex: 0,
|
||||
documentCharacterIndex: 0,
|
||||
generatedAbsoluteIndex: 910,
|
||||
documentCharacterIndex: 7,
|
||||
generatedAbsoluteIndex: 938,
|
||||
generatedLineIndex: 25,
|
||||
generatedCharacterIndex: 0,
|
||||
contentLength: 46),
|
||||
generatedCharacterIndex: 28,
|
||||
contentLength: 8),
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 139,
|
||||
documentLineIndex: 4,
|
||||
documentCharacterIndex: 17,
|
||||
generatedAbsoluteIndex: 2371,
|
||||
generatedAbsoluteIndex: 2338,
|
||||
generatedLineIndex: 54,
|
||||
generatedCharacterIndex: 95,
|
||||
contentLength: 3),
|
||||
|
|
@ -156,16 +156,17 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
documentAbsoluteIndex: 166,
|
||||
documentLineIndex: 5,
|
||||
documentCharacterIndex: 18,
|
||||
generatedAbsoluteIndex: 2684,
|
||||
generatedAbsoluteIndex: 2651,
|
||||
generatedLineIndex: 60,
|
||||
generatedCharacterIndex: 87,
|
||||
contentLength: 5),
|
||||
};
|
||||
|
||||
// Act and Assert
|
||||
RunDesignTimeTest(host,
|
||||
testName: "ModelExpressionTagHelper",
|
||||
expectedLineMappings: expectedLineMappings);
|
||||
RunDesignTimeTest(
|
||||
host,
|
||||
testName: "ModelExpressionTagHelper",
|
||||
expectedLineMappings: expectedLineMappings);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -197,28 +198,20 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
host.NamespaceImports.Clear();
|
||||
var expectedLineMappings = new[]
|
||||
{
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 0,
|
||||
documentLineIndex: 0,
|
||||
documentCharacterIndex: 0,
|
||||
generatedAbsoluteIndex: 343,
|
||||
generatedLineIndex: 11,
|
||||
generatedCharacterIndex: 0,
|
||||
contentLength: 45),
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 13,
|
||||
documentLineIndex: 0,
|
||||
documentCharacterIndex: 13,
|
||||
generatedAbsoluteIndex: 1412,
|
||||
generatedLineIndex: 37,
|
||||
generatedAbsoluteIndex: 1269,
|
||||
generatedLineIndex: 32,
|
||||
generatedCharacterIndex: 13,
|
||||
contentLength: 4),
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 43,
|
||||
documentLineIndex: 2,
|
||||
documentCharacterIndex: 5,
|
||||
generatedAbsoluteIndex: 1496,
|
||||
generatedLineIndex: 42,
|
||||
generatedAbsoluteIndex: 1353,
|
||||
generatedLineIndex: 37,
|
||||
generatedCharacterIndex: 6,
|
||||
contentLength: 21),
|
||||
};
|
||||
|
|
@ -247,20 +240,12 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
generatedLineIndex: 3,
|
||||
generatedCharacterIndex: 0,
|
||||
contentLength: 17),
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 0,
|
||||
documentLineIndex: 0,
|
||||
documentCharacterIndex: 0,
|
||||
generatedAbsoluteIndex: 443,
|
||||
generatedLineIndex: 17,
|
||||
generatedCharacterIndex: 0,
|
||||
contentLength: 45),
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 28,
|
||||
documentLineIndex: 1,
|
||||
documentCharacterIndex: 8,
|
||||
generatedAbsoluteIndex: 850,
|
||||
generatedLineIndex: 31,
|
||||
generatedAbsoluteIndex: 706,
|
||||
generatedLineIndex: 26,
|
||||
generatedCharacterIndex: 8,
|
||||
contentLength: 20),
|
||||
};
|
||||
|
|
@ -282,18 +267,18 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
var expectedLineMappings = new[]
|
||||
{
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 0,
|
||||
documentAbsoluteIndex: 7,
|
||||
documentLineIndex: 0,
|
||||
documentCharacterIndex: 0,
|
||||
generatedAbsoluteIndex: 363,
|
||||
documentCharacterIndex: 7,
|
||||
generatedAbsoluteIndex: 391,
|
||||
generatedLineIndex: 11,
|
||||
generatedCharacterIndex: 0,
|
||||
contentLength: 45),
|
||||
generatedCharacterIndex: 28,
|
||||
contentLength: 7),
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 24,
|
||||
documentLineIndex: 1,
|
||||
documentCharacterIndex: 8,
|
||||
generatedAbsoluteIndex: 788,
|
||||
generatedAbsoluteIndex: 755,
|
||||
generatedLineIndex: 25,
|
||||
generatedCharacterIndex: 8,
|
||||
contentLength: 20),
|
||||
|
|
@ -301,7 +286,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
documentAbsoluteIndex: 54,
|
||||
documentLineIndex: 2,
|
||||
documentCharacterIndex: 8,
|
||||
generatedAbsoluteIndex: 1014,
|
||||
generatedAbsoluteIndex: 981,
|
||||
generatedLineIndex: 33,
|
||||
generatedCharacterIndex: 8,
|
||||
contentLength: 23),
|
||||
|
|
@ -324,18 +309,18 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
var expectedLineMappings = new[]
|
||||
{
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 0,
|
||||
documentAbsoluteIndex: 7,
|
||||
documentLineIndex: 0,
|
||||
documentCharacterIndex: 0,
|
||||
generatedAbsoluteIndex: 371,
|
||||
documentCharacterIndex: 7,
|
||||
generatedAbsoluteIndex: 399,
|
||||
generatedLineIndex: 11,
|
||||
generatedCharacterIndex: 0,
|
||||
contentLength: 45),
|
||||
generatedCharacterIndex: 28,
|
||||
contentLength: 7),
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 24,
|
||||
documentLineIndex: 1,
|
||||
documentCharacterIndex: 8,
|
||||
generatedAbsoluteIndex: 804,
|
||||
generatedAbsoluteIndex: 771,
|
||||
generatedLineIndex: 25,
|
||||
generatedCharacterIndex: 8,
|
||||
contentLength: 20),
|
||||
|
|
@ -343,7 +328,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
documentAbsoluteIndex: 58,
|
||||
documentLineIndex: 2,
|
||||
documentCharacterIndex: 8,
|
||||
generatedAbsoluteIndex: 1034,
|
||||
generatedAbsoluteIndex: 1001,
|
||||
generatedLineIndex: 33,
|
||||
generatedCharacterIndex: 8,
|
||||
contentLength: 23),
|
||||
|
|
@ -351,7 +336,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
documentAbsoluteIndex: 93,
|
||||
documentLineIndex: 3,
|
||||
documentCharacterIndex: 8,
|
||||
generatedAbsoluteIndex: 1267,
|
||||
generatedAbsoluteIndex: 1234,
|
||||
generatedLineIndex: 41,
|
||||
generatedCharacterIndex: 8,
|
||||
contentLength: 21),
|
||||
|
|
@ -359,7 +344,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
documentAbsoluteIndex: 129,
|
||||
documentLineIndex: 4,
|
||||
documentCharacterIndex: 8,
|
||||
generatedAbsoluteIndex: 1498,
|
||||
generatedAbsoluteIndex: 1465,
|
||||
generatedLineIndex: 49,
|
||||
generatedCharacterIndex: 8,
|
||||
contentLength: 24),
|
||||
|
|
@ -382,19 +367,51 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
var expectedLineMappings = new[]
|
||||
{
|
||||
BuildLineMapping(
|
||||
documentAbsoluteIndex: 0,
|
||||
documentAbsoluteIndex: 7,
|
||||
documentLineIndex: 0,
|
||||
documentCharacterIndex: 0,
|
||||
generatedAbsoluteIndex: 366,
|
||||
documentCharacterIndex: 7,
|
||||
generatedAbsoluteIndex: 394,
|
||||
generatedLineIndex: 11,
|
||||
generatedCharacterIndex: 0,
|
||||
contentLength: 68),
|
||||
generatedCharacterIndex: 28,
|
||||
contentLength: 30),
|
||||
};
|
||||
|
||||
// Act and Assert
|
||||
RunDesignTimeTest(host, "Model", expectedLineMappings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ModelVisitor_GeneratesLineMappingsForLastModel_WhenMultipleModelsArePresent()
|
||||
{
|
||||
// Arrange
|
||||
var fileProvider = new TestFileProvider();
|
||||
var host = new MvcRazorHostWithNormalizedNewLine(new DefaultChunkTreeCache(fileProvider))
|
||||
{
|
||||
DesignTimeMode = true
|
||||
};
|
||||
host.NamespaceImports.Clear();
|
||||
var inputFile = "TestFiles/Input/MultipleModels.cshtml";
|
||||
var outputFile = "TestFiles/Output/DesignTime/MultipleModels.cs";
|
||||
var expectedCode = ResourceFile.ReadResource(_assembly, outputFile, sourceFile: false);
|
||||
|
||||
// Act
|
||||
GeneratorResults results;
|
||||
using (var stream = ResourceFile.GetResourceStream(_assembly, inputFile, sourceFile: true))
|
||||
{
|
||||
results = host.GenerateCode(inputFile, stream);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.False(results.Success);
|
||||
var parserError = Assert.Single(results.ParserErrors);
|
||||
Assert.Equal("Only one 'model' statement is allowed in a file.", parserError.Message);
|
||||
#if GENERATE_BASELINES
|
||||
ResourceFile.UpdateFile(_assembly, outputFile, expectedCode, results.GeneratedCode);
|
||||
#else
|
||||
Assert.Equal(expectedCode, results.GeneratedCode, ignoreLineEndingDifferences: true);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void RunRuntimeTest(
|
||||
MvcRazorHost host,
|
||||
string testName)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
@model ThisShouldNotBeGenerated
|
||||
@model System.Collections.IEnumerable
|
||||
|
|
@ -8,11 +8,6 @@ namespace Asp
|
|||
private void @__RazorDesignTimeHelpers__()
|
||||
{
|
||||
#pragma warning disable 219
|
||||
#line 1 "TestFiles/Input/Basic.cshtml"
|
||||
Microsoft.AspNet.Mvc.Razor.RazorPage<dynamic> __inheritsHelper = null;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#pragma warning restore 219
|
||||
}
|
||||
#line hidden
|
||||
|
|
|
|||
|
|
@ -14,11 +14,6 @@ using MyNamespace
|
|||
private void @__RazorDesignTimeHelpers__()
|
||||
{
|
||||
#pragma warning disable 219
|
||||
#line 1 "TestFiles/Input/Inject.cshtml"
|
||||
Microsoft.AspNet.Mvc.Razor.RazorPage<dynamic> __inheritsHelper = null;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#pragma warning restore 219
|
||||
}
|
||||
#line hidden
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Asp
|
|||
{
|
||||
#pragma warning disable 219
|
||||
#line 1 "TestFiles/Input/InjectWithModel.cshtml"
|
||||
Microsoft.AspNet.Mvc.Razor.RazorPage<MyModel> __inheritsHelper = null;
|
||||
var __modelHelper = default(MyModel);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Asp
|
|||
{
|
||||
#pragma warning disable 219
|
||||
#line 1 "TestFiles/Input/InjectWithSemicolon.cshtml"
|
||||
Microsoft.AspNet.Mvc.Razor.RazorPage<MyModel> __inheritsHelper = null;
|
||||
var __modelHelper = default(MyModel);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Asp
|
|||
{
|
||||
#pragma warning disable 219
|
||||
#line 1 "TestFiles/Input/Model.cshtml"
|
||||
Microsoft.AspNet.Mvc.Razor.RazorPage<System.Collections.IEnumerable> __inheritsHelper = null;
|
||||
var __modelHelper = default(System.Collections.IEnumerable);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace Asp
|
|||
#line hidden
|
||||
;
|
||||
#line 1 "TestFiles/Input/ModelExpressionTagHelper.cshtml"
|
||||
Microsoft.AspNet.Mvc.Razor.RazorPage<DateTime> __inheritsHelper = null;
|
||||
var __modelHelper = default(DateTime);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
namespace Asp
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class ASPV_TestFiles_Input_MultipleModels_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<System.Collections.IEnumerable>
|
||||
{
|
||||
private static object @__o;
|
||||
private void @__RazorDesignTimeHelpers__()
|
||||
{
|
||||
#pragma warning disable 219
|
||||
#line 2 "TestFiles/Input/MultipleModels.cshtml"
|
||||
var __modelHelper = default(System.Collections.IEnumerable);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#pragma warning restore 219
|
||||
}
|
||||
#line hidden
|
||||
public ASPV_TestFiles_Input_MultipleModels_cshtml()
|
||||
{
|
||||
}
|
||||
#line hidden
|
||||
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
|
||||
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<System.Collections.IEnumerable> Html { get; private set; }
|
||||
|
||||
#line hidden
|
||||
|
||||
#pragma warning disable 1998
|
||||
public override async Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue