/// <summary> /// Instantiates a new <see cref="RewritingContext"/>. /// </summary> public RewritingContext(Block syntaxTree, ParserErrorSink errorSink) { _errors = new List<RazorError>(); SyntaxTree = syntaxTree; ErrorSink = errorSink; }
public GeneratorResults(Block document, IList<RazorError> parserErrors, CodeCompileUnit generatedCode, IDictionary<int, GeneratedCodeMapping> designTimeLineMappings) : this(parserErrors.Count == 0, document, parserErrors, generatedCode, designTimeLineMappings) { }
public override void GenerateStartBlockCode(Block target, CodeGeneratorContext context) { _writer = context.CreateCodeWriter(); string prefix = context.BuildCodeString( cw => cw.WriteHelperHeaderPrefix(context.Host.GeneratedClassContext.TemplateTypeName, context.Host.StaticHelpers)); _writer.WriteLinePragma( context.GenerateLinePragma(Signature.Location, prefix.Length, Signature.Value.Length)); _writer.WriteSnippet(prefix); _writer.WriteSnippet(Signature); if (HeaderComplete) { _writer.WriteHelperHeaderSuffix(context.Host.GeneratedClassContext.TemplateTypeName); } _writer.WriteLinePragma(null); if (HeaderComplete) { _writer.WriteReturn(); _writer.WriteStartConstructor(context.Host.GeneratedClassContext.TemplateTypeName); _writer.WriteStartLambdaDelegate(HelperWriterName); } _statementCollectorToken = context.ChangeStatementCollector(AddStatementToHelper); _oldWriter = context.TargetWriterName; context.TargetWriterName = HelperWriterName; }
public BlockBuilder(Block original) { Type = original.Type; Children = new List<SyntaxTreeNode>(original.Children); Name = original.Name; CodeGenerator = original.CodeGenerator; }
public override void VisitBlock(Block block) { if (CanRewrite(block)) { var newNode = RewriteBlock(_blocks.Peek(), block); if (newNode != null) { _blocks.Peek().Children.Add(newNode); } } else { // Not rewritable. var builder = new BlockBuilder(block); builder.Children.Clear(); _blocks.Push(builder); base.VisitBlock(block); Debug.Assert(ReferenceEquals(builder, _blocks.Peek())); if (_blocks.Count > 1) { _blocks.Pop(); _blocks.Peek().Children.Add(builder.Build()); } } }
/// <summary> /// Instantiates a new <see cref="ParserResults"/> instance. /// </summary> /// <param name="success"><c>true</c> if parsing was successful, <c>false</c> otherwise.</param> /// <param name="document">The <see cref="Block"/> for the syntax tree.</param> /// <param name="tagHelperDescriptors"> /// The <see cref="TagHelperDescriptor"/>s that apply to the current Razor document. /// </param> /// <param name="errorSink"> /// The <see cref="ErrorSink"/> used to collect <see cref="RazorError"/>s encountered when parsing the /// current Razor document. /// </param> protected ParserResults(bool success, Block document, IEnumerable<TagHelperDescriptor> tagHelperDescriptors, ErrorSink errorSink) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (tagHelperDescriptors == null) { throw new ArgumentNullException(nameof(tagHelperDescriptors)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } Success = success; Document = document; TagHelperDescriptors = tagHelperDescriptors; ErrorSink = errorSink; ParserErrors = errorSink.Errors; Prefix = tagHelperDescriptors.FirstOrDefault()?.Prefix; }
public override void GenerateStartBlockCode(Block target, CodeGeneratorContext context) { if (context.Host.DesignTimeMode) { return; // Don't generate anything! } context.FlushBufferedStatement(); context.AddStatement(context.BuildCodeString(cw => { if (!String.IsNullOrEmpty(context.TargetWriterName)) { cw.WriteStartMethodInvoke(context.Host.GeneratedClassContext.WriteAttributeToMethodName); cw.WriteSnippet(context.TargetWriterName); cw.WriteParameterSeparator(); } else { cw.WriteStartMethodInvoke(context.Host.GeneratedClassContext.WriteAttributeMethodName); } cw.WriteStringLiteral(Name); cw.WriteParameterSeparator(); cw.WriteLocationTaggedString(Prefix); cw.WriteParameterSeparator(); cw.WriteLocationTaggedString(Suffix); // In VB, we need a line continuation cw.WriteLineContinuation(); })); }
public override void GenerateEndBlockCode(Block target, CodeGeneratorContext context) { string endBlock = context.BuildCodeString(cw => { if (context.ExpressionRenderingMode == ExpressionRenderingMode.WriteToOutput) { if (!context.Host.DesignTimeMode) { cw.WriteEndMethodInvoke(); } cw.WriteEndStatement(); } else { cw.WriteLineContinuation(); } }); context.MarkEndOfGeneratedCode(); context.BufferStatementFragment(endBlock); context.FlushBufferedStatement(); if (context.Host.EnableInstrumentation && context.ExpressionRenderingMode == ExpressionRenderingMode.WriteToOutput) { Span contentSpan = target.Children .OfType<Span>() .Where(s => s.Kind == SpanKind.Code || s.Kind == SpanKind.Markup) .FirstOrDefault(); if (contentSpan != null) { context.AddContextCall(contentSpan, context.Host.GeneratedClassContext.EndContextMethodName, false); } } }
internal static void WriteDebugTree(string sourceFile, Block document, PartialParseResult result, TextChange change, RazorEditorParser parser, bool treeStructureChanged) { if (!OutputDebuggingEnabled) { return; } RunTask(() => { string outputFileName = Normalize(sourceFile) + "_tree"; string outputPath = Path.Combine(Path.GetDirectoryName(sourceFile), outputFileName); var treeBuilder = new StringBuilder(); WriteTree(document, treeBuilder); treeBuilder.AppendLine(); treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Last Change: {0}", change); treeBuilder.AppendLine(); treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Normalized To: {0}", change.Normalize()); treeBuilder.AppendLine(); treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Partial Parse Result: {0}", result); treeBuilder.AppendLine(); if (result.HasFlag(PartialParseResult.Rejected)) { treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Tree Structure Changed: {0}", treeStructureChanged); treeBuilder.AppendLine(); } if (result.HasFlag(PartialParseResult.AutoCompleteBlock)) { treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Auto Complete Insert String: \"{0}\"", parser.GetAutoCompleteString()); treeBuilder.AppendLine(); } File.WriteAllText(outputPath, treeBuilder.ToString()); }); }
public override void GenerateStartParentChunk(Block target, ChunkGeneratorContext context) { var chunk = context.ChunkTreeBuilder.StartParentChunk<CodeAttributeChunk>(target); chunk.Attribute = Name; chunk.Prefix = Prefix; chunk.Suffix = Suffix; }
public override void GenerateStartBlockCode(Block target, CodeGeneratorContext context) { var chunk = context.CodeTreeBuilder.StartChunkBlock<HelperChunk>(target, topLevel: true); chunk.Signature = Signature; chunk.Footer = Footer; chunk.HeaderComplete = HeaderComplete; }
public virtual void VisitBlock(Block block) { VisitStartBlock(block); foreach (SyntaxTreeNode node in block.Children) { node.Accept(this); } VisitEndBlock(block); }
protected GeneratorResults(bool success, Block document, IList<RazorError> parserErrors, CodeBuilderResult codeBuilderResult) : base(success, document, parserErrors) { GeneratedCode = codeBuilderResult.Code; DesignTimeLineMappings = codeBuilderResult.DesignTimeLineMappings; }
private void RewriteTags(Block input, RewritingContext context) { // We want to start a new block without the children from existing (we rebuild them). TrackBlock(new BlockBuilder { Type = input.Type, CodeGenerator = input.CodeGenerator }); var activeTagHelpers = _trackerStack.Count; foreach (var child in input.Children) { if (child.IsBlock) { var childBlock = (Block)child; if (childBlock.Type == BlockType.Tag) { if (TryRewriteTagHelper(childBlock, context)) { continue; } // If we get to here it means that we're a normal html tag. No need to iterate any deeper into // the children of it because they wont be tag helpers. } else { // We're not an Html tag so iterate through children recursively. RewriteTags(childBlock, context); continue; } } // At this point the child is a Span or Block with Type BlockType.Tag that doesn't happen to be a // tag helper. // Add the child to current block. _currentBlock.Children.Add(child); } // We captured the number of active tag helpers at the start of our logic, it should be the same. If not // it means that there are malformed tag helpers at the top of our stack. if (activeTagHelpers != _trackerStack.Count) { // Malformed tag helpers built here will be tag helpers that do not have end tags in the current block // scope. Block scopes are special cases in Razor such as @<p> would cause an error because there's no // matching end </p> tag in the template block scope and therefore doesn't make sense as a tag helper. BuildMalformedTagHelpers(_trackerStack.Count - activeTagHelpers, context); Debug.Assert(activeTagHelpers == _trackerStack.Count); } BuildCurrentlyTrackedBlock(); }
public override void GenerateEndBlockCode(Block target, CodeGeneratorContext context) { string startBlock = context.BuildCodeString(cw => { cw.WriteEndLambdaDelegate(); cw.WriteEndMethodInvoke(); cw.WriteEndStatement(); }); context.AddStatement(startBlock); }
public override void GenerateStartBlockCode(Block target, CodeGeneratorContext context) { // Flush the buffered statement since we're interrupting it with a comment. if (!String.IsNullOrEmpty(context.CurrentBufferedStatement)) { context.MarkEndOfGeneratedCode(); context.BufferStatementFragment(context.BuildCodeString(cw => cw.WriteLineContinuation())); } context.FlushBufferedStatement(); }
protected GeneratorResults(bool success, Block document, IList<RazorError> parserErrors, CodeCompileUnit generatedCode, IDictionary<int, GeneratedCodeMapping> designTimeLineMappings) : base(success, document, parserErrors) { GeneratedCode = generatedCode; DesignTimeLineMappings = designTimeLineMappings; }
/// <summary> /// Starts the generation of a <see cref="TagHelperChunk"/>. /// </summary> /// <param name="target"> /// The <see cref="Block"/> responsible for this <see cref="TagHelperCodeGenerator"/>. /// </param> /// <param name="context">A <see cref="CodeGeneratorContext"/> instance that contains information about /// the current code generation process.</param> public override void GenerateStartBlockCode(Block target, CodeGeneratorContext context) { var tagHelperBlock = target as TagHelperBlock; if (tagHelperBlock == null) { throw new ArgumentException( RazorResources.TagHelpers_TagHelperCodeGeneartorMustBeAssociatedWithATagHelperBlock); } var attributes = new List<KeyValuePair<string, Chunk>>(); // We need to create a code generator to create chunks for each of the attributes. var codeGenerator = context.Host.CreateCodeGenerator( context.ClassName, context.RootNamespace, context.SourceFile); foreach (var attribute in tagHelperBlock.Attributes) { ChunkBlock attributeChunkValue = null; if (attribute.Value != null) { // Populates the code tree with chunks associated with attributes attribute.Value.Accept(codeGenerator); var chunks = codeGenerator.Context.CodeTreeBuilder.CodeTree.Chunks; var first = chunks.FirstOrDefault(); attributeChunkValue = new ChunkBlock { Association = first?.Association, Children = chunks, Start = first == null ? SourceLocation.Zero : first.Start }; } attributes.Add(new KeyValuePair<string, Chunk>(attribute.Key, attributeChunkValue)); // Reset the code tree builder so we can build a new one for the next attribute codeGenerator.Context.CodeTreeBuilder = new CodeTreeBuilder(); } var unprefixedTagName = tagHelperBlock.TagName.Substring(_tagHelperDescriptors.First().Prefix.Length); context.CodeTreeBuilder.StartChunkBlock( new TagHelperChunk( unprefixedTagName, tagHelperBlock.SelfClosing, attributes, _tagHelperDescriptors), target, topLevel: false); }
protected override SyntaxTreeNode RewriteBlock(BlockBuilder parent, Block block) { // Collect the content of this node var content = string.Concat(block.Children.Cast<Span>().Select(s => s.Content)); // Create a new span containing this content var span = new SpanBuilder(); span.EditHandler = new SpanEditHandler(HtmlTokenizer.Tokenize); FillSpan(span, block.Children.Cast<Span>().First().Start, content); return span.Build(); }
public override void GenerateStartBlockCode(Block target, CodeGeneratorContext context) { string startBlock = context.BuildCodeString(cw => { cw.WriteStartMethodInvoke(context.Host.GeneratedClassContext.DefineSectionMethodName); cw.WriteStringLiteral(SectionName); cw.WriteParameterSeparator(); cw.WriteStartLambdaDelegate(); }); context.AddStatement(startBlock); }
/// <summary> /// Starts the generation of a <see cref="TagHelperChunk"/>. /// </summary> /// <param name="target"> /// The <see cref="Block"/> responsible for this <see cref="TagHelperChunkGenerator"/>. /// </param> /// <param name="context">A <see cref="ChunkGeneratorContext"/> instance that contains information about /// the current chunk generation process.</param> public override void GenerateStartParentChunk(Block target, ChunkGeneratorContext context) { var tagHelperBlock = target as TagHelperBlock; Debug.Assert( tagHelperBlock != null, $"A {nameof(TagHelperChunkGenerator)} must only be used with {nameof(TagHelperBlock)}s."); var attributes = new List<KeyValuePair<string, Chunk>>(); // We need to create a chunk generator to create chunks for each of the attributes. var chunkGenerator = context.Host.CreateChunkGenerator( context.ClassName, context.RootNamespace, context.SourceFile); foreach (var attribute in tagHelperBlock.Attributes) { ParentChunk attributeChunkValue = null; if (attribute.Value != null) { // Populates the chunk tree with chunks associated with attributes attribute.Value.Accept(chunkGenerator); var chunks = chunkGenerator.Context.ChunkTreeBuilder.ChunkTree.Chunks; var first = chunks.FirstOrDefault(); attributeChunkValue = new ParentChunk { Association = first?.Association, Children = chunks, Start = first == null ? SourceLocation.Zero : first.Start }; } attributes.Add(new KeyValuePair<string, Chunk>(attribute.Key, attributeChunkValue)); // Reset the chunk tree builder so we can build a new one for the next attribute chunkGenerator.Context.ChunkTreeBuilder = new ChunkTreeBuilder(); } var unprefixedTagName = tagHelperBlock.TagName.Substring(_tagHelperDescriptors.First().Prefix.Length); context.ChunkTreeBuilder.StartParentChunk( new TagHelperChunk( unprefixedTagName, tagHelperBlock.TagMode, attributes, _tagHelperDescriptors), target, topLevel: false); }
public override void GenerateEndBlockCode(Block target, CodeGeneratorContext context) { string generatedCode = context.BuildCodeString(cw => { cw.WriteEndLambdaDelegate(); cw.WriteEndConstructor(); cw.WriteEndLambdaExpression(); }); context.BufferStatementFragment(generatedCode); context.TargetWriterName = _oldTargetWriter; }
public override void GenerateEndBlockCode(Block target, CodeGeneratorContext context) { if (context.Host.DesignTimeMode) { return; // Don't generate anything! } context.FlushBufferedStatement(); context.AddStatement(context.BuildCodeString(cw => { cw.WriteEndMethodInvoke(); cw.WriteEndStatement(); })); }
public static TagHelperBlockBuilder Rewrite( string tagName, bool validStructure, Block tag, IEnumerable<TagHelperDescriptor> descriptors, ErrorSink errorSink) { // There will always be at least one child for the '<'. var start = tag.Children.First().Start; var attributes = GetTagAttributes(tagName, validStructure, tag, descriptors, errorSink); var tagMode = GetTagMode(tagName, tag, descriptors, errorSink); return new TagHelperBlockBuilder(tagName, tagMode, start, attributes, descriptors); }
public override void GenerateStartBlockCode(Block target, CodeGeneratorContext context) { string generatedCode = context.BuildCodeString(cw => { cw.WriteStartLambdaExpression(ItemParameterName); cw.WriteStartConstructor(context.Host.GeneratedClassContext.TemplateTypeName); cw.WriteStartLambdaDelegate(TemplateWriterName); }); context.MarkEndOfGeneratedCode(); context.BufferStatementFragment(generatedCode); context.FlushBufferedStatement(); _oldTargetWriter = context.TargetWriterName; context.TargetWriterName = TemplateWriterName; }
public IEnumerable<TagHelperDescriptor> GetDescriptors(Block root) { if (root == null) { throw new ArgumentNullException(nameof(root)); } _directiveDescriptors = new List<TagHelperDirectiveDescriptor>(); // This will recurse through the syntax tree. VisitBlock(root); var resolutionContext = GetTagHelperDescriptorResolutionContext(_directiveDescriptors, _errorSink); var descriptors = _descriptorResolver.Resolve(resolutionContext); return descriptors; }
public override void GenerateStartBlockCode(Block target, CodeGeneratorContext context) { if (context.Host.DesignTimeMode) { return; // Don't generate anything! } // What kind of block is nested within string generatedCode; Block child = target.Children.Where(n => n.IsBlock).Cast<Block>().FirstOrDefault(); if (child != null && child.Type == BlockType.Expression) { _isExpression = true; generatedCode = context.BuildCodeString(cw => { cw.WriteParameterSeparator(); cw.WriteStartMethodInvoke("Tuple.Create"); cw.WriteLocationTaggedString(Prefix); cw.WriteParameterSeparator(); cw.WriteStartMethodInvoke("Tuple.Create", "System.Object", "System.Int32"); }); _oldRenderingMode = context.ExpressionRenderingMode; context.ExpressionRenderingMode = ExpressionRenderingMode.InjectCode; } else { generatedCode = context.BuildCodeString(cw => { cw.WriteParameterSeparator(); cw.WriteStartMethodInvoke("Tuple.Create"); cw.WriteLocationTaggedString(Prefix); cw.WriteParameterSeparator(); cw.WriteStartMethodInvoke("Tuple.Create", "System.Object", "System.Int32"); cw.WriteStartConstructor(context.Host.GeneratedClassContext.TemplateTypeName); cw.WriteStartLambdaDelegate(ValueWriterName); }); } context.MarkEndOfGeneratedCode(); context.BufferStatementFragment(generatedCode); _oldTargetWriter = context.TargetWriterName; context.TargetWriterName = ValueWriterName; }
public override void GenerateEndBlockCode(Block target, CodeGeneratorContext context) { if (context.Host.DesignTimeMode) { return; // Don't generate anything! } string generatedCode; if (_isExpression) { generatedCode = context.BuildCodeString(cw => { cw.WriteParameterSeparator(); cw.WriteSnippet(ValueStart.AbsoluteIndex.ToString(CultureInfo.CurrentCulture)); cw.WriteEndMethodInvoke(); cw.WriteParameterSeparator(); // literal: false - This attribute value is not a literal value, it is dynamically generated cw.WriteBooleanLiteral(false); cw.WriteEndMethodInvoke(); cw.WriteLineContinuation(); }); context.ExpressionRenderingMode = _oldRenderingMode; } else { generatedCode = context.BuildCodeString(cw => { cw.WriteEndLambdaDelegate(); cw.WriteEndConstructor(); cw.WriteParameterSeparator(); cw.WriteSnippet(ValueStart.AbsoluteIndex.ToString(CultureInfo.CurrentCulture)); cw.WriteEndMethodInvoke(); cw.WriteParameterSeparator(); // literal: false - This attribute value is not a literal value, it is dynamically generated cw.WriteBooleanLiteral(false); cw.WriteEndMethodInvoke(); cw.WriteLineContinuation(); }); } context.AddStatement(generatedCode); context.TargetWriterName = _oldTargetWriter; }
/// <inheritdoc /> protected override IEnumerable<TagHelperDescriptor> GetTagHelperDescriptors( Block documentRoot, ErrorSink errorSink) { if (documentRoot == null) { throw new ArgumentNullException(nameof(documentRoot)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } var visitor = new ViewImportsTagHelperDirectiveSpanVisitor( TagHelperDescriptorResolver, _viewImportsDirectiveDescriptors, errorSink); var descriptors = visitor.GetDescriptors(documentRoot); foreach (var descriptor in descriptors) { foreach (var attributeDescriptor in descriptor.Attributes) { if (attributeDescriptor.IsIndexer && string.Equals( attributeDescriptor.TypeName, _modelExpressionTypeName, StringComparison.Ordinal)) { errorSink.OnError( SourceLocation.Undefined, Resources.FormatMvcRazorParser_InvalidPropertyType( descriptor.TypeName, attributeDescriptor.Name, _modelExpressionTypeName), length: 0); } } } return descriptors; }
/// <summary> /// Instantiates a new <see cref="ParserResults"/> instance. /// </summary> /// <param name="document">The <see cref="Block"/> for the syntax tree.</param> /// <param name="tagHelperDescriptors"> /// The <see cref="TagHelperDescriptor"/>s that apply to the current Razor document. /// </param> /// <param name="errorSink"> /// The <see cref="ErrorSink"/> used to collect <see cref="RazorError"/>s encountered when parsing the /// current Razor document. /// </param> public ParserResults(Block document, IEnumerable<TagHelperDescriptor> tagHelperDescriptors, ErrorSink errorSink) : this(!errorSink.Errors.Any(), document, tagHelperDescriptors, errorSink) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (tagHelperDescriptors == null) { throw new ArgumentNullException(nameof(tagHelperDescriptors)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } }