Example #1
0
        void HighlightNodeRanges(SyntaxNode node, SnapshotSpan span)
        {
            _SyntaxNodeRangeAdornment.AddAdornment(span, null, new GeometryAdornment(ThemeHelper.MenuHoverBackgroundColor, _View.TextViewLines.GetMarkerGeometry(span), 3));
            var p = _View.Caret.Position.BufferPosition;

            if (span.Contains(p) == false)
            {
                return;
            }
            var n = _SemanticContext.GetNode(p, false, false);

            while (n != null && node.Contains(n))
            {
                if (n.Span.Start != span.Start &&
                    n.Span.Length != span.Length)
                {
                    var nodeKind = n.Kind();
                    if (nodeKind != SyntaxKind.Block)
                    {
                        span = n.Span.CreateSnapshotSpan(_View.TextSnapshot);
                        _SyntaxNodeRangeAdornment.AddAdornment(span, null, new GeometryAdornment(ThemeHelper.MenuHoverBackgroundColor, _View.TextViewLines.GetMarkerGeometry(span), nodeKind.IsSyntaxBlock() || nodeKind.IsDeclaration() ? 1 : 0));
                    }
                }
                n = n.Parent;
            }
        }
Example #2
0
        public static IEnumerable <SuppressionRemoval> GetPotentialRemovals(SyntaxNode syntaxRoot, SyntaxNode suppressionSyntax)
        {
            if (syntaxRoot is null)
            {
                throw new ArgumentNullException(nameof(syntaxRoot));
            }
            if (suppressionSyntax is null)
            {
                throw new ArgumentNullException(nameof(suppressionSyntax));
            }

            if (!syntaxRoot.Contains(suppressionSyntax))
            {
                throw new ArgumentException("The specified suppression syntax is not contained in the specified syntax root.");
            }

            return(suppressionSyntax.Kind() switch
            {
                SyntaxKind.SuppressNullableWarningExpression =>
                GetPotentialRemovals(syntaxRoot, (PostfixUnaryExpressionSyntax)suppressionSyntax),

                SyntaxKind.PragmaWarningDirectiveTrivia =>
                new[] { GetPotentialRemoval(syntaxRoot, (PragmaWarningDirectiveTriviaSyntax)suppressionSyntax) },

                _ => Enumerable.Empty <SuppressionRemoval>(),
            });
Example #3
0
        internal static Binder GetEnclosingBinderInternalWithinRoot(SyntaxNode node, int position, Binder rootBinder, SyntaxNode root)
        {
            if (node == root)
            {
                return(rootBinder.GetBinder(node) ?? rootBinder);
            }

            Debug.Assert(root.Contains(node));

            Binder binder = null;

            for (var current = node; binder == null; current = current.ParentOrStructuredTriviaParent)
            {
                Debug.Assert(current != null); // Why were we asked for an enclosing binder for a node outside our root?
                binder = rootBinder.GetBinder(current);
                if (current == root)
                {
                    break;
                }
            }

            binder = binder ?? rootBinder.GetBinder(root) ?? rootBinder;
            Debug.Assert(binder != null);

            return(binder);
        }
Example #4
0
        internal static Result IsExecutedBefore(this SyntaxNode node, SyntaxNode other)
        {
            if (node is null ||
                other is null)
            {
                return(Result.No);
            }

            if (node.Contains(other) &&
                node.SpanStart < other.SpanStart)
            {
                return(Result.Yes);
            }

            if (!node.SharesAncestor <MemberDeclarationSyntax>(other))
            {
                return(Result.Unknown);
            }

            var statement      = node.FirstAncestorOrSelf <StatementSyntax>();
            var otherStatement = other.FirstAncestorOrSelf <StatementSyntax>();

            if (statement == null ||
                otherStatement == null)
            {
                return(Result.Unknown);
            }

            var block      = statement.Parent as BlockSyntax;
            var otherBlock = otherStatement.Parent as BlockSyntax;

            if (block == null && otherBlock == null)
            {
                return(Result.No);
            }

            if (ReferenceEquals(block, otherBlock) ||
                otherBlock?.Contains(node) == true ||
                block?.Contains(other) == true)
            {
                var firstAnon = node.FirstAncestor <AnonymousFunctionExpressionSyntax>();
                var otherAnon = other.FirstAncestor <AnonymousFunctionExpressionSyntax>();
                if (!ReferenceEquals(firstAnon, otherAnon))
                {
                    return(Result.Yes);
                }

                return(statement.SpanStart < otherStatement.SpanStart
                    ? Result.Yes
                    : Result.No);
            }

            return(Result.No);
        }
 private static bool IsInPropertyInitialization(
     SyntaxNode declarationSyntax,
     SyntaxNode node
     ) =>
 declarationSyntax.IsKind(SyntaxKind.PropertyDeclaration) &&
 declarationSyntax.Contains(node);
Example #6
0
        private static SyntaxNode AdjustStartingNodeAccordingToNewRoot(SyntaxNode startingNode, SyntaxNode root)
        {
            SyntaxNode result = startingNode.Contains(root) ? root : startingNode;
            if (result != root && !root.Contains(result))
            {
                result = root;
            }

            return result;
        }
Example #7
0
        private static Binder GetEnclosingBinder(SyntaxNode node, int position, Binder rootBinder, SyntaxNode root)
        {
            if (node == root)
            {
                return rootBinder.GetBinder(node) ?? rootBinder;
            }

            Debug.Assert(root.Contains(node));

            ExpressionSyntax typeOfArgument = null;
            SyntaxNode unexpectedAnonymousFunction = null;

            // Keep track of which fix-up should be applied first.  If we see a typeof expression inside an unexpected
            // anonymous function, that the typeof binder should be innermost (i.e. should have the unexpected
            // anonymous function binder as its Next).
            // NOTE: only meaningful if typeOfArgument is non-null;
            bool typeOfEncounteredBeforeUnexpectedAnonymousFunction = false;

            Binder binder = null;
            for (var current = node; binder == null; current = current.ParentOrStructuredTriviaParent)
            {
                Debug.Assert(current != null); // Why were we asked for an enclosing binder for a node outside our root?
                StatementSyntax stmt = current as StatementSyntax;
                TypeOfExpressionSyntax typeOfExpression;
                if (stmt != null)
                {
                    if (LookupPosition.IsInStatementScope(position, stmt))
                    {
                        binder = rootBinder.GetBinder(current);

                        if (binder != null)
                        {
                            binder = AdjustBinderForPositionWithinStatement(position, binder, stmt);
                        }
                    }
                }
                else if (current.Kind() == SyntaxKind.CatchClause)
                {
                    if (LookupPosition.IsInCatchBlockScope(position, (CatchClauseSyntax)current))
                    {
                        binder = rootBinder.GetBinder(current);
                    }
                }
                else if (current.Kind() == SyntaxKind.CatchFilterClause)
                {
                    if (LookupPosition.IsInCatchFilterScope(position, (CatchFilterClauseSyntax)current))
                    {
                        binder = rootBinder.GetBinder(current);
                    }
                }
                else if (current.IsAnonymousFunction())
                {
                    if (LookupPosition.IsInAnonymousFunctionOrQuery(position, current))
                    {
                        binder = rootBinder.GetBinder(current);

                        // This should only happen in error scenarios.  For example, C# does not allow array rank
                        // specifiers in types, (e.g. int[1] x;), but the syntax model does.  In order to construct
                        // an appropriate binder chain for the anonymous method body, we need to construct an
                        // ExecutableCodeBinder.
                        if (binder == null && unexpectedAnonymousFunction == null && current != root)
                        {
                            unexpectedAnonymousFunction = current;
                        }
                    }
                }
                else if (current.Kind() == SyntaxKind.TypeOfExpression &&
                    typeOfArgument == null &&
                    LookupPosition.IsBetweenTokens(
                        position,
                        (typeOfExpression = (TypeOfExpressionSyntax)current).OpenParenToken,
                        typeOfExpression.CloseParenToken))
                {
                    typeOfArgument = typeOfExpression.Type;
                    typeOfEncounteredBeforeUnexpectedAnonymousFunction = unexpectedAnonymousFunction == null;
                }
                else if (current.Kind() == SyntaxKind.SwitchSection)
                {
                    if (LookupPosition.IsInSwitchSectionScope(position, (SwitchSectionSyntax)current))
                    {
                        binder = rootBinder.GetBinder(current);
                    }
                }
                else if (current.Kind() == SyntaxKind.ArgumentList)
                {
                    var argList = (ArgumentListSyntax)current;

                    if (LookupPosition.IsBetweenTokens(position, argList.OpenParenToken, argList.CloseParenToken))
                    {
                        binder = rootBinder.GetBinder(current);
                    }
                }
                else if (current.Kind() == SyntaxKind.EqualsValueClause)
                {
                    binder = rootBinder.GetBinder(current);
                }
                else if (current.Kind() == SyntaxKind.Attribute)
                {
                    binder = rootBinder.GetBinder(current);
                }
                else if (current.Kind() == SyntaxKind.ArrowExpressionClause)
                {
                    binder = rootBinder.GetBinder(current);
                }
                else if (current is ExpressionSyntax && 
                            ((current.Parent as LambdaExpressionSyntax)?.Body == current ||
                             (current.Parent as SwitchStatementSyntax)?.Expression == current ||
                             (current.Parent as CommonForEachStatementSyntax)?.Expression == current))
                {
                    binder = rootBinder.GetBinder(current);
                }
                else if (current is VariableComponentSyntax &&
                             (current.Parent as ForEachComponentStatementSyntax)?.VariableComponent == current)
                {
                    binder = rootBinder.GetBinder(current.Parent);
                }
                else if (current is VariableComponentSyntax &&
                             (current.Parent is VariableComponentAssignmentSyntax) &&
                             (current.Parent.Parent as ForStatementSyntax)?.Deconstruction == current)
                {
                    binder = rootBinder.GetBinder(current.Parent.Parent);
                }
                else if (current is VariableComponentSyntax &&
                             (current.Parent is VariableComponentAssignmentSyntax) &&
                             (current.Parent.Parent as DeconstructionDeclarationStatementSyntax)?.Assignment.VariableComponent == current)
                {
                    binder = rootBinder.GetBinder(current.Parent.Parent);
                }
                else
                {
                    // If this ever breaks, make sure that all callers of
                    // CanHaveAssociatedLocalBinder are in sync.
                    Debug.Assert(!current.CanHaveAssociatedLocalBinder());
                }

                if (current == root)
                {
                    break;
                }
            }

            binder = binder ?? rootBinder.GetBinder(root) ?? rootBinder;
            Debug.Assert(binder != null);

            if (typeOfArgument != null && !typeOfEncounteredBeforeUnexpectedAnonymousFunction)
            {
                binder = new TypeofBinder(typeOfArgument, binder);
            }

            if (unexpectedAnonymousFunction != null)
            {
                binder = new ExecutableCodeBinder(unexpectedAnonymousFunction,
                                                  new LambdaSymbol(binder.ContainingMemberOrLambda,
                                                                   ImmutableArray<ParameterSymbol>.Empty,
                                                                   RefKind.None,
                                                                   ErrorTypeSymbol.UnknownResultType,
                                                                   unexpectedAnonymousFunction.Kind() == SyntaxKind.AnonymousMethodExpression ? MessageID.IDS_AnonMethod : MessageID.IDS_Lambda,
                                                                   unexpectedAnonymousFunction,
                                                                   isSynthesized: false),
                                                  binder);
            }

            if (typeOfArgument != null && typeOfEncounteredBeforeUnexpectedAnonymousFunction)
            {
                binder = new TypeofBinder(typeOfArgument, binder);
            }

            return binder;
        }
Example #8
0
        private static bool ContainsConditionalDirectiveTrivia(SyntaxNode node)
        {
            for (var currentDirective = node.GetFirstDirective(); currentDirective != null && node.Contains(currentDirective); currentDirective = currentDirective.GetNextDirective())
            {
                switch (currentDirective.Kind())
                {
                case SyntaxKind.IfDirectiveTrivia:
                case SyntaxKind.ElseDirectiveTrivia:
                case SyntaxKind.ElifDirectiveTrivia:
                case SyntaxKind.EndIfDirectiveTrivia:
                    return(true);
                }
            }

            return(false);
        }
Example #9
0
        private static void ComputeChangeTypeAndAddAwait(
            CodeFixContext context,
            Diagnostic diagnostic,
            VariableDeclarationSyntax variableDeclaration,
            TypeSyntax type,
            ExpressionSyntax expression,
            ITypeSymbol typeSymbol,
            SemanticModel semanticModel)
        {
            if (!typeSymbol.OriginalDefinition.EqualsOrInheritsFromTaskOfT())
            {
                return;
            }

            if (!(semanticModel.GetEnclosingSymbol(variableDeclaration.SpanStart, context.CancellationToken) is IMethodSymbol methodSymbol))
            {
                return;
            }

            if (!methodSymbol.MethodKind.Is(MethodKind.Ordinary, MethodKind.LocalFunction))
            {
                return;
            }

            SyntaxNode node = GetSyntax();

            if (node == null)
            {
                return;
            }

            SyntaxNode bodyOrExpressionBody = GetBodyOrExpressionBody();

            if (bodyOrExpressionBody == null)
            {
                return;
            }

            foreach (SyntaxNode descendant in bodyOrExpressionBody.DescendantNodes())
            {
                if (descendant.IsKind(SyntaxKind.ReturnStatement))
                {
                    var returnStatement = (ReturnStatementSyntax)descendant;

                    if (returnStatement
                        .Expression?
                        .WalkDownParentheses()
                        .IsKind(SyntaxKind.AwaitExpression) == false)
                    {
                        return;
                    }
                }
            }

            ITypeSymbol typeArgument = ((INamedTypeSymbol)typeSymbol).TypeArguments[0];

            CodeAction codeAction = CodeAction.Create(
                $"Change type to '{SymbolDisplay.ToMinimalDisplayString(typeArgument, semanticModel, type.SpanStart, SymbolDisplayFormats.Default)}' and add await",
                cancellationToken => ChangeTypeAndAddAwait(context.Document, node, variableDeclaration, type, expression, typeArgument, semanticModel, cancellationToken),
                EquivalenceKey.Create(diagnostic, CodeFixIdentifiers.ChangeTypeAccordingToInitializer, "AddAwait"));

            context.RegisterCodeFix(codeAction, diagnostic);

            SyntaxNode GetSyntax()
            {
                foreach (SyntaxReference syntaxReference in methodSymbol.DeclaringSyntaxReferences)
                {
                    SyntaxNode syntax = syntaxReference.GetSyntax(context.CancellationToken);

                    if (syntax.Contains(variableDeclaration))
                    {
                        return(syntax);
                    }
                }

                return(null);
            }

            SyntaxNode GetBodyOrExpressionBody()
            {
                switch (node.Kind())
                {
                case SyntaxKind.MethodDeclaration:
                    return(((MethodDeclarationSyntax)node).BodyOrExpressionBody());

                case SyntaxKind.LocalFunctionStatement:
                    return(((LocalFunctionStatementSyntax)node).BodyOrExpressionBody());
                }

                Debug.Fail(node.Kind().ToString());

                return(null);
            }
        }