Add Model specific code generation.
By adding model specific code generation we are able to map the generic "base type" code to the cshtml file. This also involved utilizing the CreateClassDeclaration method in the Microsoft.AspNet.Razor library. Lastly Added a MvcCSharpChunkVisitor to add one more abstraction layer between the Microsoft.AspNet.Razor code and the Mvc code; this makes it so Mvc follows the same class structure as the base Razor parser. #568
This commit is contained in:
parent
2aacdeca4a
commit
b808c48faf
|
|
@ -25,6 +25,10 @@
|
|||
<Compile Include="InjectChunk.cs" />
|
||||
<Compile Include="InjectChunkVisitor.cs" />
|
||||
<Compile Include="InjectParameterGenerator.cs" />
|
||||
<Compile Include="ModelChunk.cs" />
|
||||
<Compile Include="ModelChunkVisitor.cs" />
|
||||
<Compile Include="ModelCodeGenerator.cs" />
|
||||
<Compile Include="MvcCSharpChunkVisitor.cs" />
|
||||
<Compile Include="MvcCSharpCodeBuilder.cs" />
|
||||
<Compile Include="MvcCSharpCodeVistor.cs" />
|
||||
<Compile Include="MvcRazorCodeParser.cs" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public class ModelChunk : Chunk
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the chunk for an @model statement.
|
||||
/// </summary>
|
||||
/// <param name="baseType">The base type of the view.</param>
|
||||
/// <param name="modelType">The type of the view's Model.</param>
|
||||
public ModelChunk(string baseType, string modelType)
|
||||
{
|
||||
BaseType = baseType;
|
||||
ModelType = modelType;
|
||||
}
|
||||
|
||||
public string BaseType { get; private set; }
|
||||
public string ModelType { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler.CSharp;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public class ModelChunkVisitor : MvcCSharpCodeVisitor
|
||||
{
|
||||
public ModelChunkVisitor([NotNull] CSharpCodeWriter writer,
|
||||
[NotNull] CodeGeneratorContext context)
|
||||
: base(writer, context)
|
||||
{ }
|
||||
|
||||
protected override void Visit(ModelChunk chunk)
|
||||
{
|
||||
var csharpVisitor = new CSharpCodeVisitor(Writer, Context);
|
||||
|
||||
Writer.Write(chunk.BaseType).Write("<");
|
||||
csharpVisitor.CreateExpressionCodeMapping(chunk.ModelType, chunk);
|
||||
Writer.Write(">");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.Mvc.Razor;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Generator
|
||||
{
|
||||
public class ModelCodeGenerator : SpanCodeGenerator
|
||||
{
|
||||
public ModelCodeGenerator(string baseType, string modelType)
|
||||
{
|
||||
BaseType = baseType;
|
||||
ModelType = modelType;
|
||||
}
|
||||
|
||||
public string BaseType { get; private set; }
|
||||
public string ModelType { get; private set; }
|
||||
|
||||
public override void GenerateCode(Span target, CodeGeneratorContext context)
|
||||
{
|
||||
var modelChunk = new ModelChunk(BaseType, ModelType);
|
||||
context.CodeTreeBuilder.AddChunk(modelChunk, target, topLevel: true);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Full Model Type: " + BaseType + "<" + ModelType + ">";
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as ModelCodeGenerator;
|
||||
return other != null &&
|
||||
string.Equals(ModelType, other.ModelType, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ModelType.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler.CSharp;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public abstract class MvcCSharpChunkVisitor : CodeVisitor<CSharpCodeWriter>
|
||||
{
|
||||
public MvcCSharpChunkVisitor([NotNull] CSharpCodeWriter writer,
|
||||
[NotNull] CodeGeneratorContext context)
|
||||
: base(writer, context)
|
||||
{ }
|
||||
|
||||
public override void Accept(Chunk chunk)
|
||||
{
|
||||
if (chunk is InjectChunk)
|
||||
{
|
||||
Visit((InjectChunk)chunk);
|
||||
}
|
||||
else if (chunk is ModelChunk)
|
||||
{
|
||||
Visit((ModelChunk)chunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.Accept(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void Visit(InjectChunk chunk);
|
||||
protected abstract void Visit(ModelChunk chunk);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,10 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler.CSharp;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
|
|
@ -15,6 +17,29 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
}
|
||||
|
||||
protected override CSharpCodeWritingScope BuildClassDeclaration(CSharpCodeWriter writer)
|
||||
{
|
||||
var chunks = Context.CodeTreeBuilder.CodeTree.Chunks;
|
||||
|
||||
// If there were any model chunks then we need to modify the class declaration signature.
|
||||
if (chunks.OfType<ModelChunk>().Any())
|
||||
{
|
||||
writer.Write(string.Format(CultureInfo.CurrentCulture, "public class {0} : ", Context.ClassName));
|
||||
|
||||
var modelVisitor = new ModelChunkVisitor(writer, Context);
|
||||
// This generates the base class signature
|
||||
modelVisitor.Accept(chunks);
|
||||
|
||||
writer.WriteLine();
|
||||
|
||||
return new CSharpCodeWritingScope(writer);
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.BuildClassDeclaration(writer);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void BuildConstructor([NotNull] CSharpCodeWriter writer)
|
||||
{
|
||||
writer.WriteLineHiddenDirective();
|
||||
|
|
|
|||
|
|
@ -2,31 +2,22 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler.CSharp;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public abstract class MvcCSharpCodeVisitor : CodeVisitor<CSharpCodeWriter>
|
||||
public abstract class MvcCSharpCodeVisitor : MvcCSharpChunkVisitor
|
||||
{
|
||||
public MvcCSharpCodeVisitor([NotNull] CSharpCodeWriter writer,
|
||||
public MvcCSharpCodeVisitor([NotNull] CSharpCodeWriter writer,
|
||||
[NotNull] CodeGeneratorContext context)
|
||||
: base(writer, context)
|
||||
{ }
|
||||
|
||||
protected override void Visit(InjectChunk chunk)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Accept(Chunk chunk)
|
||||
protected override void Visit(ModelChunk chunk)
|
||||
{
|
||||
if (chunk is InjectChunk)
|
||||
{
|
||||
Visit((InjectChunk)chunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.Accept(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void Visit(InjectChunk chunk);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNet.Mvc.Razor.Host;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
|
|
@ -13,7 +12,6 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
public class MvcRazorCodeParser : CSharpCodeParser
|
||||
{
|
||||
private const string GenericTypeFormat = "{0}<{1}>";
|
||||
private const string ModelKeyword = "model";
|
||||
private const string InjectKeyword = "inject";
|
||||
private readonly string _baseType;
|
||||
|
|
@ -138,12 +136,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
|
||||
private SpanCodeGenerator CreateModelCodeGenerator(string model)
|
||||
{
|
||||
// In the event we have an empty model, the name we generate does not matter since it's a parser error.
|
||||
// We'll use the non-generic version of the base type.
|
||||
var baseType = string.IsNullOrEmpty(model) ?
|
||||
_baseType :
|
||||
string.Format(CultureInfo.InvariantCulture, GenericTypeFormat, _baseType, model);
|
||||
return new SetBaseTypeCodeGenerator(baseType);
|
||||
return new ModelCodeGenerator(_baseType, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue