public static SyntaxNode LocateOwner(this SyntaxNode node, SourceChange change) { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (change.Span.AbsoluteIndex < node.Position) { // Early escape for cases where changes overlap multiple spans // In those cases, the span will return false, and we don't want to search the whole tree // So if the current span starts after the change, we know we've searched as far as we need to return(null); } if (IsSpanKind(node)) { var editHandler = node.GetSpanContext()?.EditHandler ?? SpanEditHandler.CreateDefault(); return(editHandler.OwnsChange(node, change) ? node : null); } SyntaxNode owner = null; IEnumerable <SyntaxNode> children; if (node is MarkupStartTagSyntax startTag) { children = startTag.Children; } else if (node is MarkupEndTagSyntax endTag) { children = endTag.Children; } else if (node is MarkupTagHelperStartTagSyntax startTagHelper) { children = startTagHelper.Children; } else if (node is MarkupTagHelperEndTagSyntax endTagHelper) { children = endTagHelper.Children; } else { children = node.ChildNodes(); } foreach (var child in children) { owner = LocateOwner(child, change); if (owner != null) { break; } } return(owner); }
public SpanConstructor(SpanKindInternal kind, SourceLocation location, IEnumerable <IToken> tokens) { Builder = new SpanBuilder(location); Builder.Kind = kind; Builder.EditHandler = SpanEditHandler.CreateDefault((content) => SpanConstructor.TestTokenizer(content)); foreach (IToken sym in tokens) { Builder.Accept(sym); } }
public void Reset() { // Need to potentially allocate a new list because Span.ReplaceWith takes ownership // of the original list. _symbols = null; _symbols = new List <ISymbol>(); EditHandler = SpanEditHandler.CreateDefault((content) => Enumerable.Empty <ISymbol>()); ChunkGenerator = SpanChunkGenerator.Null; Start = SourceLocation.Undefined; }
protected override SyntaxTreeNode RewriteBlock(BlockBuilder parent, Block block) { // Collect the content of this node var builder = new StringBuilder(); for (var i = 0; i < block.Children.Count; i++) { var childSpan = (Span)block.Children[i]; builder.Append(childSpan.Content); } // Create a new span containing this content var span = new SpanBuilder(block.Children[0].Start); span.EditHandler = SpanEditHandler.CreateDefault(HtmlLanguageCharacteristics.Instance.TokenizeString); Debug.Assert(block.Children.Count > 0); var start = ((Span)block.Children[0]).Start; FillSpan(span, start, builder.ToString()); return(span.Build()); }
private void CommentSpanConfig(SpanBuilder span) { span.ChunkGenerator = SpanChunkGenerator.Null; span.EditHandler = SpanEditHandler.CreateDefault(Language.TokenizeString); }
public override SyntaxNode VisitCSharpExplicitExpression(CSharpExplicitExpressionSyntax node) { CSharpTransitionSyntax transition = null; var builder = SyntaxListBuilder <RazorSyntaxNode> .Create(); if (_rewriteAsMarkup) { // Convert transition. // Change to a MarkupChunkGenerator so that the '@' \ parenthesis is generated as part of the output. var context = node.GetSpanContext(); var newContext = new SpanContext(new MarkupChunkGenerator(), context?.EditHandler ?? SpanEditHandler.CreateDefault((content) => Enumerable.Empty <Syntax.InternalSyntax.SyntaxToken>())); var expression = SyntaxFactory.CSharpExpressionLiteral(new SyntaxList <SyntaxToken>(node.Transition.Transition)).WithSpanContext(newContext); expression = (CSharpExpressionLiteralSyntax)VisitCSharpExpressionLiteral(expression); builder.Add(expression); // Since the original transition is part of the body, we need something to take it's place. transition = SyntaxFactory.CSharpTransition(SyntaxFactory.MissingToken(SyntaxKind.Transition)); var body = (CSharpExplicitExpressionBodySyntax)node.Body; var rewrittenOpenParen = (RazorSyntaxNode)VisitRazorMetaCode(body.OpenParen); var rewrittenBody = (CSharpCodeBlockSyntax)VisitCSharpCodeBlock(body.CSharpCode); var rewrittenCloseParen = (RazorSyntaxNode)VisitRazorMetaCode(body.CloseParen); builder.Add(rewrittenOpenParen); builder.AddRange(rewrittenBody.Children); builder.Add(rewrittenCloseParen); } else { // This is the first expression of a non-string attribute like attr=@(a + b) // Below code converts this to an implicit expression to make the parens // part of the expression so that it is rendered. transition = (CSharpTransitionSyntax)Visit(node.Transition); var body = (CSharpExplicitExpressionBodySyntax)node.Body; var rewrittenOpenParen = (RazorSyntaxNode)VisitRazorMetaCode(body.OpenParen); var rewrittenBody = (CSharpCodeBlockSyntax)VisitCSharpCodeBlock(body.CSharpCode); var rewrittenCloseParen = (RazorSyntaxNode)VisitRazorMetaCode(body.CloseParen); builder.Add(rewrittenOpenParen); builder.AddRange(rewrittenBody.Children); builder.Add(rewrittenCloseParen); } var rewrittenCodeBlock = SyntaxFactory.CSharpCodeBlock(builder.ToList()); return(SyntaxFactory.CSharpImplicitExpression(transition, SyntaxFactory.CSharpImplicitExpressionBody(rewrittenCodeBlock))); }
public override SyntaxNode VisitCSharpImplicitExpression(CSharpImplicitExpressionSyntax node) { if (_rewriteAsMarkup) { var builder = SyntaxListBuilder <RazorSyntaxNode> .Create(); // Convert transition. // Change to a MarkupChunkGenerator so that the '@' \ parenthesis is generated as part of the output. var context = node.GetSpanContext(); var newContext = new SpanContext(new MarkupChunkGenerator(), context?.EditHandler ?? SpanEditHandler.CreateDefault((content) => Enumerable.Empty <Syntax.InternalSyntax.SyntaxToken>())); var expression = SyntaxFactory.CSharpExpressionLiteral(new SyntaxList <SyntaxToken>(node.Transition.Transition)).WithSpanContext(newContext); expression = (CSharpExpressionLiteralSyntax)VisitCSharpExpressionLiteral(expression); builder.Add(expression); var rewrittenBody = (CSharpCodeBlockSyntax)VisitCSharpCodeBlock(((CSharpImplicitExpressionBodySyntax)node.Body).CSharpCode); builder.AddRange(rewrittenBody.Children); // Since the original transition is part of the body, we need something to take it's place. var transition = SyntaxFactory.CSharpTransition(SyntaxFactory.MissingToken(SyntaxKind.Transition)); var rewrittenCodeBlock = SyntaxFactory.CSharpCodeBlock(builder.ToList()); return(SyntaxFactory.CSharpImplicitExpression(transition, SyntaxFactory.CSharpImplicitExpressionBody(rewrittenCodeBlock))); } return(base.VisitCSharpImplicitExpression(node)); }
public SpanConstructor With(SpanEditHandler handler) { Builder.EditHandler = handler; return(this); }
public void Reset() { EditHandler = SpanEditHandler.CreateDefault((content) => Enumerable.Empty <SyntaxToken>()); ChunkGenerator = SpanChunkGenerator.Null; }
public SpanContext(ISpanChunkGenerator chunkGenerator, SpanEditHandler editHandler) { ChunkGenerator = chunkGenerator; EditHandler = editHandler; }