Пример #1
0
        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());
                }
            }
        }
Пример #2
0
        /// <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;
        }
Пример #3
0
        public static void EvaluateParseTree(Block actualRoot, Block expectedRoot)
        {
            // Evaluate the result
            var collector = new ErrorCollector();

            if (expectedRoot == null)
            {
                Assert.Null(actualRoot);
            }
            else
            {
                // Link all the nodes
                expectedRoot.LinkNodes();
                Assert.NotNull(actualRoot);
                EvaluateSyntaxTreeNode(collector, actualRoot, expectedRoot);
                if (collector.Success)
                {
                    WriteTraceLine("Parse Tree Validation Succeeded:" + Environment.NewLine + collector.Message);
                }
                else
                {
                    Assert.True(false, Environment.NewLine + collector.Message);
                }
            }
        }
Пример #4
0
        public override void GenerateStartParentChunk(Block target, ChunkGeneratorContext context)
        {
            var chunk = context.ChunkTreeBuilder.StartParentChunk<CodeAttributeChunk>(target);

            chunk.Attribute = Name;
            chunk.Prefix = Prefix;
            chunk.Suffix = Suffix;
        }
Пример #5
0
        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();
        }
Пример #6
0
        public virtual void VisitBlock(Block block)
        {
            VisitStartBlock(block);

            // Perf: Avoid allocating an enumerator.
            for (var i = 0; i < block.Children.Count; i++)
            {
                block.Children[i].Accept(this);
            }
            VisitEndBlock(block);
        }
Пример #7
0
        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 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;
        }
Пример #9
0
        protected override bool CanRewrite(Block block)
        {
            var gen = block.ChunkGenerator as AttributeBlockChunkGenerator;
            if (gen != null && block.Children.Count > 0)
            {
                // Perf: Avoid allocating an enumerator.
                for (var i = 0; i < block.Children.Count; i++)
                {
                    if (!IsLiteralAttributeValue(block.Children[i]))
                    {
                        return false;
                    }
                }

                return true;
            }

            return false;
        }
Пример #10
0
        private static bool IsTypeAttribute(Block block)
        {
            var span = block.Children.First() as Span;

            if (span == null)
            {
                return false;
            }

            var trimmedStartContent = span.Content.TrimStart();
            if (trimmedStartContent.StartsWith("type", StringComparison.OrdinalIgnoreCase) &&
                (trimmedStartContent.Length == 4 ||
                ValidAfterTypeAttributeNameCharacters.Contains(trimmedStartContent[4])))
            {
                return true;
            }

            return false;
        }
Пример #11
0
        /// <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));
            }
        }
Пример #12
0
        public Block TagHelperBlock(
            string tagName,
            TagMode tagMode,
            SourceLocation start,
            Block startTag,
            SyntaxTreeNode[] children,
            Block endTag)
        {
            var builder = new TagHelperBlockBuilder(
                tagName,
                tagMode,
                attributes: new List<TagHelperAttributeNode>(),
                children: children)
            {
                Start = start,
                SourceStartTag = startTag,
                SourceEndTag = endTag
            };

            return builder.Build();
        }
Пример #13
0
        /// <summary>
        /// Instantiates a new <see cref="GeneratorResults"/> 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>
        /// <param name="codeGeneratorResult">The results of generating code for the document.</param>
        /// <param name="chunkTree">A <see cref="ChunkTree"/> for the document.</param>
        public GeneratorResults(Block document,
                                IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
                                ErrorSink errorSink,
                                CodeGeneratorResult codeGeneratorResult,
                                ChunkTree chunkTree)
            : base(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));
            }

            if (codeGeneratorResult == null)
            {
                throw new ArgumentNullException(nameof(codeGeneratorResult));
            }

            if (chunkTree == null)
            {
                throw new ArgumentNullException(nameof(chunkTree));
            }

            GeneratedCode = codeGeneratorResult.Code;
            DesignTimeLineMappings = codeGeneratorResult.DesignTimeLineMappings;
            ChunkTree = chunkTree;
        }
Пример #14
0
        protected override SyntaxTreeNode RewriteBlock(BlockBuilder parent, Block block)
        {
            var newBlock = new BlockBuilder(block);
            newBlock.Children.Clear();
            var ws = block.Children.FirstOrDefault() as Span;
            IEnumerable<SyntaxTreeNode> newNodes = block.Children;
            if (ws.Content.All(Char.IsWhiteSpace))
            {
                // Add this node to the parent
                var builder = new SpanBuilder(ws);
                builder.ClearSymbols();
                FillSpan(builder, ws.Start, ws.Content);
                parent.Children.Add(builder.Build());

                // Remove the old whitespace node
                newNodes = block.Children.Skip(1);
            }

            foreach (SyntaxTreeNode node in newNodes)
            {
                newBlock.Children.Add(node);
            }
            return newBlock.Build();
        }
