private bool TryTakeOldNodeOrToken( bool asToken, out BlendedNode blendedNode) { // If we're asking for tokens, then first move down to our first token. (if we're // already at a token, then this won't do anything). if (asToken) { _oldTreeCursor = _oldTreeCursor.MoveToFirstToken(); } // See if we're actually able to reuse this node or token. If not, our caller will // move the cursor to the next appropriate position and will try again. var currentNodeOrToken = _oldTreeCursor.CurrentNodeOrToken; if (!CanReuse(currentNodeOrToken)) { blendedNode = default(BlendedNode); return(false); } // We can reuse this node or token. Move us forward in the new text, and move to the // next sibling. _newPosition += currentNodeOrToken.FullWidth; _oldTreeCursor = _oldTreeCursor.MoveToNextSibling(); _newDirectives = currentNodeOrToken.ApplyDirectives(_newDirectives); _oldDirectives = currentNodeOrToken.ApplyDirectives(_oldDirectives); blendedNode = CreateBlendedNode( node: (Stark.CSharpSyntaxNode)currentNodeOrToken.AsNode(), token: (InternalSyntax.SyntaxToken)currentNodeOrToken.AsToken().Node); return(true); }
private static DirectiveStack ApplyDirectivesToTrivia(GreenNode triviaList, DirectiveStack stack) { if (triviaList != null && triviaList.ContainsDirectives) { return(ApplyDirectivesToListOrNode(triviaList, stack)); } return(stack); }
internal override DirectiveStack ApplyDirectives(DirectiveStack stack) { if (this.ContainsDirectives) { stack = ApplyDirectivesToTrivia(this.GetLeadingTrivia(), stack); stack = ApplyDirectivesToTrivia(this.GetTrailingTrivia(), stack); } return(stack); }
public Reader(Blender blender) { _lexer = blender._lexer; _oldTreeCursor = blender._oldTreeCursor; _changes = blender._changes; _newPosition = blender._newPosition; _changeDelta = blender._changeDelta; _newDirectives = blender._newDirectives; _oldDirectives = blender._oldDirectives; _newLexerDrivenMode = blender._newLexerDrivenMode; }
private bool IsPreprocessorSymbolDefined(InternalSyntax.DirectiveStack directives, string symbolName) { switch (directives.IsDefined(symbolName)) { case InternalSyntax.DefineState.Defined: return(true); case InternalSyntax.DefineState.Undefined: return(false); default: return(this.Options.PreprocessorSymbols.Contains(symbolName)); } }
internal static DirectiveStack ApplyDirectives(GreenNode node, DirectiveStack stack) { if (node.ContainsDirectives) { for (int i = 0, n = node.SlotCount; i < n; i++) { var child = node.GetSlot(i); if (child != null) { stack = ApplyDirectivesToListOrNode(child, stack); } } } return(stack); }
public Blender(Lexer lexer, Stark.CSharpSyntaxNode oldTree, IEnumerable <TextChangeRange> changes) { Debug.Assert(lexer != null); _lexer = lexer; _changes = ImmutableStack.Create <TextChangeRange>(); if (changes != null) { // TODO: Consider implementing NormalizedChangeCollection for TextSpan. the real // reason why we are collapsing is because we want to extend change ranges and // cannot allow them to overlap. This does not seem to be a big deal since multiple // changes are infrequent and typically close to each other. However if we have // NormalizedChangeCollection for TextSpan we can have both - we can extend ranges // and not require collapsing them. NormalizedChangeCollection would also ensure // that changes are always normalized. // TODO: this is a temporary measure to prevent individual change spans from // overlapping after they are widened to effective width (+1 token at the start). // once we have normalized collection for TextSpan we will not need to collapse all // the change spans. var collapsed = TextChangeRange.Collapse(changes); // extend the change to its affected range. This will make it easier // to filter out affected nodes since we will be able simply check // if node intersects with a change. var affectedRange = ExtendToAffectedRange(oldTree, collapsed); _changes = _changes.Push(affectedRange); } if (oldTree == null) { // start at lexer current position if no nodes specified _oldTreeCursor = new Cursor(); _newPosition = lexer.TextWindow.Position; } else { _oldTreeCursor = Cursor.FromRoot(oldTree).MoveToFirstChild(); _newPosition = 0; } _changeDelta = 0; _newDirectives = default(DirectiveStack); _oldDirectives = default(DirectiveStack); _newLexerDrivenMode = 0; }
private SyntaxToken LexNewToken(LexerMode mode) { if (_lexer.TextWindow.Position != _newPosition) { _lexer.Reset(_newPosition, _newDirectives); } if (mode >= LexerMode.XmlDocComment) { mode |= _newLexerDrivenMode; } var token = _lexer.Lex(ref mode); _newDirectives = _lexer.Directives; _newLexerDrivenMode = mode & (LexerMode.MaskXmlDocCommentLocation | LexerMode.MaskXmlDocCommentStyle); return(token); }
private void SkipOldToken() { Debug.Assert(!_oldTreeCursor.IsFinished); // First, move down so that we're actually pointing at a token. If we're already // pointing at a token, then we'll just stay there. _oldTreeCursor = _oldTreeCursor.MoveToFirstToken(); var node = _oldTreeCursor.CurrentNodeOrToken; // Now, skip past it. _changeDelta += node.FullWidth; _oldDirectives = node.ApplyDirectives(_oldDirectives); _oldTreeCursor = _oldTreeCursor.MoveToNextSibling(); // If our cursor is now after any changes, then just skip past them while upping // the changeDelta length. This will let us know that we need to read tokens // from the new text to try to sync up. this.SkipPastChanges(); }
public bool IncrementallyEquivalent(DirectiveStack other) { var mine = SkipInsignificantDirectives(_directives); var theirs = SkipInsignificantDirectives(other._directives); bool mineHasAny = mine != null && mine.Any(); bool theirsHasAny = theirs != null && theirs.Any(); while (mineHasAny && theirsHasAny) { if (!mine.Head.IncrementallyEquivalent(theirs.Head)) { return(false); } mine = SkipInsignificantDirectives(mine.Tail); theirs = SkipInsignificantDirectives(theirs.Tail); mineHasAny = mine != null && mine.Any(); theirsHasAny = theirs != null && theirs.Any(); } return(mineHasAny == theirsHasAny); }
private Blender( Lexer lexer, Cursor oldTreeCursor, ImmutableStack <TextChangeRange> changes, int newPosition, int changeDelta, DirectiveStack newDirectives, DirectiveStack oldDirectives, LexerMode newLexerDrivenMode) { Debug.Assert(lexer != null); Debug.Assert(changes != null); Debug.Assert(newPosition >= 0); _lexer = lexer; _oldTreeCursor = oldTreeCursor; _changes = changes; _newPosition = newPosition; _changeDelta = changeDelta; _newDirectives = newDirectives; _oldDirectives = oldDirectives; _newLexerDrivenMode = newLexerDrivenMode & (LexerMode.MaskXmlDocCommentLocation | LexerMode.MaskXmlDocCommentStyle); }
internal virtual DirectiveStack ApplyDirectives(DirectiveStack stack) { return(ApplyDirectives(this, stack)); }
internal static DirectiveStack ApplyDirectivesToListOrNode(GreenNode listOrNode, DirectiveStack stack) { // If we have a list of trivia, then that node is not actually a CSharpSyntaxNode. // Just defer to our standard ApplyDirectives helper as it will do the appropriate // walking of this list to ApplyDirectives to the children. if (listOrNode.RawKind == GreenNode.ListKind) { return(ApplyDirectives(listOrNode, stack)); } else { // Otherwise, we must have an actual piece of C# trivia. Just apply the stack // to that node directly. return(((CSharpSyntaxNode)listOrNode).ApplyDirectives(stack)); } }
internal void SetDirectiveStack(InternalSyntax.DirectiveStack directives) { _directives = directives; _hasDirectives = true; }
internal override DirectiveStack ApplyDirectives(DirectiveStack stack) { return(stack.Add(new Directive(this))); }
private void BuildPreprocessorStateChangeMap() { InternalSyntax.DirectiveStack currentState = InternalSyntax.DirectiveStack.Empty; var positions = ArrayBuilder <int> .GetInstance(); var states = ArrayBuilder <InternalSyntax.DirectiveStack> .GetInstance(); foreach (DirectiveTriviaSyntax directive in this.GetRoot().GetDirectives(d => { switch (d.Kind()) { case SyntaxKind.IfDirectiveTrivia: case SyntaxKind.ElifDirectiveTrivia: case SyntaxKind.ElseDirectiveTrivia: case SyntaxKind.EndIfDirectiveTrivia: case SyntaxKind.DefineDirectiveTrivia: case SyntaxKind.UndefDirectiveTrivia: return(true); default: return(false); } })) { currentState = directive.ApplyDirectives(currentState); switch (directive.Kind()) { case SyntaxKind.IfDirectiveTrivia: // #if directive doesn't affect the set of defined/undefined symbols break; case SyntaxKind.ElifDirectiveTrivia: states.Add(currentState); positions.Add(((ElifDirectiveTriviaSyntax)directive).ElifKeyword.SpanStart); break; case SyntaxKind.ElseDirectiveTrivia: states.Add(currentState); positions.Add(((ElseDirectiveTriviaSyntax)directive).ElseKeyword.SpanStart); break; case SyntaxKind.EndIfDirectiveTrivia: states.Add(currentState); positions.Add(((EndIfDirectiveTriviaSyntax)directive).EndIfKeyword.SpanStart); break; case SyntaxKind.DefineDirectiveTrivia: states.Add(currentState); positions.Add(((DefineDirectiveTriviaSyntax)directive).Name.SpanStart); break; case SyntaxKind.UndefDirectiveTrivia: states.Add(currentState); positions.Add(((UndefDirectiveTriviaSyntax)directive).Name.SpanStart); break; default: throw ExceptionUtilities.UnexpectedValue(directive.Kind()); } } #if DEBUG int currentPos = -1; foreach (int pos in positions) { Debug.Assert(currentPos < pos); currentPos = pos; } #endif ImmutableInterlocked.InterlockedInitialize(ref _preprocessorStates, states.ToImmutableAndFree()); ImmutableInterlocked.InterlockedInitialize(ref _preprocessorStateChangePositions, positions.ToImmutableAndFree()); }
internal DirectiveParser(Lexer lexer, DirectiveStack context) : base(lexer, LexerMode.Directive, null, null, false) { _context = context; }
internal ParsedSyntaxTree(SourceText textOpt, Encoding encodingOpt, SourceHashAlgorithm checksumAlgorithm, string path, CSharpParseOptions options, CSharpSyntaxNode root, Syntax.InternalSyntax.DirectiveStack directives, bool cloneRoot = true) { Debug.Assert(root != null); Debug.Assert(options != null); Debug.Assert(textOpt == null || textOpt.Encoding == encodingOpt && textOpt.ChecksumAlgorithm == checksumAlgorithm); _lazyText = textOpt; _encodingOpt = encodingOpt ?? textOpt?.Encoding; _checksumAlgorithm = checksumAlgorithm; _options = options; _path = path ?? string.Empty; _root = cloneRoot ? this.CloneNodeAsRoot(root) : root; _hasCompilationUnitRoot = root.Kind() == SyntaxKind.CompilationUnit; this.SetDirectiveStack(directives); }