public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveTypeParameter)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); TypeParameterSyntax typeParameter = root .FindNode(context.Span, getInnermostNodeForTie: true)? .FirstAncestorOrSelf <TypeParameterSyntax>(); Debug.Assert(typeParameter != null, $"{nameof(typeParameter)} is null"); if (typeParameter == null) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.TypeParameterHasSameNameAsTypeParameterFromOuterType: { TypeParameterInfo info; if (TypeParameterInfo.TryCreate(typeParameter, out info)) { CodeAction codeAction = CodeAction.Create( $"Remove type parameter '{info.Name}'", cancellationToken => { SeparatedSyntaxList <TypeParameterSyntax> parameters = info.TypeParameterList.Parameters; TypeParameterListSyntax newTypeParameterList = (parameters.Count == 1) ? default(TypeParameterListSyntax) : info.TypeParameterList.WithParameters(parameters.Remove(typeParameter)); SyntaxNode newNode = GenericDeclarationHelper.WithTypeParameterList(info.Declaration, newTypeParameterList); TypeParameterConstraintClauseSyntax constraintClause = info.ConstraintClause; if (constraintClause != null) { newNode = GenericDeclarationHelper.WithConstraintClauses(newNode, info.ConstraintClauses.Remove(constraintClause)); } return(context.Document.ReplaceNodeAsync(info.Declaration, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } } } }
private void RemoveConstraint( CodeFixContext context, Diagnostic diagnostic, TypeParameterConstraintSyntax constraint) { SeparatedSyntaxList <TypeParameterConstraintSyntax> constraints; if (GenericDeclarationHelper.TryGetContainingList(constraint, out constraints)) { CodeAction codeAction = CodeAction.Create( $"Remove constraint '{constraint}'", cancellationToken => context.Document.RemoveNodeAsync(constraint, RemoveHelper.GetRemoveOptions(constraint), cancellationToken), GetEquivalenceKey(diagnostic, constraint.Kind().ToString())); context.RegisterCodeFix(codeAction, diagnostic); } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsAnyCodeFixEnabled( CodeFixIdentifiers.RemoveConstraint, CodeFixIdentifiers.MoveConstraint)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out TypeParameterConstraintSyntax constraint)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.NewConstraintMustBeLastConstraintSpecified: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MoveConstraint)) { break; } SeparatedSyntaxList <TypeParameterConstraintSyntax> constraints; if (GenericDeclarationHelper.TryGetContainingList(constraint, out constraints)) { MoveConstraint(context, diagnostic, constraint, constraints, constraints.Count - 1); } break; } case CompilerDiagnosticIdentifiers.DuplicateConstraintForTypeParameter: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConstraint)) { RemoveConstraint(context, diagnostic, constraint); } break; } case CompilerDiagnosticIdentifiers.ClassOrStructConstraintMustComeBeforeAnyOtherConstraints: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MoveConstraint)) { break; } SeparatedSyntaxList <TypeParameterConstraintSyntax> constraints; if (GenericDeclarationHelper.TryGetContainingList(constraint, out constraints)) { if (IsDuplicateConstraint(constraint, constraints)) { RemoveConstraint(context, diagnostic, constraint); } else { MoveConstraint(context, diagnostic, constraint, constraints, 0); } } break; } case CompilerDiagnosticIdentifiers.CannotSpecifyBothConstraintClassAndClassOrStructConstraint: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConstraint)) { break; } RemoveConstraint(context, diagnostic, constraint); SeparatedSyntaxList <TypeParameterConstraintSyntax> constraintClauses; if (GenericDeclarationHelper.TryGetContainingList(constraint, out constraintClauses)) { TypeParameterConstraintSyntax classConstraint = constraintClauses.Find(SyntaxKind.ClassConstraint); if (classConstraint != null) { RemoveConstraint(context, diagnostic, classConstraint); } TypeParameterConstraintSyntax structConstraint = constraintClauses.Find(SyntaxKind.StructConstraint); if (structConstraint != null) { RemoveConstraint(context, diagnostic, structConstraint); } } break; } case CompilerDiagnosticIdentifiers.NewConstraintCannotBeUsedWithStructConstraint: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConstraint)) { break; } RemoveConstraint(context, diagnostic, constraint); SeparatedSyntaxList <TypeParameterConstraintSyntax> constraintClauses; if (GenericDeclarationHelper.TryGetContainingList(constraint, out constraintClauses)) { TypeParameterConstraintSyntax structConstraint = constraintClauses.Find(SyntaxKind.StructConstraint); RemoveConstraint(context, diagnostic, structConstraint); } break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsAnyCodeFixEnabled( 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.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConstraintClauses)) { break; } CodeAction codeAction = CodeAction.Create( "Remove constraints", cancellationToken => { SyntaxNode node = constraintClause.Parent; SyntaxNode newNode = GenericDeclarationHelper.RemoveConstraintClauses(node); return(context.Document.ReplaceNodeAsync(node, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ConstraintClauseHasAlreadyBeenSpecified: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.CombineConstraintClauses)) { break; } SyntaxList <TypeParameterConstraintClauseSyntax> constraintClauses = GenericDeclarationHelper.GetContainingList(constraintClause); int index = constraintClauses.IndexOf(constraintClause); string name = constraintClause.NameText(); TypeParameterConstraintClauseSyntax constraintClause2 = constraintClauses.FirstOrDefault(f => string.Equals(name, f.NameText(), StringComparison.Ordinal)); if (constraintClause2 == null) { break; } CodeAction codeAction = CodeAction.Create( $"Combine constraints for '{name}'", cancellationToken => { SyntaxNode node = constraintClause.Parent; TypeParameterConstraintClauseSyntax newConstraintClause = constraintClause2.WithConstraints(constraintClause2.Constraints.AddRange(constraintClause.Constraints)); SyntaxList <TypeParameterConstraintClauseSyntax> newConstraintClauses = constraintClauses .Replace(constraintClause2, newConstraintClause) .RemoveAt(index); SyntaxNode newNode = GenericDeclarationHelper.WithConstraintClauses(node, newConstraintClauses); return(context.Document.ReplaceNodeAsync(node, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }