private static GenericInfo ToMultiLine(GenericInfo info)
        {
            SyntaxNode declaration = info.Node;
            SyntaxList <TypeParameterConstraintClauseSyntax> constraintClauses = info.ConstraintClauses;

            TypeParameterConstraintClauseSyntax first = constraintClauses.First();

            SyntaxToken previousToken = declaration.FindToken(first.FullSpan.Start - 1);

            declaration = declaration.ReplaceToken(previousToken, previousToken.WithTrailingTrivia(TriviaList(NewLine())));

            SyntaxTriviaList leadingTrivia = declaration
                                             .FindToken(declaration.SpanStart)
                                             .LeadingTrivia;

            SyntaxTriviaList trivia = IncreaseIndentation(leadingTrivia.LastOrDefault());

            int count = constraintClauses.Count;

            for (int i = 0; i < count; i++)
            {
                TypeParameterConstraintClauseSyntax newNode = constraintClauses[i].WithLeadingTrivia(trivia);

                if (i < count - 1)
                {
                    newNode = newNode.WithTrailingTrivia(NewLine());
                }

                constraintClauses = constraintClauses.ReplaceAt(i, newNode);
            }

            return(SyntaxInfo.GenericInfo(declaration).WithConstraintClauses(constraintClauses));
        }
Beispiel #2
0
        public static Task <Document> RefactorAsync(
            Document document,
            BaseTypeSyntax baseType,
            CancellationToken cancellationToken)
        {
            SyntaxRemoveOptions removeOptions = RemoveHelper.DefaultRemoveOptions;

            if (baseType.GetLeadingTrivia().All(f => f.IsWhitespaceTrivia()))
            {
                removeOptions &= ~SyntaxRemoveOptions.KeepLeadingTrivia;
            }

            if (baseType.GetTrailingTrivia().All(f => f.IsWhitespaceTrivia()))
            {
                var baseList = (BaseListSyntax)baseType.Parent;

                if (baseList.Types.IsLast(baseType) &&
                    !SyntaxInfo.GenericInfo(baseList.Parent).ConstraintClauses.Any())
                {
                    removeOptions &= ~SyntaxRemoveOptions.KeepTrailingTrivia;
                }
            }

            return(document.RemoveNodeAsync(baseType, removeOptions, cancellationToken));
        }
        private static GenericInfo ToSingleLine(GenericInfo info)
        {
            SyntaxNode declaration = info.Node;

            SyntaxList <TypeParameterConstraintClauseSyntax> constraintClauses = info.ConstraintClauses;

            SyntaxToken previousToken = declaration.FindToken(constraintClauses.First().FullSpan.Start - 1);

            declaration = declaration.ReplaceToken(previousToken, previousToken.WithTrailingTrivia(TriviaList(ElasticSpace)));

            int count = constraintClauses.Count;

            for (int i = 0; i < count; i++)
            {
                TypeParameterConstraintClauseSyntax constraintClause = constraintClauses[i];

                TextSpan?span = null;

                if (i == count - 1)
                {
                    span = TextSpan.FromBounds(constraintClause.FullSpan.Start, constraintClause.Span.End);
                }

                TypeParameterConstraintClauseSyntax newNode = constraintClause
                                                              .RemoveWhitespace(span)
                                                              .WithFormatterAnnotation();

                constraintClauses = constraintClauses.ReplaceAt(i, newNode);
            }

            return(SyntaxInfo.GenericInfo(declaration).WithConstraintClauses(constraintClauses));
        }
