예제 #1
0
        private static IdentifierNameSyntax PadMemberAccess(
            SimpleLambdaExpressionSyntax node,
            IdentifierNameSyntax memberAccess)
        {
            // We want to make the new span
            var originalSpan = node.GetLocation().GetMappedLineSpan();

            // Start by collecting all the trivia 'inside' the expression - we need to tack that on the end, but
            // if it ends with a newline, don't include that.
            var innerTrivia = SyntaxFactory.TriviaList(node.DescendantTrivia(descendIntoChildren: n => true));

            if (innerTrivia.Count > 0 && innerTrivia[innerTrivia.Count - 1].IsKind(SyntaxKind.EndOfLineTrivia))
            {
                innerTrivia = innerTrivia.RemoveAt(innerTrivia.Count - 1);
            }

            memberAccess = memberAccess.WithTrailingTrivia(innerTrivia);

            // If everything is all on one line, then make sure the spans are the same, to compensate
            // for the expression potentially being longer than the variable name.
            var lineSpan = originalSpan.EndLinePosition.Line - originalSpan.StartLinePosition.Line;

            if (lineSpan == 0)
            {
                var padding        = node.Span.Length - memberAccess.FullSpan.Length;
                var trailingTrivia =
                    SyntaxFactory.TriviaList(memberAccess.GetTrailingTrivia())
                    .Add(SyntaxFactory.Whitespace(new string(' ', padding)))
                    .AddRange(node.GetTrailingTrivia());

                return
                    (memberAccess
                     .WithLeadingTrivia(node.GetLeadingTrivia())
                     .WithTrailingTrivia(trailingTrivia));
            }
            else
            {
                // If everything isn't on the same line, we need to pad out the last line.
                var padding =
                    originalSpan.EndLinePosition.Character -
                    originalSpan.StartLinePosition.Character;

                var trailingTrivia =
                    SyntaxFactory.TriviaList(memberAccess.GetTrailingTrivia())
                    .Add(SyntaxFactory.Whitespace(new string(' ', padding)))
                    .AddRange(node.GetTrailingTrivia());

                return
                    (memberAccess
                     .WithLeadingTrivia(node.GetLeadingTrivia())
                     .WithTrailingTrivia(trailingTrivia));
            }
        }
예제 #2
0
        public override SyntaxNode VisitObjectCreationExpression(ObjectCreationExpressionSyntax node)
        {
            if (node.Initializer == null || IsAnonymousType(node))
            {
                return(base.VisitObjectCreationExpression(node));
            }

            ObjectCreationExpressionSyntax newNode = (ObjectCreationExpressionSyntax)base.VisitObjectCreationExpression(node);

            var openBrace  = newNode.Initializer.OpenBraceToken;
            var closeBrace = newNode.Initializer.CloseBraceToken;

            IdentifierNameSyntax obj = IdentifierName("_obj_");

            var constructObject = GenerateObject(newNode.Type.WithoutTrailingTrivia(), obj.Identifier, node.ArgumentList)
                                  .WithTrailingTrivia(openBrace.TrailingTrivia)
                                  .WithLeadingTrivia((newNode.ArgumentList?.GetTrailingTrivia() ?? newNode.Type.GetTrailingTrivia()).AddRange(openBrace.LeadingTrivia));

            StatementSyntax[] statements = GetInitialiserFunctionStatements(node, newNode, obj);

            var returnObject = ReturnStatement(obj.WithLeadingTrivia(Space)).WithLeadingTrivia(closeBrace.LeadingTrivia);

            var func = GenerateFunction(constructObject, statements, returnObject);

            requiresSystemUsing = true;
            return(GenerateInvocation(newNode, func));
        }
예제 #3
0
            public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
            {
                // We only care about xml doc comments
                var leadingTrivia = CanHaveDocComments(node) ? VisitList(node.GetLeadingTrivia()) : node.GetLeadingTrivia();

                if (_namespaceMembers.Contains(node.Identifier.Text))
                {
                    var expanded = Simplifier.Expand <SyntaxNode>(node, _model, _workspace, cancellationToken: _cancellationToken);
                    return(expanded.WithLeadingTrivia(leadingTrivia));
                }

                return(node.WithLeadingTrivia(leadingTrivia));
            }
