Browse Source
Use the @model directive to generate a strongly typed WebViewPage class. Support completion on the Model property in a view.pull/28/head
8 changed files with 310 additions and 9 deletions
@ -0,0 +1,34 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Web.Razor; |
||||||
|
using ICSharpCode.SharpDevelop; |
||||||
|
|
||||||
|
namespace ICSharpCode.AspNet.Mvc.Completion |
||||||
|
{ |
||||||
|
public class RazorCSharpModelTypeLocater |
||||||
|
{ |
||||||
|
public RazorCSharpModelTypeLocater(ITextBuffer textBuffer) |
||||||
|
{ |
||||||
|
ParserResults results = ParseTemplate(textBuffer); |
||||||
|
ModelTypeName = GetModelTypeName(results); |
||||||
|
} |
||||||
|
|
||||||
|
ParserResults ParseTemplate(ITextBuffer textBuffer) |
||||||
|
{ |
||||||
|
var host = new RazorEngineHost(new CSharpRazorCodeLanguage()); |
||||||
|
var engine = new RazorTemplateEngine(host); |
||||||
|
return engine.ParseTemplate(textBuffer.CreateReader()); |
||||||
|
} |
||||||
|
|
||||||
|
string GetModelTypeName(ParserResults results) |
||||||
|
{ |
||||||
|
var visitor = new RazorCSharpParserModelTypeVisitor(); |
||||||
|
results.Document.Accept(visitor); |
||||||
|
return visitor.ModelTypeName; |
||||||
|
} |
||||||
|
|
||||||
|
public string ModelTypeName { get; private set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Web.Razor.Parser; |
||||||
|
using System.Web.Razor.Parser.SyntaxTree; |
||||||
|
|
||||||
|
namespace ICSharpCode.AspNet.Mvc.Completion |
||||||
|
{ |
||||||
|
public class RazorCSharpParserModelTypeVisitor : ParserVisitor |
||||||
|
{ |
||||||
|
bool foundModelTypeName; |
||||||
|
|
||||||
|
public RazorCSharpParserModelTypeVisitor() |
||||||
|
{ |
||||||
|
ModelTypeName = String.Empty; |
||||||
|
} |
||||||
|
|
||||||
|
public string ModelTypeName { get; private set; } |
||||||
|
|
||||||
|
public override void VisitSpan(Span span) |
||||||
|
{ |
||||||
|
Console.WriteLine("Span.Kind: " + span.Kind); |
||||||
|
Console.WriteLine("Span.GetType(): " + span.GetType().Name); |
||||||
|
Console.WriteLine("Span.Content: '" + span.Content + "'"); |
||||||
|
|
||||||
|
if (foundModelTypeName) |
||||||
|
return; |
||||||
|
|
||||||
|
if (IsModelSpan(span)) { |
||||||
|
VisitModelNameSpan(span.Next); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool IsModelSpan(Span span) |
||||||
|
{ |
||||||
|
return span.Content == "model"; |
||||||
|
} |
||||||
|
|
||||||
|
void VisitModelNameSpan(Span span) |
||||||
|
{ |
||||||
|
if (span == null) |
||||||
|
return; |
||||||
|
|
||||||
|
string firstLineOfMarkup = GetFirstLine(span.Content); |
||||||
|
ModelTypeName = firstLineOfMarkup.Trim(); |
||||||
|
foundModelTypeName = true; |
||||||
|
} |
||||||
|
|
||||||
|
string GetFirstLine(string text) |
||||||
|
{ |
||||||
|
int endOfLineIndex = text.IndexOf('\r'); |
||||||
|
if (endOfLineIndex > 0) { |
||||||
|
return text.Substring(0, endOfLineIndex); |
||||||
|
} |
||||||
|
return text; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using ICSharpCode.SharpDevelop.Dom; |
||||||
|
|
||||||
|
namespace ICSharpCode.AspNet.Mvc.Completion |
||||||
|
{ |
||||||
|
public class RazorCompilationUnit : DefaultCompilationUnit |
||||||
|
{ |
||||||
|
public RazorCompilationUnit(IProjectContent projectContent) |
||||||
|
: base(projectContent) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public static RazorCompilationUnit CreateFromParseInfo(ParseInformation parseInformation) |
||||||
|
{ |
||||||
|
return new RazorCompilationUnit(parseInformation.CompilationUnit.ProjectContent) { |
||||||
|
ModelTypeName = GetModelTypeName(parseInformation.CompilationUnit) |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
static string GetModelTypeName(ICompilationUnit compilationUnit) |
||||||
|
{ |
||||||
|
var originalRazorCompilationUnit = compilationUnit as RazorCompilationUnit; |
||||||
|
if (originalRazorCompilationUnit != null) { |
||||||
|
return originalRazorCompilationUnit.ModelTypeName; |
||||||
|
} |
||||||
|
return String.Empty; |
||||||
|
} |
||||||
|
|
||||||
|
public string ModelTypeName { get; set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,148 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using ICSharpCode.AspNet.Mvc.Completion; |
||||||
|
using ICSharpCode.SharpDevelop; |
||||||
|
using ICSharpCode.SharpDevelop.Dom; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace AspNet.Mvc.Tests.Completion |
||||||
|
{ |
||||||
|
[TestFixture] |
||||||
|
public class RazorCSharpParserTests |
||||||
|
{ |
||||||
|
RazorCSharpParser parser; |
||||||
|
|
||||||
|
void CreateParser() |
||||||
|
{ |
||||||
|
parser = new RazorCSharpParser(); |
||||||
|
} |
||||||
|
|
||||||
|
ICompilationUnit Parse(string code) |
||||||
|
{ |
||||||
|
var projectContent = new DefaultProjectContent(); |
||||||
|
var textBuffer = new StringTextBuffer(code); |
||||||
|
return parser.Parse(projectContent, @"d:\MyProject\Views\Index.cshtml", textBuffer); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Parse_ModelDirectiveWithTypeName_ModelTypeNameFound() |
||||||
|
{ |
||||||
|
CreateParser(); |
||||||
|
string code = "@model MvcApplication.MyModel\r\n"; |
||||||
|
|
||||||
|
var compilationUnit = Parse(code) as RazorCompilationUnit; |
||||||
|
|
||||||
|
Assert.AreEqual("MvcApplication.MyModel", compilationUnit.ModelTypeName); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Parse_ModelDirectiveWithTypeNameFollowedByHtmlMarkup_ModelTypeNameFound() |
||||||
|
{ |
||||||
|
CreateParser(); |
||||||
|
string code = |
||||||
|
"@model MvcApplication.LogonModel\r\n" + |
||||||
|
"<h2>Index</h2>\r\n"; |
||||||
|
|
||||||
|
var compilationUnit = Parse(code) as RazorCompilationUnit; |
||||||
|
|
||||||
|
Assert.AreEqual("MvcApplication.LogonModel", compilationUnit.ModelTypeName); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Parse_SingleLineFileWithModelDirectiveAndTypeNameButNoNewLineAtEnd_ModelTypeNameFound() |
||||||
|
{ |
||||||
|
CreateParser(); |
||||||
|
string code = "@model MvcApplication.MyModel"; |
||||||
|
|
||||||
|
var compilationUnit = Parse(code) as RazorCompilationUnit; |
||||||
|
|
||||||
|
Assert.AreEqual("MvcApplication.MyModel", compilationUnit.ModelTypeName); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Parse_ModelTypeDirectiveWithTypeNameFollowedByRazorBlock_ModelTypeNameFound() |
||||||
|
{ |
||||||
|
CreateParser(); |
||||||
|
|
||||||
|
string code = |
||||||
|
"@model IEnumerable<MvcApplication1.Models.MyClass>\r\n" + |
||||||
|
"\r\n" + |
||||||
|
"@{\r\n" + |
||||||
|
" ViewBag.Title = \"Title1\";\r\n" + |
||||||
|
"}\r\n" + |
||||||
|
"\r\n"; |
||||||
|
|
||||||
|
var compilationUnit = Parse(code) as RazorCompilationUnit; |
||||||
|
|
||||||
|
Assert.AreEqual("IEnumerable<MvcApplication1.Models.MyClass>", compilationUnit.ModelTypeName); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Parse_UsingDirective_ModelTypeNameIsEmptyString() |
||||||
|
{ |
||||||
|
CreateParser(); |
||||||
|
string code = "@using System.Xml\r\n"; |
||||||
|
|
||||||
|
var compilationUnit = Parse(code) as RazorCompilationUnit; |
||||||
|
|
||||||
|
Assert.AreEqual(String.Empty, compilationUnit.ModelTypeName); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Parse_HelperDirective_ModelTypeNameIsEmptyString() |
||||||
|
{ |
||||||
|
CreateParser(); |
||||||
|
string code = "@helper MyHelper\r\n"; |
||||||
|
|
||||||
|
var compilationUnit = Parse(code) as RazorCompilationUnit; |
||||||
|
|
||||||
|
Assert.AreEqual(String.Empty, compilationUnit.ModelTypeName); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Parse_HtmlMarkupOnly_ModelTypeNameIsEmptyString() |
||||||
|
{ |
||||||
|
CreateParser(); |
||||||
|
string code = "<h1>heading</h1>\r\n"; |
||||||
|
|
||||||
|
var compilationUnit = Parse(code) as RazorCompilationUnit; |
||||||
|
|
||||||
|
Assert.AreEqual(String.Empty, compilationUnit.ModelTypeName); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Parse_ModelDirectiveOnly_ModelTypeNameIsEmptyString() |
||||||
|
{ |
||||||
|
CreateParser(); |
||||||
|
string code = "@model"; |
||||||
|
|
||||||
|
var compilationUnit = Parse(code) as RazorCompilationUnit; |
||||||
|
|
||||||
|
Assert.AreEqual(String.Empty, compilationUnit.ModelTypeName); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Parse_ModelStringInsideParagraphTags_ModelTypeNameIsEmptyString() |
||||||
|
{ |
||||||
|
CreateParser(); |
||||||
|
string code = "<p>model</p>"; |
||||||
|
|
||||||
|
var compilationUnit = Parse(code) as RazorCompilationUnit; |
||||||
|
|
||||||
|
Assert.AreEqual(String.Empty, compilationUnit.ModelTypeName); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Parse_ModelStringOnlyWithoutRazorTransition_ModelTypeNameIsEmptyString() |
||||||
|
{ |
||||||
|
CreateParser(); |
||||||
|
string code = "model"; |
||||||
|
|
||||||
|
var compilationUnit = Parse(code) as RazorCompilationUnit; |
||||||
|
|
||||||
|
Assert.AreEqual(String.Empty, compilationUnit.ModelTypeName); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue