static void CreateCSharpParsedDocument(RazorCSharpParserContext context) { if (context.Project == null) { return; } context.CSharpCode = CreateCodeFile(context); context.ParsedSyntaxTree = CSharpSyntaxTree.ParseText(Microsoft.CodeAnalysis.Text.SourceText.From(context.CSharpCode)); var originalProject = TypeSystemService.GetCodeAnalysisProject(context.Project); if (originalProject != null) { string fileName = context.FileName + ".g.cs"; var documentId = TypeSystemService.GetDocumentId(originalProject.Id, fileName); if (documentId == null) { context.AnalysisDocument = originalProject.AddDocument( fileName, context.ParsedSyntaxTree?.GetRoot()); } else { context.AnalysisDocument = TypeSystemService.GetCodeAnalysisDocument(documentId); } } }
static IEnumerable <FoldingRegion> GetFoldingRegions(RazorCSharpParserContext context) { var foldingRegions = new List <FoldingRegion> (); GetHtmlFoldingRegions(context, foldingRegions); GetRazorFoldingRegions(context, foldingRegions); return(foldingRegions); }
static void GetHtmlFoldingRegions(RazorCSharpParserContext context, List <FoldingRegion> foldingRegions) { if (context.HtmlParsedDocument != null) { var d = new MonoDevelop.AspNet.WebForms.WebFormsParsedDocument(null, WebSubtype.Html, null, context.HtmlParsedDocument); foldingRegions.AddRange(d.Foldings); } }
void EnsureParserInitializedFor(RazorCSharpParserContext context) { if (context.EditorParser != null) { return; } CreateParserFor(context); }
static void ParseHtmlDocument(RazorCSharpParserContext context, List <Error> errors) { var sb = new StringBuilder(); var spanList = new List <Span> (); context.Comments = new List <Comment> (); Action <Span> action = (Span span) => { if (span.Kind == SpanKind.Markup) { sb.Append(span.Content); spanList.Add(span); } else { for (int i = 0; i < span.Content.Length; i++) { char ch = span.Content[i]; if (ch != '\r' && ch != '\n') { sb.Append(' '); } else { sb.Append(ch); } } if (span.Kind == SpanKind.Comment) { var comment = new Comment(span.Content) { OpenTag = "@*", ClosingTag = "*@", CommentType = CommentType.Block, }; comment.Region = new MonoDevelop.Ide.Editor.DocumentRegion( context.Document.OffsetToLocation(span.Start.AbsoluteIndex - comment.OpenTag.Length), context.Document.OffsetToLocation(span.Start.AbsoluteIndex + span.Length + comment.ClosingTag.Length)); context.Comments.Add(comment); } } }; context.EditorParser.CurrentParseTree.Accept(new CallbackVisitor(action)); var parser = new MonoDevelop.Xml.Parser.XmlParser(new WebFormsRootState(), true); try { parser.Parse(new StringReader(sb.ToString())); } catch (Exception ex) { LoggingService.LogError("Unhandled error parsing html in Razor document '" + (context.FileName ?? "") + "'", ex); } context.HtmlParsedDocument = parser.Nodes.GetRoot(); errors.AddRange(parser.Errors); }
System.Threading.Tasks.Task <ParsedDocument> Parse(RazorCSharpParserContext context, CancellationToken cancellationToken) { EnsureParserInitializedFor(context); var errors = new List <Error> (); using (var source = new SeekableTextReader(context.Content.CreateReader())) { var textChange = CreateTextChange(context, source); var parseResult = context.EditorParser.CheckForStructureChanges(textChange); if (parseResult == PartialParseResult.Rejected) { context.RazorDocument.ParseComplete.WaitOne(); if (!context.CapturedArgs.GeneratorResults.Success) { GetRazorErrors(context, errors); } } } ParseHtmlDocument(context, errors); CreateCSharpParsedDocument(context); context.ClearLastTextChange(); RazorHostKind kind = RazorHostKind.WebPage; if (context.EditorParser.Host is WebCodeRazorHost) { kind = RazorHostKind.WebCode; } else if (context.EditorParser.Host is MonoDevelop.AspNet.Razor.Generator.PreprocessedRazorHost) { kind = RazorHostKind.Template; } var model = context.AnalysisDocument.GetSemanticModelAsync(cancellationToken).Result; var pageInfo = new RazorCSharpPageInfo() { HtmlRoot = context.HtmlParsedDocument, GeneratorResults = context.CapturedArgs.GeneratorResults, Spans = context.EditorParser.CurrentParseTree.Flatten(), CSharpSyntaxTree = context.ParsedSyntaxTree, ParsedDocument = new DefaultParsedDocument("generated.cs") { Ast = model }, AnalysisDocument = context.AnalysisDocument, CSharpCode = context.CSharpCode, Errors = errors, FoldingRegions = GetFoldingRegions(context), Comments = context.Comments, HostKind = kind, }; return(System.Threading.Tasks.Task.FromResult((ParsedDocument) new RazorCSharpParsedDocument(context.FileName, pageInfo))); }
void CreateParserFor(RazorCSharpParserContext context) { context.EditorParser = new MonoDevelop.Web.Razor.EditorParserFixed.RazorEditorParser(CreateRazorHost(context), context.FileName); context.RazorDocument.ParseComplete = new AutoResetEvent(false); context.EditorParser.DocumentParseComplete += (sender, args) => { context.RazorDocument.CapturedArgs = args; context.RazorDocument.ParseComplete.Set(); }; }
static void GetRazorErrors(RazorCSharpParserContext context, List <Error> errors) { foreach (var error in context.CapturedArgs.GeneratorResults.ParserErrors) { int off = error.Location.AbsoluteIndex; if (error.Location.CharacterIndex > 0 && error.Length == 1) { off--; } errors.Add(new Error(ErrorType.Error, error.Message, context.Document.OffsetToLocation(off))); } }
public override System.Threading.Tasks.Task<ParsedDocument> Parse (MonoDevelop.Ide.TypeSystem.ParseOptions parseOptions, CancellationToken cancellationToken) { OpenRazorDocument currentDocument = GetDocument (parseOptions.FileName); if (currentDocument == null) return System.Threading.Tasks.Task.FromResult ((ParsedDocument)new RazorCSharpParsedDocument (parseOptions.FileName, new RazorCSharpPageInfo ())); var context = new RazorCSharpParserContext (parseOptions, currentDocument); lock (currentDocument) { return Parse (context, cancellationToken); } }
public override System.Threading.Tasks.Task <ParsedDocument> Parse(MonoDevelop.Ide.TypeSystem.ParseOptions parseOptions, CancellationToken cancellationToken) { OpenRazorDocument currentDocument = GetDocument(parseOptions.FileName); if (currentDocument == null) { return(System.Threading.Tasks.Task.FromResult((ParsedDocument) new RazorCSharpParsedDocument(parseOptions.FileName, new RazorCSharpPageInfo()))); } var context = new RazorCSharpParserContext(parseOptions, currentDocument); lock (currentDocument) { return(Parse(context, cancellationToken)); } }
static TextChange CreateTextChange(RazorCSharpParserContext context, SeekableTextReader source) { ChangeInfo lastChange = context.GetLastTextChange(); if (lastChange == null) { return(new TextChange(0, 0, new SeekableTextReader(String.Empty), 0, source.Length, source)); } if (lastChange.DeleteChange) { return(new TextChange(lastChange.StartOffset, lastChange.AbsoluteLength, lastChange.Buffer, lastChange.StartOffset, 0, source)); } return(new TextChange(lastChange.StartOffset, 0, lastChange.Buffer, lastChange.StartOffset, lastChange.AbsoluteLength, source)); }
static void GetRazorFoldingRegions(RazorCSharpParserContext context, List <FoldingRegion> foldingRegions) { var blocks = new List <Block> (); GetBlocks(context.EditorParser.CurrentParseTree, blocks); foreach (var block in blocks) { var beginLine = context.Document.GetLineByOffset(block.Start.AbsoluteIndex); var endLine = context.Document.GetLineByOffset(block.Start.AbsoluteIndex + block.Length); if (beginLine != endLine) { foldingRegions.Add(new FoldingRegion(RazorUtils.GetShortName(block), new DocumentRegion(context.Document.OffsetToLocation(block.Start.AbsoluteIndex), context.Document.OffsetToLocation(block.Start.AbsoluteIndex + block.Length)))); } } }
static string CreateCodeFile(RazorCSharpParserContext context) { var unit = context.CapturedArgs.GeneratorResults.GeneratedCode; System.CodeDom.Compiler.CodeDomProvider provider = context.Project != null ? context.Project.LanguageBinding.GetCodeDomProvider() : new Microsoft.CSharp.CSharpCodeProvider(); using (var sw = new StringWriter()) { provider.GenerateCodeFromCompileUnit(unit, sw, new System.CodeDom.Compiler.CodeGeneratorOptions() { // HACK: we use true, even though razor uses false, to work around a mono bug where it omits the // line ending after "#line hidden", resulting in the unparseable "#line hiddenpublic" BlankLinesBetweenMembers = true, // matches Razor built-in settings IndentString = String.Empty, }); return(sw.ToString()); } }
System.Threading.Tasks.Task<ParsedDocument> Parse (RazorCSharpParserContext context, CancellationToken cancellationToken) { EnsureParserInitializedFor (context); var errors = new List<Error> (); using (var source = new SeekableTextReader (context.Content.CreateReader ())) { var textChange = CreateTextChange (context, source); var parseResult = context.EditorParser.CheckForStructureChanges (textChange); if (parseResult == PartialParseResult.Rejected) { context.RazorDocument.ParseComplete.WaitOne (); if (!context.CapturedArgs.GeneratorResults.Success) GetRazorErrors (context, errors); } } ParseHtmlDocument (context, errors); CreateCSharpParsedDocument (context); context.ClearLastTextChange (); RazorHostKind kind = RazorHostKind.WebPage; if (context.EditorParser.Host is WebCodeRazorHost) { kind = RazorHostKind.WebCode; } else if (context.EditorParser.Host is MonoDevelop.AspNet.Razor.Generator.PreprocessedRazorHost) { kind = RazorHostKind.Template; } var model = context.AnalysisDocument.GetSemanticModelAsync (cancellationToken).Result; var pageInfo = new RazorCSharpPageInfo () { HtmlRoot = context.HtmlParsedDocument, GeneratorResults = context.CapturedArgs.GeneratorResults, Spans = context.EditorParser.CurrentParseTree.Flatten (), CSharpSyntaxTree = context.ParsedSyntaxTree, ParsedDocument = new DefaultParsedDocument ("generated.cs") { Ast = model }, AnalysisDocument = context.AnalysisDocument, CSharpCode = context.CSharpCode, Errors = errors, FoldingRegions = GetFoldingRegions (context), Comments = context.Comments, HostKind = kind, }; return System.Threading.Tasks.Task.FromResult((ParsedDocument)new RazorCSharpParsedDocument (context.FileName, pageInfo)); }
void CreateParserFor (RazorCSharpParserContext context) { context.EditorParser = new MonoDevelop.Web.Razor.EditorParserFixed.RazorEditorParser (CreateRazorHost (context), context.FileName); context.RazorDocument.ParseComplete = new AutoResetEvent (false); context.EditorParser.DocumentParseComplete += (sender, args) => { context.RazorDocument.CapturedArgs = args; context.RazorDocument.ParseComplete.Set (); }; }
static RazorEngineHost CreateRazorHost (RazorCSharpParserContext context) { if (context.Project != null) { var projectFile = context.Project.GetProjectFile (context.FileName); if (projectFile != null && projectFile.Generator == "RazorTemplatePreprocessor") { return new MonoDevelop.AspNet.Razor.Generator.PreprocessedRazorHost (context.FileName) { DesignTimeMode = true, EnableLinePragmas = false, }; } } string virtualPath = "~/Views/Default.cshtml"; if (context.AspProject != null) virtualPath = context.AspProject.LocalToVirtualPath (context.FileName); WebPageRazorHost host = null; // Try to create host using web.config file var webConfigMap = new WebConfigurationFileMap (); if (context.AspProject != null) { var vdm = new VirtualDirectoryMapping (context.AspProject.Project.BaseDirectory.Combine ("Views"), true, "web.config"); webConfigMap.VirtualDirectories.Add ("/", vdm); } Configuration configuration; try { configuration = WebConfigurationManager.OpenMappedWebConfiguration (webConfigMap, "/"); } catch { configuration = null; } if (configuration != null) { //TODO: use our assemblies, not the project's var rws = configuration.GetSectionGroup (RazorWebSectionGroup.GroupName) as RazorWebSectionGroup; if (rws != null) { host = WebRazorHostFactory.CreateHostFromConfig (rws, virtualPath, context.FileName); host.DesignTimeMode = true; } } if (host == null) { host = new MvcWebPageRazorHost (virtualPath, context.FileName) { DesignTimeMode = true }; // Add default namespaces from Razor section host.NamespaceImports.Add ("System.Web.Mvc"); host.NamespaceImports.Add ("System.Web.Mvc.Ajax"); host.NamespaceImports.Add ("System.Web.Mvc.Html"); host.NamespaceImports.Add ("System.Web.Routing"); } return host; }
static TextChange CreateTextChange (RazorCSharpParserContext context, SeekableTextReader source) { ChangeInfo lastChange = context.GetLastTextChange (); if (lastChange == null) return new TextChange (0, 0, new SeekableTextReader (String.Empty), 0, source.Length, source); if (lastChange.DeleteChange) return new TextChange (lastChange.StartOffset, lastChange.AbsoluteLength, lastChange.Buffer, lastChange.StartOffset, 0, source); return new TextChange (lastChange.StartOffset, 0, lastChange.Buffer, lastChange.StartOffset, lastChange.AbsoluteLength, source); }
static void GetRazorErrors (RazorCSharpParserContext context, List<Error> errors) { foreach (var error in context.CapturedArgs.GeneratorResults.ParserErrors) { int off = error.Location.AbsoluteIndex; if (error.Location.CharacterIndex > 0 && error.Length == 1) off--; errors.Add (new Error (ErrorType.Error, error.Message, context.Document.OffsetToLocation (off))); } }
static void ParseHtmlDocument (RazorCSharpParserContext context, List<Error> errors) { var sb = new StringBuilder (); var spanList = new List<Span> (); context.Comments = new List<Comment> (); Action<Span> action = (Span span) => { if (span.Kind == SpanKind.Markup) { sb.Append (span.Content); spanList.Add (span); } else { for (int i = 0; i < span.Content.Length; i++) { char ch = span.Content[i]; if (ch != '\r' && ch != '\n') sb.Append (' '); else sb.Append (ch); } if (span.Kind == SpanKind.Comment) { var comment = new Comment (span.Content) { OpenTag = "@*", ClosingTag = "*@", CommentType = CommentType.Block, }; comment.Region = new MonoDevelop.Ide.Editor.DocumentRegion ( context.Document.OffsetToLocation (span.Start.AbsoluteIndex - comment.OpenTag.Length), context.Document.OffsetToLocation (span.Start.AbsoluteIndex + span.Length + comment.ClosingTag.Length)); context.Comments.Add (comment); } } }; context.EditorParser.CurrentParseTree.Accept (new CallbackVisitor (action)); var parser = new MonoDevelop.Xml.Parser.XmlParser (new WebFormsRootState (), true); try { parser.Parse (new StringReader (sb.ToString ())); } catch (Exception ex) { LoggingService.LogError ("Unhandled error parsing html in Razor document '" + (context.FileName ?? "") + "'", ex); } context.HtmlParsedDocument = parser.Nodes.GetRoot (); errors.AddRange (parser.Errors); }
static IEnumerable<FoldingRegion> GetFoldingRegions (RazorCSharpParserContext context) { var foldingRegions = new List<FoldingRegion> (); GetHtmlFoldingRegions (context, foldingRegions); GetRazorFoldingRegions (context, foldingRegions); return foldingRegions; }
static RazorEngineHost CreateRazorHost(RazorCSharpParserContext context) { if (context.Project != null) { var projectFile = context.Project.GetProjectFile(context.FileName); if (projectFile != null && projectFile.Generator == "RazorTemplatePreprocessor") { return(new MonoDevelop.AspNet.Razor.Generator.PreprocessedRazorHost(context.FileName) { DesignTimeMode = true, EnableLinePragmas = false, }); } } string virtualPath = "~/Views/Default.cshtml"; if (context.AspProject != null) { virtualPath = context.AspProject.LocalToVirtualPath(context.FileName); } WebPageRazorHost host = null; // Try to create host using web.config file var webConfigMap = new WebConfigurationFileMap(); if (context.AspProject != null) { var vdm = new VirtualDirectoryMapping(context.AspProject.Project.BaseDirectory.Combine("Views"), true, "web.config"); webConfigMap.VirtualDirectories.Add("/", vdm); } Configuration configuration; try { configuration = WebConfigurationManager.OpenMappedWebConfiguration(webConfigMap, "/"); } catch { configuration = null; } if (configuration != null) { //TODO: use our assemblies, not the project's var rws = configuration.GetSectionGroup(RazorWebSectionGroup.GroupName) as RazorWebSectionGroup; if (rws != null) { host = WebRazorHostFactory.CreateHostFromConfig(rws, virtualPath, context.FileName); host.DesignTimeMode = true; } } if (host == null) { host = new MvcWebPageRazorHost(virtualPath, context.FileName) { DesignTimeMode = true }; // Add default namespaces from Razor section host.NamespaceImports.Add("System.Web.Mvc"); host.NamespaceImports.Add("System.Web.Mvc.Ajax"); host.NamespaceImports.Add("System.Web.Mvc.Html"); host.NamespaceImports.Add("System.Web.Routing"); } return(host); }
static void GetHtmlFoldingRegions (RazorCSharpParserContext context, List<FoldingRegion> foldingRegions) { if (context.HtmlParsedDocument != null) { var d = new MonoDevelop.AspNet.WebForms.WebFormsParsedDocument (null, WebSubtype.Html, null, context.HtmlParsedDocument); foldingRegions.AddRange (d.Foldings); } }
void EnsureParserInitializedFor (RazorCSharpParserContext context) { if (context.EditorParser != null) return; CreateParserFor (context); }
static void GetRazorFoldingRegions (RazorCSharpParserContext context, List<FoldingRegion> foldingRegions) { var blocks = new List<Block> (); GetBlocks (context.EditorParser.CurrentParseTree, blocks); foreach (var block in blocks) { var beginLine = context.Document.GetLineByOffset (block.Start.AbsoluteIndex); var endLine = context.Document.GetLineByOffset (block.Start.AbsoluteIndex + block.Length); if (beginLine != endLine) foldingRegions.Add (new FoldingRegion (RazorUtils.GetShortName (block), new DocumentRegion (context.Document.OffsetToLocation (block.Start.AbsoluteIndex), context.Document.OffsetToLocation (block.Start.AbsoluteIndex + block.Length)))); } }
static string CreateCodeFile (RazorCSharpParserContext context) { var unit = context.CapturedArgs.GeneratorResults.GeneratedCode; System.CodeDom.Compiler.CodeDomProvider provider = context.Project != null ? context.Project.LanguageBinding.GetCodeDomProvider () : new Microsoft.CSharp.CSharpCodeProvider (); using (var sw = new StringWriter ()) { provider.GenerateCodeFromCompileUnit (unit, sw, new System.CodeDom.Compiler.CodeGeneratorOptions () { // HACK: we use true, even though razor uses false, to work around a mono bug where it omits the // line ending after "#line hidden", resulting in the unparseable "#line hiddenpublic" BlankLinesBetweenMembers = true, // matches Razor built-in settings IndentString = String.Empty, }); return sw.ToString (); } }
static void CreateCSharpParsedDocument (RazorCSharpParserContext context) { if (context.Project == null) return; context.CSharpCode = CreateCodeFile (context); context.ParsedSyntaxTree = CSharpSyntaxTree.ParseText (Microsoft.CodeAnalysis.Text.SourceText.From (context.CSharpCode)); var originalProject = TypeSystemService.GetCodeAnalysisProject (context.Project); if (originalProject != null) { string fileName = context.FileName + ".g.cs"; var documentId = TypeSystemService.GetDocumentId (originalProject.Id, fileName); if (documentId == null) { context.AnalysisDocument = originalProject.AddDocument ( fileName, context.ParsedSyntaxTree?.GetRoot ()); } else { context.AnalysisDocument = TypeSystemService.GetCodeAnalysisDocument (documentId); } } }