Пример #15
0
        private static void EvaluateBlock(ErrorCollector collector, Block actual, Block expected)
        {
            if (actual.Type != expected.Type || !expected.ChunkGenerator.Equals(actual.ChunkGenerator))
            {
                AddMismatchError(collector, actual, expected);
            }
            else
            {
                if (actual is TagHelperBlock)
                {
                    EvaluateTagHelperBlock(collector, actual as TagHelperBlock, expected as TagHelperBlock);
                }

                AddPassedMessage(collector, expected);
                using (collector.Indent())
                {
                    var expectedNodes = expected.Children.GetEnumerator();
                    var actualNodes = actual.Children.GetEnumerator();
                    while (expectedNodes.MoveNext())
                    {
                        if (!actualNodes.MoveNext())
                        {
                            collector.AddError("{0} - FAILED :: No more elements at this node", expectedNodes.Current);
                        }
                        else
                        {
                            EvaluateSyntaxTreeNode(collector, actualNodes.Current, expectedNodes.Current);
                        }
                    }
                    while (actualNodes.MoveNext())
                    {
                        collector.AddError("End of Node - FAILED :: Found Node: {0}", actualNodes.Current);
                    }
                }
            }
        }
Пример #16
0
 public static void EvaluateResults(ParserResults results, Block expectedRoot, IList<RazorError> expectedErrors)
 {
     EvaluateParseTree(results.Document, expectedRoot);
     EvaluateRazorErrors(results.ParserErrors, expectedErrors);
 }
Пример #17
0
 public static void EvaluateResults(ParserResults results, Block expectedRoot)
 {
     EvaluateResults(results, expectedRoot, null);
 }
Пример #18
0
        protected virtual void RunParseTest(string document, Func<ParserBase, Action> parserActionSelector, Block expectedRoot, IList<RazorError> expectedErrors, bool designTimeParser, Func<ParserContext, ParserBase> parserSelector = null)
        {
            // Create the source
            var results = RunParse(document, parserActionSelector, designTimeParser, parserSelector);

            // Evaluate the results
            if (!ReferenceEquals(expectedRoot, IgnoreOutput))
            {
                EvaluateResults(results, expectedRoot, expectedErrors);
            }
        }
Пример #19
0
 protected virtual void ParseDocumentTest(string document, Block expectedRoot, bool designTimeParser, params RazorError[] expectedErrors)
 {
     RunParseTest(document, parser => parser.ParseDocument, expectedRoot, expectedErrors, designTimeParser, parserSelector: c => c.MarkupParser);
 }
Пример #20
0
        private void CodeBlock(bool acceptTerminatingBrace, Block block)
        {
            EnsureCurrent();
            while (!EndOfFile && !At(CSharpSymbolType.RightBrace))
            {
                // Parse a statement, then return here
                Statement();
                EnsureCurrent();
            }

            if (EndOfFile)
            {
                Context.OnError(
                    block.Start,
                    RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF(block.Name, '}', '{'),
                    length: 1  /* { OR } */);
            }
            else if (acceptTerminatingBrace)
            {
                Assert(CSharpSymbolType.RightBrace);
                Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
                AcceptAndMoveNext();
            }
        }
Пример #21
0
 private void CodeBlock(Block block)
 {
     CodeBlock(true, block);
 }
Пример #22
0
 private void HandleStatement(Block block, CSharpSymbolType type)
 {
     switch (type)
     {
         case CSharpSymbolType.RazorCommentTransition:
             Output(SpanKind.Code);
             RazorComment();
             Statement(block);
             break;
         case CSharpSymbolType.LeftBrace:
             // Verbatim Block
             block = block ?? new Block(RazorResources.BlockName_Code, CurrentLocation);
             AcceptAndMoveNext();
             CodeBlock(block);
             break;
         case CSharpSymbolType.Keyword:
             // Keyword block
             HandleKeyword(false, StandardStatement);
             break;
         case CSharpSymbolType.Transition:
             // Embedded Expression block
             EmbeddedExpression();
             break;
         case CSharpSymbolType.RightBrace:
             // Possible end of Code Block, just run the continuation
             break;
         case CSharpSymbolType.Comment:
             AcceptAndMoveNext();
             break;
         default:
             // Other statement
             StandardStatement();
             break;
     }
 }
