internal ParsedSyntaxTree( SourceText textOpt, Encoding encodingOpt, SourceHashAlgorithm checksumAlgorithm, string path, CSharpParseOptions options, CSharpSyntaxNode root, Syntax.InternalSyntax.DirectiveStack directives, ImmutableDictionary <string, ReportDiagnostic> diagnosticOptions, bool?isGeneratedCode, bool cloneRoot) { 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; _diagnosticOptions = diagnosticOptions ?? EmptyDiagnosticOptions; if (isGeneratedCode is bool b) { _isGenerationConfigured = true; _lazyIsGeneratedCode = b.ToThreeState(); } this.SetDirectiveStack(directives); }
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); }
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) { this.oldTreeCursor = this.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 = this.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. this.newPosition += currentNodeOrToken.FullWidth; this.oldTreeCursor = this.oldTreeCursor.MoveToNextSibling(); this.newDirectives = currentNodeOrToken.ApplyDirectives(this.newDirectives); this.oldDirectives = currentNodeOrToken.ApplyDirectives(this.oldDirectives); blendedNode = CreateBlendedNode( node: (CSharp.CSharpSyntaxNode)currentNodeOrToken.AsNode(), token: (InternalSyntax.SyntaxToken)currentNodeOrToken.AsToken().Node); return(true); }
internal bool IsPreprocessorSymbolDefined(string symbolName, int position) { if (preprocessorStateChangePositions.IsDefault) { BuildPreprocessorStateChangeMap(); } int searchResult = preprocessorStateChangePositions.BinarySearch(position); InternalSyntax.DirectiveStack directives; if (searchResult < 0) { searchResult = (~searchResult) - 1; if (searchResult >= 0) { directives = preprocessorStates[searchResult]; } else { directives = InternalSyntax.DirectiveStack.Empty; } } else { directives = preprocessorStates[searchResult]; } return(IsPreprocessorSymbolDefined(directives, symbolName)); }
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) { this.lexer = blender.lexer; this.oldTreeCursor = blender.oldTreeCursor; this.changes = blender.changes; this.newPosition = blender.newPosition; this.changeDelta = blender.changeDelta; this.newDirectives = blender.newDirectives; this.oldDirectives = blender.oldDirectives; this.newLexerDrivenMode = blender.newLexerDrivenMode; }
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; }
public Blender( Lexer lexer, CSharp.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; }
internal Syntax.InternalSyntax.DirectiveStack ApplyDirectives(Syntax.InternalSyntax.DirectiveStack stack) { if (this.IsToken) { return(this.token.ApplyDirectives(stack)); } if (this.nodeOrParent != null) { return(this.nodeOrParent.Green.ApplyDirectives(stack)); } return(stack); }
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); }
internal virtual DirectiveStack ApplyDirectives(DirectiveStack stack) { if (this.ContainsDirectives) { for (int i = 0, n = this.SlotCount; i < n; i++) { var child = this.GetSlot(i); if (child != null) { stack = ((CSharpSyntaxNode)child).ApplyDirectives(stack); } } } return(stack); }
public Blender(Lexer lexer, CSharp.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 (this.lexer.TextWindow.Position != this.newPosition) { this.lexer.Reset(this.newPosition, this.newDirectives); } if (mode >= LexerMode.XmlDocComment) { mode |= this.newLexerDrivenMode; } var token = this.lexer.Lex(ref mode); this.newDirectives = this.lexer.Directives; this.newLexerDrivenMode = mode & (LexerMode.MaskXmlDocCommentLocation | LexerMode.MaskXmlDocCommentStyle); return(token); }
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 override DirectiveStack ApplyDirectives(DirectiveStack stack) { if (this.ContainsDirectives) { var leading = this.GetLeadingTrivia(); if (leading != null && leading.ContainsDirectives) { stack = leading.ApplyDirectives(stack); } var trailing = this.GetTrailingTrivia(); if (trailing != null && trailing.ContainsDirectives) { stack = trailing.ApplyDirectives(stack); } } return(stack); }
private void SkipOldToken() { Debug.Assert(!this.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. this.oldTreeCursor = this.oldTreeCursor.MoveToFirstToken(); var node = this.oldTreeCursor.CurrentNodeOrToken; // Now, skip past it. this.changeDelta += node.FullWidth; this.oldDirectives = node.ApplyDirectives(this.oldDirectives); this.oldTreeCursor = this.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(this.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); }
internal DirectiveParser(Lexer lexer, DirectiveStack context) : base(lexer, LexerMode.Directive, null, null, false) { this.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(path != null); Debug.Assert(textOpt == null || textOpt.Encoding == encodingOpt && textOpt.ChecksumAlgorithm == checksumAlgorithm); _lazyText = textOpt; _encodingOpt = encodingOpt; _checksumAlgorithm = checksumAlgorithm; _options = options; _path = path; _root = cloneRoot ? this.CloneNodeAsRoot(root) : root; _hasCompilationUnitRoot = root.Kind() == SyntaxKind.CompilationUnit; this.SetDirectiveStack(directives); }
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; }
internal void SetDirectiveStack(InternalSyntax.DirectiveStack directives) { this.directives = directives; this.hasDirectives = true; }
public void Reset(int position, DirectiveStack directives) { this.TextWindow.Reset(position); _directives = directives; }
private SyntaxToken LexNewToken(LexerMode mode) { if (this.lexer.TextWindow.Position != this.newPosition) { this.lexer.Reset(this.newPosition, this.newDirectives); } if (mode >= LexerMode.XmlDocComment) { mode |= this.newLexerDrivenMode; } var token = this.lexer.Lex(ref mode); this.newDirectives = this.lexer.Directives; this.newLexerDrivenMode = mode & (LexerMode.MaskXmlDocCommentLocation | LexerMode.MaskXmlDocCommentStyle); return token; }
internal virtual DirectiveStack ApplyDirectives(DirectiveStack stack) { return(ApplyDirectives(this, stack)); }
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) { this.oldTreeCursor = this.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 = this.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. this.newPosition += currentNodeOrToken.FullWidth; this.oldTreeCursor = this.oldTreeCursor.MoveToNextSibling(); this.newDirectives = currentNodeOrToken.ApplyDirectives(this.newDirectives); this.oldDirectives = currentNodeOrToken.ApplyDirectives(this.oldDirectives); blendedNode = CreateBlendedNode( node: (CSharp.CSharpSyntaxNode)currentNodeOrToken.AsNode(), token: (InternalSyntax.SyntaxToken)currentNodeOrToken.AsToken().Node); return true; }
internal override DirectiveStack ApplyDirectives(DirectiveStack stack) { return stack.Add(new Directive(this)); }
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 override DirectiveStack ApplyDirectives(DirectiveStack stack) { return(stack.Add(new Directive(this))); }
internal void SetDirectiveStack(InternalSyntax.DirectiveStack directives) { _directives = directives; _hasDirectives = true; }
private CSharpSyntaxNode LexSingleDirective( bool isActive, bool endIsActive, bool afterFirstToken, bool afterNonWhitespaceOnLine, ref SyntaxListBuilder triviaList) { if (SyntaxFacts.IsWhitespace(TextWindow.PeekChar())) { this.Start(); this.AddTrivia(this.ScanWhitespace(), ref triviaList); } CSharpSyntaxNode directive; var saveMode = _mode; using (var dp = new DirectiveParser(this, _directives)) { directive = dp.ParseDirective(isActive, endIsActive, afterFirstToken, afterNonWhitespaceOnLine); } this.AddTrivia(directive, ref triviaList); _directives = directive.ApplyDirectives(_directives); _mode = saveMode; return directive; }
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.Unreachable; } } #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 source, string path, CSharpParseOptions options, CSharpSyntaxNode root, Syntax.InternalSyntax.DirectiveStack directives, bool cloneRoot = true) { Debug.Assert(root != null); Debug.Assert(options != null); Debug.Assert(path != null); this.text = source; this.options = options; this.path = path; this.root = cloneRoot ? this.CloneNodeAsRoot(root) : root; this.hasCompilationUnitRoot = root.Kind == SyntaxKind.CompilationUnit; this.SetDirectiveStack(directives); }