예제 #4
0
        private static IdentifierNameSyntax PadMemberAccess(
            SimpleLambdaExpressionSyntax node,
            IdentifierNameSyntax memberAccess)
        {
            // We want to make the new span
            var originalSpan = node.GetLocation().GetMappedLineSpan();

            var charactersToExclude = memberAccess.Identifier.Text.Length;
            var triviaList          = new SyntaxTriviaList();

            // Go through each token and
            // 1. Append leading trivia
            // 2. Append the same number of whitespace as the length of the token text
            // 3. Append trailing trivia
            foreach (var token in node.DescendantTokens())
            {
                if (token.HasLeadingTrivia)
                {
                    triviaList = triviaList.AddRange(token.LeadingTrivia);
                }

                // Need to exclude the length of the member name from the padding.
                var padding = token.Text.Length;
                if (padding > charactersToExclude)
                {
                    padding            -= charactersToExclude;
                    charactersToExclude = 0;
                }
                else
                {
                    charactersToExclude -= padding;
                    padding              = 0;
                }

                if (padding > 0)
                {
                    triviaList = triviaList.Add(SyntaxFactory.Whitespace(new string(' ', padding)));
                }

                if (token.HasTrailingTrivia)
                {
                    triviaList = triviaList.AddRange(token.TrailingTrivia);
                }
            }

            return(memberAccess
                   .WithLeadingTrivia(node.GetLeadingTrivia())
                   .WithTrailingTrivia(triviaList));
        }
예제 #5
0
            public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
            {
                ISymbol referencedSymbol = this.model.GetSymbolInfo(node, this.cancellationToken).Symbol;

                // Static members don't have to be qualified
                if (referencedSymbol == null || referencedSymbol.IsStatic)
                {
                    return(base.VisitIdentifierName(node));
                }

                // Check is the name already qualified. If so, no further action is needed (only top-most identifier may be qualified)
                // Considers:
                // a.>b<.foo() -> a.b.foo()
                if (node.Ancestors().OfType <MemberAccessExpressionSyntax>().Any(n => n.Name.DescendantNodesAndSelf().Contains(node)))
                {
                    return(base.VisitIdentifierName(node));
                }

                // Considers:
                // >a<.b.foo() -> newParameter.a.b.foo()
                if (referencedSymbol.Kind == CommonSymbolKind.Field ||
                    referencedSymbol.Kind == CommonSymbolKind.Method ||
                    referencedSymbol.Kind == CommonSymbolKind.Property ||
                    referencedSymbol.Kind == CommonSymbolKind.Event)
                {
                    // Special case: constructor of different type is an unqualified and non-static member
                    if (referencedSymbol.Kind == CommonSymbolKind.Method)
                    {
                        MethodSymbol method = (MethodSymbol)referencedSymbol;
                        if (method.MethodKind == MethodKind.Constructor)
                        {
                            return(base.VisitIdentifierName(node));
                        }
                    }

                    // Create new context with leading trivia of old context
                    IdentifierNameSyntax parameterIdentifier = Syntax.IdentifierName(this.newParameterNameToken)
                                                               .WithLeadingTrivia(node.GetLeadingTrivia());

                    // And remove leading trivia from old context
                    IdentifierNameSyntax context = node.WithLeadingTrivia();

                    return(Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, parameterIdentifier, context));
                }

                return(base.VisitIdentifierName(node));
            }
        private static ExpressionStatementSyntax ExpressionRewriter(
            this ExpressionStatementSyntax expression, SemanticModel model,
            string from = null, string to = null, IdentifierNameSyntax identifier = null,
            Func <InvocationExpressionSyntax, InvocationExpressionSyntax> func = null)
        {
            if (!(expression.Expression is InvocationExpressionSyntax invocation))
            {
                return(expression);
            }

            if (invocation.Expression.Kind() != SyntaxKind.SimpleMemberAccessExpression)
            {
                return(expression);
            }

            if (!invocation.Expression.ToString().Equals(from, StringComparison.OrdinalIgnoreCase))
            {
                return(expression);
            }

            if (invocation.Expression is MemberAccessExpressionSyntax mae)
            {
                if (identifier != null)
                {
                    identifier = identifier.WithLeadingTrivia(mae.Expression.GetLeadingTrivia());
                    expression = expression.ReplaceNode(expression.Expression,
                                                        expression.Expression.ReplaceNode(mae, mae.WithExpression(identifier)));
                }

                expression = expression.ReplaceNode(expression.Expression, invocation.ReplaceNode(mae, mae.WithName(IdentifierName(to))));
            }

            if (func != null)
            {
                expression = expression.ReplaceNode(expression.Expression, func((InvocationExpressionSyntax)expression.Expression));
            }

            expression = expression.RewriteAssertMessage(model);
            return(expression);
        }
        private async Task<Document> AddNullableComment(Document document, TypeConstraintSyntax typeConstraintNode, CancellationToken cancellationToken)
        {
            var constraintClause = (TypeParameterConstraintClauseSyntax)typeConstraintNode.Parent;

            TypeConstraintSyntax[] otherTypeConstraints = constraintClause.ChildNodes().OfType<TypeConstraintSyntax>().Except(new[] { typeConstraintNode }).ToArray();

            SyntaxNode root = await document.GetSyntaxRootAsync().ConfigureAwait(false);

            IdentifierNameSyntax idNameSyntax = constraintClause.ChildNodes().OfType<IdentifierNameSyntax>().First();

            SyntaxToken identifierToken = typeConstraintNode.ChildNodes().First().ChildTokens().First();

            TypeParameterConstraintClauseSyntax newConstraintClause;

            if (otherTypeConstraints.Length > 0)
            {
                // Only this type constraint must be removed, since the where clause contains others

                // Adding the starting comment before the type constraint
                SyntaxToken newIdentifierToken = SyntaxFactory.Identifier(identifierToken.LeadingTrivia.Add(SyntaxFactory.Comment(NullableReferenceTypeAnalyzer.NullableSyntaxMarker.Start)),
                                                                          SyntaxKind.IdentifierName, identifierToken.Text, identifierToken.ValueText,
                                                                          SyntaxTriviaList.Empty);

                TypeConstraintSyntax newNode = typeConstraintNode.ReplaceToken(identifierToken, newIdentifierToken);

                // Moving the new type constraint to the first of list
                SeparatedSyntaxList<TypeParameterConstraintSyntax> newConstraintList = SyntaxFactory.SeparatedList<TypeParameterConstraintSyntax>(otherTypeConstraints.Prepend(newNode));
                newConstraintClause = SyntaxFactory.TypeParameterConstraintClause(idNameSyntax.WithLeadingTrivia(SyntaxFactory.Space)).WithConstraints(newConstraintList);

                // Adding the end type constraint after the first comma.
                SyntaxToken firstCommaToken = newConstraintClause.ChildTokens().First(token => token.IsKind(SyntaxKind.CommaToken));
                SyntaxToken newCommaToken = SyntaxFactory.Token(firstCommaToken.LeadingTrivia,
                                                                SyntaxKind.CommaToken,
                                                                firstCommaToken.TrailingTrivia.Insert(0, SyntaxFactory.Comment(NullableReferenceTypeAnalyzer.NullableSyntaxMarker.End)));

                newConstraintClause = newConstraintClause.ReplaceToken(firstCommaToken, newCommaToken);
            }
            else
            {
                // the whole where clause needs to be removed, so adding the comments before and after it.

                SyntaxToken oldWhereKeyword = constraintClause.ChildTokens().First(it => it.IsKind(SyntaxKind.WhereKeyword));

                SyntaxToken newWhereKeyword = SyntaxFactory.Token(oldWhereKeyword.LeadingTrivia.Add(SyntaxFactory.Comment(NullableReferenceTypeAnalyzer.NullableSyntaxMarker.Start)),
                                                                  SyntaxKind.WhereKeyword,
                                                                  oldWhereKeyword.TrailingTrivia);

                SyntaxToken newIdentifierToken = SyntaxFactory.Identifier(identifierToken.LeadingTrivia, SyntaxKind.IdentifierName,
                                                                          identifierToken.Text, identifierToken.ValueText,
                                                                          identifierToken.TrailingTrivia.Insert(0, SyntaxFactory.Comment(NullableReferenceTypeAnalyzer.NullableSyntaxMarker.End)));

                TypeConstraintSyntax newNode = typeConstraintNode.ReplaceToken(identifierToken, newIdentifierToken);

                newConstraintClause = SyntaxFactory.TypeParameterConstraintClause(newWhereKeyword,
                                                                                  constraintClause.ChildNodes().OfType<IdentifierNameSyntax>().First(),
                                                                                  constraintClause.ChildTokens().First(it => it.IsKind(SyntaxKind.ColonToken)),
                                                                                  SyntaxFactory.SeparatedList<TypeParameterConstraintSyntax>(new[] { newNode }));
            }

            // for some reason Roslyn adds formatting annotations that results in some strange new lines being added
            // by formatter later in internal CleanupDocumentAsync method of CodeAction class.
            newConstraintClause = RemoveAnnotationFromDescendantTrivias(newConstraintClause, SyntaxAnnotation.ElasticAnnotation);

            SyntaxNode newRoot = root.ReplaceNode(constraintClause, newConstraintClause);

            Document result = document.WithSyntaxRoot(newRoot);

            return result;
        }