Пример #23
0
        private void Statement(Block block)
        {
            Span.EditHandler.AcceptedCharacters = AcceptedCharacters.Any;

            // Accept whitespace but always keep the last whitespace node so we can put it back if necessary
            var lastWhitespace = AcceptWhiteSpaceInLines();
            Debug.Assert(lastWhitespace == null ||
                (lastWhitespace.Start.AbsoluteIndex + lastWhitespace.Content.Length == CurrentLocation.AbsoluteIndex));

            if (EndOfFile)
            {
                if (lastWhitespace != null)
                {
                    Accept(lastWhitespace);
                }
                return;
            }

            var type = CurrentSymbol.Type;
            var loc = CurrentLocation;

            // Both cases @: and @:: are triggered as markup, second colon in second case will be triggered as a plain text
            var isSingleLineMarkup = type == CSharpSymbolType.Transition &&
                (NextIs(CSharpSymbolType.Colon, CSharpSymbolType.DoubleColon));

            var isMarkup = isSingleLineMarkup ||
                type == CSharpSymbolType.LessThan ||
                (type == CSharpSymbolType.Transition && NextIs(CSharpSymbolType.LessThan));

            if (Context.DesignTimeMode || !isMarkup)
            {
                // CODE owns whitespace, MARKUP owns it ONLY in DesignTimeMode.
                if (lastWhitespace != null)
                {
                    Accept(lastWhitespace);
                }
            }
            else
            {
                var nextSymbol = Lookahead(1);

                // MARKUP owns whitespace EXCEPT in DesignTimeMode.
                PutCurrentBack();

                // Put back the whitespace unless it precedes a '<text>' tag.
                if (nextSymbol != null &&
                    !string.Equals(nextSymbol.Content, SyntaxConstants.TextTagName, StringComparison.Ordinal))
                {
                    PutBack(lastWhitespace);
                }
            }

            if (isMarkup)
            {
                if (type == CSharpSymbolType.Transition && !isSingleLineMarkup)
                {
                    Context.OnError(
                        loc,
                        RazorResources.ParseError_AtInCode_Must_Be_Followed_By_Colon_Paren_Or_Identifier_Start,
                        length: 1 /* @ */);
                }

                // Markup block
                Output(SpanKind.Code);
                if (Context.DesignTimeMode && CurrentSymbol != null &&
                    (CurrentSymbol.Type == CSharpSymbolType.LessThan || CurrentSymbol.Type == CSharpSymbolType.Transition))
                {
                    PutCurrentBack();
                }
                OtherParserBlock();
            }
            else
            {
                // What kind of statement is this?
                HandleStatement(block, type);
            }
        }
Пример #24
0
        private void ConditionalBlock(Block block)
        {
            AcceptAndMoveNext();
            AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));

            // Parse the condition, if present (if not present, we'll let the C# compiler complain)
            if (AcceptCondition())
            {
                AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
                ExpectCodeBlock(block);
            }
        }
Пример #25
0
 protected virtual void ParseBlockTest(string document, Block expectedRoot, params RazorError[] expectedErrors)
 {
     ParseBlockTest(document, expectedRoot, false, expectedErrors);
 }
Пример #26
0
 protected virtual void ParseBlockTest(string document, Block expectedRoot)
 {
     ParseBlockTest(document, expectedRoot, false, null);
 }
Пример #27
0
 protected virtual void ParseBlockTest(string document, Block expectedRoot, bool designTimeParser)
 {
     ParseBlockTest(document, expectedRoot, designTimeParser, null);
 }
Пример #28
0
        private void FilterableCatchBlock()
        {
            Assert(CSharpKeyword.Catch);

            var block = new Block(CurrentSymbol);

            // Accept "catch"
            AcceptAndMoveNext();
            AcceptWhile(IsValidStatementSpacingSymbol);

            // Parse the catch condition if present. If not present, let the C# compiler complain.
            if (AcceptCondition())
            {
                AcceptWhile(IsValidStatementSpacingSymbol);

                if (At(CSharpKeyword.When))
                {
                    // Accept "when".
                    AcceptAndMoveNext();
                    AcceptWhile(IsValidStatementSpacingSymbol);

                    // Parse the filter condition if present. If not present, let the C# compiler complain.
                    if (!AcceptCondition())
                    {
                        // Incomplete condition.
                        return;
                    }

                    AcceptWhile(IsValidStatementSpacingSymbol);
                }

                ExpectCodeBlock(block);
            }
        }
Пример #29
0
 protected virtual void ParseBlockTest(string document, Block expectedRoot, bool designTimeParser, params RazorError[] expectedErrors)
 {
     RunParseTest(document, parser => parser.ParseBlock, expectedRoot, (expectedErrors ?? new RazorError[0]).ToList(), designTimeParser);
 }
Пример #30
0
 private void ConditionalBlock(bool topLevel)
 {
     Assert(CSharpSymbolType.Keyword);
     var block = new Block(CurrentSymbol);
     ConditionalBlock(block);
     if (topLevel)
     {
         CompleteBlock();
     }
 }