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; } }
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>(), });
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); }
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);
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; }
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; }
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); }
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); } }