Beispiel #4
0
        private static void AnalyzeTypeParameterList(SyntaxNodeAnalysisContext context)
        {
            var typeParameterList = (TypeParameterListSyntax)context.Node;

            GenericInfo genericInfo = SyntaxInfo.GenericInfo(typeParameterList);

            if (!genericInfo.Success)
            {
                return;
            }

            if (!genericInfo.TypeParameters.Any())
            {
                return;
            }

            if (!genericInfo.ConstraintClauses.Any())
            {
                return;
            }

            if (genericInfo.ConstraintClauses.SpanContainsDirectives())
            {
                return;
            }

            if (!IsFixable(genericInfo.TypeParameters, genericInfo.ConstraintClauses))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context,
                                               DiagnosticDescriptors.OrderTypeParameterConstraints,
                                               genericInfo.ConstraintClauses[0]);
        }
        private static Task <Document> WrapBaseListAsync(
            Document document,
            BaseListSyntax baseList,
            CancellationToken cancellationToken = default)
        {
            List <TextChange> textChanges = GetFixListChanges(
                baseList,
                baseList.ColonToken,
                baseList.Types,
                ListFixMode.Wrap,
                cancellationToken);

            if (baseList.Types.Count > 1)
            {
                GenericInfo genericInfo = SyntaxInfo.GenericInfo(baseList.Parent);

                SyntaxList <TypeParameterConstraintClauseSyntax> constraintClauses = genericInfo.ConstraintClauses;

                if (constraintClauses.Any())
                {
                    List <TextChange> textChanges2 = GetFixListChanges(
                        genericInfo.Node,
                        constraintClauses.First().WhereKeyword.GetPreviousToken(),
                        constraintClauses,
                        ListFixMode.Wrap,
                        cancellationToken);

                    textChanges.AddRange(textChanges2);
                }
            }

            return(document.WithTextChangesAsync(textChanges, cancellationToken));
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveTypeParameter))
            {
                return;
            }

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

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out TypeParameterSyntax typeParameter))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.TypeParameterHasSameNameAsTypeParameterFromOuterType:
                {
                    TypeParameterInfo typeParameterInfo = SyntaxInfo.TypeParameterInfo(typeParameter);

                    if (!typeParameterInfo.Success)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        $"Remove type parameter '{typeParameterInfo.Name}'",
                        cancellationToken =>
                        {
                            GenericInfo genericInfo = SyntaxInfo.GenericInfo(typeParameterInfo.Declaration);

                            GenericInfo newGenericInfo = genericInfo.RemoveTypeParameter(typeParameter);

                            TypeParameterConstraintClauseSyntax constraintClause = typeParameterInfo.ConstraintClause;

                            if (constraintClause != null)
                            {
                                newGenericInfo = newGenericInfo.RemoveConstraintClause(constraintClause);
                            }

                            return(context.Document.ReplaceNodeAsync(genericInfo.Declaration, newGenericInfo.Declaration, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
        private static Task <Document> RefactorAsync(
            Document document,
            SyntaxNode node,
            CancellationToken cancellationToken)
        {
            GenericInfo genericInfo = SyntaxInfo.GenericInfo(node);

            SyntaxList <TypeParameterConstraintClauseSyntax> newConstraintClauses = SortConstraints(genericInfo.TypeParameters, genericInfo.ConstraintClauses);

            GenericInfo newInfo = genericInfo.WithConstraintClauses(newConstraintClauses);

            return(document.ReplaceNodeAsync(genericInfo.Node, newInfo.Node, cancellationToken));
        }
Beispiel #8
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Diagnostic diagnostic = context.Diagnostics[0];

            if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveTypeParameter))
            {
                return;
            }

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

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out TypeParameterSyntax typeParameter))
            {
                return;
            }

            string name = typeParameter.Identifier.ValueText;

            if (string.IsNullOrEmpty(name))
            {
                return;
            }

            CodeAction codeAction = CodeAction.Create(
                $"Remove type parameter '{name}'",
                cancellationToken =>
            {
                GenericInfo genericInfo = SyntaxInfo.GenericInfo(typeParameter);

                GenericInfo newGenericInfo = genericInfo.RemoveTypeParameter(typeParameter);

                TypeParameterConstraintClauseSyntax constraintClause = genericInfo.FindConstraintClause(name);

                if (constraintClause != null)
                {
                    newGenericInfo = newGenericInfo.RemoveConstraintClause(constraintClause);
                }

                return(context.Document.ReplaceNodeAsync(genericInfo.Node, newGenericInfo.Node, cancellationToken));
            },
                GetEquivalenceKey(diagnostic));

            context.RegisterCodeFix(codeAction, diagnostic);
        }
Beispiel #9
0
        public static void ComputeRefactoring(RefactoringContext context, TypeParameterConstraintClauseSyntax constraintClause)
        {
            GenericInfo genericInfo = SyntaxInfo.GenericInfo(constraintClause);

            if (!genericInfo.Success)
            {
                return;
            }

            SyntaxList <TypeParameterConstraintClauseSyntax> constraintClauses = genericInfo.ConstraintClauses;

            if (constraintClauses.IsSingleLine())
            {
                if (constraintClauses.Count > 1)
                {
                    context.RegisterRefactoring(
                        "Wrap constraints",
                        ct =>
                    {
                        GenericInfo newInfo = WrapConstraints(genericInfo);

                        return(context.Document.ReplaceNodeAsync(genericInfo.Node, newInfo.Node, ct));
                    },
                        RefactoringDescriptors.WrapConstraintClauses);
                }
            }
            else if (constraintClause.DescendantTrivia(constraintClause.Span).All(f => f.IsWhitespaceOrEndOfLineTrivia()) &&
                     constraintClauses[0].GetFirstToken().GetPreviousToken().TrailingTrivia.IsEmptyOrWhitespace())
            {
                context.RegisterRefactoring(
                    "Unwrap constraints",
                    ct =>
                {
                    GenericInfo newInfo = UnwrapConstraints(genericInfo);

                    return(context.Document.ReplaceNodeAsync(genericInfo.Node, newInfo.Node, ct));
                },
                    RefactoringDescriptors.WrapConstraintClauses);
            }
        }
