Beispiel #1
0
        private static SyntaxTokenList GetOriginalModifiers(CSharp.CSharpSyntaxNode decl)
        {
            if (decl != null)
            {
                switch (decl.Kind)
                {
                case SyntaxKind.FieldDeclaration:
                    return(((CSharp.Syntax.FieldDeclarationSyntax)decl).Modifiers);

                case SyntaxKind.MethodDeclaration:
                case SyntaxKind.DestructorDeclaration:
                    return(((CSharp.Syntax.MethodDeclarationSyntax)decl).Modifiers);

                case SyntaxKind.ConstructorDeclaration:
                    return(((CSharp.Syntax.ConstructorDeclarationSyntax)decl).Modifiers);

                case SyntaxKind.JavaNormalClassDeclaration:
                    return(((CSharp.Syntax.JavaNormalClassDeclarationSyntax)decl).Modifier.JavaModifiers);

                case SyntaxKind.JavaNormalInterfaceDeclaration:
                    return(((CSharp.Syntax.JavaNormalInterfaceDeclarationSyntax)decl).Modifier.JavaModifiers);
                }
            }

            return(default(SyntaxTokenList));
        }
        private SyntaxTree WithChanges(SourceText newText, IReadOnlyList <TextChangeRange> changes)
        {
            if (changes == null)
            {
                throw new ArgumentNullException("changes");
            }

            var oldTree = this;

            // if changes is entire text do a full reparse
            if (changes.Count == 1 && changes[0].Span == new TextSpan(0, this.Length) && changes[0].NewLength == newText.Length)
            {
                // parser will do a full parse if we give it no changes
                changes = null;
                oldTree = null;
            }

            using (var lexer = new InternalSyntax.Lexer(newText, this.Options))
            {
                CSharp.CSharpSyntaxNode oldRoot = oldTree != null?oldTree.GetRoot() : null;

                using (var parser = new InternalSyntax.LanguageParser(lexer, oldRoot, changes))
                {
                    var compilationUnit = (CompilationUnitSyntax)parser.ParseCompilationUnit().CreateRed();
                    var tree            = new ParsedSyntaxTree(newText, this.FilePath, this.Options, compilationUnit, parser.Directives);
                    tree.VerifySource(changes);
                    return(tree);
                }
            }
        }
Beispiel #3
0
        private static bool CanReuseParameter(CSharp.Syntax.ParameterSyntax parameter)
        {
            // cannot reuse a node that possibly ends in an expression
            if (parameter.Default != null)
            {
                return(false);
            }

            // cannot reuse lambda parameters as normal parameters (parsed with
            // different rules)
            CSharp.CSharpSyntaxNode parent = parameter.Parent;
            if (parent != null)
            {
                if (parent.Kind == SyntaxKind.SimpleLambdaExpression)
                {
                    return(false);
                }

                CSharp.CSharpSyntaxNode grandparent = parent.Parent;
                if (grandparent != null && grandparent.Kind == SyntaxKind.ParenthesizedLambdaExpression)
                {
                    Debug.Assert(parent.Kind == SyntaxKind.ParameterList);
                    return(false);
                }
            }

            return(true);
        }
Beispiel #4
0
        private static TextChangeRange ExtendToAffectedRange(
            CSharp.CSharpSyntaxNode oldTree,
            TextChangeRange changeRange
            )
        {
            // we will increase affected range of the change by the number of lookahead tokens
            // original code in Blender seem to imply the lookahead at the end of a node is 1 token
            // max. TODO: 1 token lookahead seems a bit too optimistic. Increase if needed.
            const int maxLookahead = 1;

            // check if change is not after the end. TODO: there should be an assert somewhere about
            // changes starting at least at the End of old tree
            var lastCharIndex = oldTree.FullWidth - 1;

            // Move the start of the change range so that it is contained within oldTree.
            var start = Math.Max(Math.Min(changeRange.Span.Start, lastCharIndex), 0);

            // the first iteration aligns us with the change start. subsequent iteration move us to
            // the left by maxLookahead tokens.  We only need to do this as long as we're not at the
            // start of the tree.  Also, the tokens we get back may be zero width.  In that case we
            // need to keep on looking backward.
            for (var i = 0; start > 0 && i <= maxLookahead;)
            {
                var token = oldTree.FindToken(start, findInsideTrivia: false);
                Debug.Assert(
                    token.Kind() != SyntaxKind.None,
                    "how could we not get a real token back?"
                    );

                start = Math.Max(0, token.Position - 1);

                // Only increment i if we got a non-zero width token.  Otherwise, we want to just do
                // this again having moved back one space.
                if (token.FullWidth > 0)
                {
                    i++;
                }
            }

            if (IsInsideInterpolation(oldTree, start))
            {
                // If the changed range starts inside an interpolated string, we
                // move the start of the change range to the beginning of the line so that any
                // interpolated string literal in the changed range will be scanned in its entirety.
                var column =
                    oldTree.SyntaxTree.GetLineSpan(new TextSpan(start, 0)).Span.Start.Character;
                start = Math.Max(start - column, 0);
            }

            var finalSpan   = TextSpan.FromBounds(start, changeRange.Span.End);
            var finalLength = changeRange.NewLength + (changeRange.Span.Start - start);

            return(new TextChangeRange(finalSpan, finalLength));
        }
Beispiel #5
0
        // NOTE: If you add new state, you should probably add it to ResetPoint as well.

        internal LanguageParser(
            Lexer lexer,
            CSharp.CSharpSyntaxNode oldTree,
            IEnumerable <TextChangeRange> changes,
            CancellationToken cancellationToken = default(CancellationToken))
            : base(lexer, LexerMode.Syntax, oldTree, changes, allowModeReset: false,
                   preLexIfNotIncremental: true, cancellationToken: cancellationToken)
        {
            this._syntaxFactoryContext = new SyntaxFactoryContext();
            this._syntaxFactory        = new ContextAwareSyntax(_syntaxFactoryContext);
        }
Beispiel #6
0
        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;
        }
Beispiel #7
0
        private static bool IsInsideInterpolation(CSharp.CSharpSyntaxNode oldTree, int start)
        {
            var token = oldTree.FindToken(start, findInsideTrivia: false);

            for (var parent = token.Parent; // for each parent
                 parent != null;
                 parent = parent.Parent)
            {
                if (parent.Kind() == SyntaxKind.InterpolatedStringExpression)
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #8
0
 private BlendedNode CreateBlendedNode(CSharp.CSharpSyntaxNode node, SyntaxToken token)
 {
     return(new BlendedNode(
                node,
                token,
                new Blender(
                    _lexer,
                    _oldTreeCursor,
                    _changes,
                    _newPosition,
                    _changeDelta,
                    _newDirectives,
                    _oldDirectives,
                    _newLexerDrivenMode
                    )
                ));
 }
Beispiel #9
0
        //#endif

        internal XSharpLanguageParser(
            String FileName,
            SourceText Text,
            CSharpParseOptions options,
            CSharp.CSharpSyntaxNode oldTree,
            IEnumerable <TextChangeRange> changes,
            LexerMode lexerMode = LexerMode.Syntax,
            CancellationToken cancellationToken = default(CancellationToken))
            : base(/*lexer*/ null, lexerMode, oldTree, changes, allowModeReset: false,
                   preLexIfNotIncremental: true, cancellationToken: cancellationToken)
        {
            _syntaxFactoryContext = new SyntaxFactoryContext();
            _syntaxFactory        = new ContextAwareSyntax(_syntaxFactoryContext);
            _text          = Text;
            _fileName      = FileName;
            _options       = options;
            _isScript      = options.Kind == SourceCodeKind.Script;
            _isMacroScript = _isScript && options.MacroScript;
        }
Beispiel #10
0
        protected SyntaxParser(
            Lexer lexer,
            LexerMode mode,
            CSharp.CSharpSyntaxNode oldTree,
            IEnumerable <TextChangeRange> changes,
            bool allowModeReset,
            bool preLexIfNotIncremental         = false,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            this.lexer             = lexer;
            _mode                  = mode;
            _allowModeReset        = allowModeReset;
            this.cancellationToken = cancellationToken;
            _currentNode           = default(BlendedNode);
            _isIncremental         = oldTree != null;

            if (this.IsIncremental || allowModeReset)
            {
                _firstBlender  = new Blender(lexer, oldTree, changes);
                _blendedTokens = s_blendedNodesPool.Allocate();
            }
            else
            {
                _firstBlender = default(Blender);
                _lexedTokens  = new ArrayElement <SyntaxToken> [32];
            }

#if !XSHARP
            // PreLex is not cancellable.
            //      If we may cancel why would we aggressively lex ahead?
            //      Cancellations in a constructor make disposing complicated
            //
            // So, if we have a real cancellation token, do not do prelexing.
            if (preLexIfNotIncremental && !this.IsIncremental && !cancellationToken.CanBeCanceled)
            {
                this.PreLex();
            }
#endif
        }
Beispiel #11
0
 public static Cursor FromRoot(CSharp.CSharpSyntaxNode node)
 {
     return(new Cursor(node, indexInParent: 0));
 }
 internal BlendedNode(CSharp.CSharpSyntaxNode node, SyntaxToken token, Blender blender)
 {
     this.Node = node;
     this.Token = token;
     this.Blender = blender;
 }
 private static bool IsIncomplete(CSharp.CSharpSyntaxNode node)
 {
     // A node is incomplete if the last token in it is a missing token.  Use the green
     // node to determine this as it's much faster than going through the red API.
     return(node.Green.GetLastTerminal().IsMissing);
 }
Beispiel #14
0
 internal BlendedNode(CSharp.CSharpSyntaxNode node, SyntaxToken token, Blender blender)
 {
     this.Node    = node;
     this.Token   = token;
     this.Blender = blender;
 }
Beispiel #15
0
 private static CSharp.CSharpSyntaxNode GetOldParent(CSharp.CSharpSyntaxNode node)
 {
     return(node != null ? node.Parent : null);
 }
Beispiel #16
0
 private BlendedNode CreateBlendedNode(CSharp.CSharpSyntaxNode node, SyntaxToken token)
 {
     return(new BlendedNode(node, token,
                            new Blender(lexer, oldTreeCursor, changes, newPosition, changeDelta, newLexerDrivenMode)));
 }