diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorCodeGenerator.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorCodeGenerator.cs new file mode 100644 index 0000000000..a2868f56ef --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorCodeGenerator.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. + +using System.CodeDom; +using Microsoft.AspNet.Razor; +using Microsoft.AspNet.Razor.Generator; + +namespace Microsoft.AspNet.Mvc.Razor +{ + internal class MvcRazorCodeGenerator : CSharpRazorCodeGenerator + { + private const string DefaultModelTypeName = "dynamic"; + + public MvcRazorCodeGenerator(string className, string rootNamespaceName, string sourceFileName, RazorEngineHost host) + : base(className, rootNamespaceName, sourceFileName, host) + { + var mvcHost = host as MvcRazorHost; + if (mvcHost != null) + { + // set the default model type to "dynamic" (Dev10 bug 935656) + // don't set it for "special" pages (such as "_viewStart.cshtml") + SetBaseType(DefaultModelTypeName); + } + } + + private void SetBaseType(string modelTypeName) + { + var baseType = new CodeTypeReference(Context.Host.DefaultBaseClass + "<" + modelTypeName + ">"); + Context.GeneratedClass.BaseTypes.Clear(); + Context.GeneratedClass.BaseTypes.Add(baseType); + } + } +} diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorCodeParser.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorCodeParser.cs new file mode 100644 index 0000000000..4c5eca4bb6 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorCodeParser.cs @@ -0,0 +1,68 @@ +using System; +using System.Globalization; +using Microsoft.AspNet.Razor.Generator; +using Microsoft.AspNet.Razor.Parser; +using Microsoft.AspNet.Razor.Text; + +namespace Microsoft.AspNet.Mvc.Razor +{ + public class MvcRazorCodeParser : CSharpCodeParser + { + private const string ModelKeyword = "model"; + private const string GenericTypeFormatString = "{0}<{1}>"; + private SourceLocation? _endInheritsLocation; + private bool _modelStatementFound; + + public MvcRazorCodeParser() + { + MapDirectives(ModelDirective, ModelKeyword); + } + + protected override void InheritsDirective() + { + // Verify we're on the right keyword and accept + AssertDirective(SyntaxConstants.CSharp.InheritsKeyword); + AcceptAndMoveNext(); + _endInheritsLocation = CurrentLocation; + + InheritsDirectiveCore(); + CheckForInheritsAndModelStatements(); + } + + private void CheckForInheritsAndModelStatements() + { + if (_modelStatementFound && _endInheritsLocation.HasValue) + { + Context.OnError(_endInheritsLocation.Value, String.Format(CultureInfo.CurrentCulture, "MvcResources.MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword", ModelKeyword)); + } + } + + protected virtual void ModelDirective() + { + // Verify we're on the right keyword and accept + AssertDirective(ModelKeyword); + AcceptAndMoveNext(); + + SourceLocation endModelLocation = CurrentLocation; + + BaseTypeDirective( + String.Format(CultureInfo.CurrentCulture, + "MvcResources.MvcRazorCodeParser_ModelKeywordMustBeFollowedByTypeName", ModelKeyword), + CreateModelCodeGenerator); + + if (_modelStatementFound) + { + Context.OnError(endModelLocation, String.Format(CultureInfo.CurrentCulture, "MvcResources.MvcRazorCodeParser_OnlyOneModelStatementIsAllowed", ModelKeyword)); + } + + _modelStatementFound = true; + + CheckForInheritsAndModelStatements(); + } + + private SpanCodeGenerator CreateModelCodeGenerator(string model) + { + return new SetModelTypeCodeGenerator(model, GenericTypeFormatString); + } + } +} diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/SetModelTypeCodeGenerator.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/SetModelTypeCodeGenerator.cs new file mode 100644 index 0000000000..7c270303e2 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/SetModelTypeCodeGenerator.cs @@ -0,0 +1,39 @@ +using System; +using System.Globalization; +using Microsoft.AspNet.Razor.Generator; + +namespace Microsoft.AspNet.Mvc.Razor +{ + internal class SetModelTypeCodeGenerator : SetBaseTypeCodeGenerator + { + private string _genericTypeFormat; + + public SetModelTypeCodeGenerator(string modelType, string genericTypeFormat) + : base(modelType) + { + _genericTypeFormat = genericTypeFormat; + } + + protected override string ResolveType(CodeGeneratorContext context, string baseType) + { + return String.Format( + CultureInfo.InvariantCulture, + _genericTypeFormat, + context.Host.DefaultBaseClass, + baseType); + } + + public override bool Equals(object obj) + { + SetModelTypeCodeGenerator other = obj as SetModelTypeCodeGenerator; + return other != null && + base.Equals(obj) && + String.Equals(_genericTypeFormat, other._genericTypeFormat, StringComparison.Ordinal); + } + + public override string ToString() + { + return "Model:" + BaseType; + } + } +}