Beispiel #10
0
        public static void ComputeRefactoring(RefactoringContext context, TypeParameterConstraintClauseSyntax constraintClause)
        {
            GenericInfo genericInfo = SyntaxInfo.GenericInfo(constraintClause);

            if (!genericInfo.Success)
            {
                return;
            }

            SyntaxList <TypeParameterConstraintClauseSyntax> constraintClauses = genericInfo.ConstraintClauses;

            if (constraintClauses.IsSingleLine())
            {
                if (constraintClauses.Count > 1)
                {
                    context.RegisterRefactoring(
                        "Format constraints on separate lines",
                        cancellationToken =>
                    {
                        GenericInfo newInfo = ToMultiLine(genericInfo);

                        return(context.Document.ReplaceNodeAsync(genericInfo.Node, newInfo.Node, cancellationToken));
                    },
                        RefactoringIdentifiers.FormatConstraintClauses);
                }
            }
            else if (constraintClause.DescendantTrivia(constraintClause.Span).All(f => f.IsWhitespaceOrEndOfLineTrivia()) &&
                     constraintClauses[0].GetFirstToken().GetPreviousToken().TrailingTrivia.IsEmptyOrWhitespace())
            {
                context.RegisterRefactoring(
                    "Format constraints on a single line",
                    cancellationToken =>
                {
                    GenericInfo newInfo = ToSingleLine(genericInfo);

                    return(context.Document.ReplaceNodeAsync(genericInfo.Node, newInfo.Node, cancellationToken));
                },
                    RefactoringIdentifiers.FormatConstraintClauses);
            }
        }
Beispiel #11
0
        public static void ComputeRefactoring(RefactoringContext context, TypeParameterConstraintClauseSyntax constraintClause)
        {
            GenericInfo genericInfo = SyntaxInfo.GenericInfo(constraintClause);

            if (!genericInfo.Success)
            {
                return;
            }

            SyntaxList <TypeParameterConstraintClauseSyntax> constraintClauses = genericInfo.ConstraintClauses;

            if (constraintClauses.IsSingleLine())
            {
                if (constraintClauses.Count > 1)
                {
                    context.RegisterRefactoring(
                        "Format constraints on separate lines",
                        cancellationToken =>
                    {
                        GenericInfo newInfo = ToMultiLine(genericInfo);

                        return(context.Document.ReplaceNodeAsync(genericInfo.Node, newInfo.Node, cancellationToken));
                    });
                }
            }
            else
            {
                context.RegisterRefactoring(
                    "Format constraints on a single line",
                    cancellationToken =>
                {
                    GenericInfo newInfo = ToSingleLine(genericInfo);

                    return(context.Document.ReplaceNodeAsync(genericInfo.Node, newInfo.Node, cancellationToken));
                });
            }
        }
Beispiel #12
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsAnyEnabled(
                    CodeFixIdentifiers.RemoveConstraintClauses,
                    CodeFixIdentifiers.CombineConstraintClauses))
            {
                return;
            }

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

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out TypeParameterConstraintClauseSyntax constraintClause))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.ConstraintsAreNotAllowedOnNonGenericDeclarations:
                {
                    if (!Settings.IsEnabled(CodeFixIdentifiers.RemoveConstraintClauses))
                    {
                        break;
                    }

                    GenericInfo genericInfo = SyntaxInfo.GenericInfo(constraintClause);

                    if (!genericInfo.Success)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Remove constraints",
                        cancellationToken =>
                        {
                            GenericInfo newGenericInfo = genericInfo.RemoveAllConstraintClauses();

                            return(context.Document.ReplaceNodeAsync(genericInfo.Node, newGenericInfo.Node, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.ConstraintClauseHasAlreadyBeenSpecified:
                {
                    if (!Settings.IsEnabled(CodeFixIdentifiers.CombineConstraintClauses))
                    {
                        break;
                    }

                    GenericInfo genericInfo = SyntaxInfo.GenericInfo(constraintClause);

                    int index = genericInfo.ConstraintClauses.IndexOf(constraintClause);

                    string name = constraintClause.Name.Identifier.ValueText;

                    TypeParameterConstraintClauseSyntax constraintClause2 = genericInfo.FindConstraintClause(name);

                    if (constraintClause2 == null)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        $"Combine constraints for '{name}'",
                        cancellationToken =>
                        {
                            TypeParameterConstraintClauseSyntax newConstraintClause = constraintClause2.WithConstraints(constraintClause2.Constraints.AddRange(constraintClause.Constraints));

                            SyntaxList <TypeParameterConstraintClauseSyntax> newConstraintClauses = genericInfo.ConstraintClauses
                                                                                                    .Replace(constraintClause2, newConstraintClause)
                                                                                                    .RemoveAt(index);

                            GenericInfo newGenericInfo = genericInfo.WithConstraintClauses(newConstraintClauses);

                            return(context.Document.ReplaceNodeAsync(genericInfo.Node, newGenericInfo.Node, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }