public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); Diagnostic diagnostic = context.Diagnostics.First(); TextSpan diagnosticSpan = diagnostic.Location.SourceSpan; var argumentListNode = root.FindNode(diagnosticSpan) .Ancestors() .OfType <ArgumentListSyntax>() .FirstOrDefault(); var firstParameterIdentifier = argumentListNode.Arguments .First() .Expression as IdentifierNameSyntax; string firstParameterName = firstParameterIdentifier.Identifier.ValueText; string fixTitle = $"Change second argument to {firstParameterName}"; context.RegisterCodeFix( diagnostic: diagnostic, action: CodeAction.Create( title: fixTitle, equivalenceKey: fixTitle, createChangedDocument: cancellationToken => AnalyzerHelpers.ChangeArgumentAsync( context.Document, argumentListNode, firstParameterName, cancellationToken))); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); Diagnostic diagnostic = context.Diagnostics.First(); TextSpan diagnosticSpan = diagnostic.Location.SourceSpan; // Find the method that contains the EnsureArg call. var containingMethod = root.FindNode(diagnosticSpan) .Ancestors() .OfType <MemberDeclarationSyntax>() .FirstOrDefault(); if (containingMethod == null) { return; } var argumentListNode = root.FindNode(diagnosticSpan) .Ancestors() .OfType <ArgumentListSyntax>() .FirstOrDefault(); var methodParameters = AnalyzerHelpers.GetParameters(containingMethod); foreach (string parameterName in methodParameters) { string fixTitle = $"Change first argument to {parameterName}"; context.RegisterCodeFix( diagnostic: diagnostic, action: CodeAction.Create( title: fixTitle, equivalenceKey: fixTitle, createChangedDocument: cancellationToken => AnalyzerHelpers.ChangeArgumentAsync( context.Document, argumentListNode, parameterName, cancellationToken))); } }
private void AnalyzeNode(SyntaxNodeAnalysisContext context) { if (!context.Node.IsKind(SyntaxKind.InvocationExpression)) { return; } var invocationExpr = context.Node as InvocationExpressionSyntax; if (!IsNodeEnsureArgCall(context, invocationExpr)) { return; } var argumentList = invocationExpr.ArgumentList as ArgumentListSyntax; if ((argumentList?.Arguments.Count ?? 0) < 1) { return; } var firstArgumentNameSyntax = argumentList.Arguments[0].Expression as IdentifierNameSyntax; if (firstArgumentNameSyntax == null) { return; } var methodDeclaration = context.Node .Ancestors() .OfType <MemberDeclarationSyntax>() .FirstOrDefault(); string firstArgumentName = firstArgumentNameSyntax.Identifier.ValueText; if (methodDeclaration != null) { var methodParameters = AnalyzerHelpers.GetParameters(methodDeclaration); if (!methodParameters.Contains(firstArgumentName)) { var diagnostic = Diagnostic.Create( Rule1, firstArgumentNameSyntax.GetLocation(), firstArgumentName, GetMethodName(methodDeclaration)); context.ReportDiagnostic(diagnostic); } } if (argumentList.Arguments.Count >= 2) { ExpressionSyntax secondArgument = argumentList.Arguments[1].Expression; string secondParameterText = null; Location diagnosticLocation = null; // String Literal e.g. Ensure.Arg(a, "b"); if (secondArgument.IsKind(SyntaxKind.StringLiteralExpression)) { var stringLiteral = secondArgument as LiteralExpressionSyntax; secondParameterText = stringLiteral.Token.ValueText; diagnosticLocation = stringLiteral.GetLocation(); if (secondParameterText == firstArgumentName) { var diagnostic = Diagnostic.Create( Rule3, diagnosticLocation, secondParameterText); context.ReportDiagnostic(diagnostic); } } // Detect if using nameof operator e.g. Ensure.Arg(a, nameof(b)); if (secondArgument.IsKind(SyntaxKind.InvocationExpression)) { var invocationExpression = secondArgument as InvocationExpressionSyntax; var nameOfIdentifier = invocationExpression.ChildNodes().FirstOrDefault() as IdentifierNameSyntax; if (nameOfIdentifier.Identifier.ValueText == "nameof") { // Definitely nameof operater, keep digging to get to the identifier argument. var nameOfIdentifierArgument = invocationExpression.DescendantNodes() .OfType <ArgumentListSyntax>() .FirstOrDefault() ?.Arguments .FirstOrDefault() ?.Expression as IdentifierNameSyntax; secondParameterText = nameOfIdentifierArgument?.Identifier.ValueText; diagnosticLocation = invocationExpression.GetLocation(); } } if (secondParameterText != firstArgumentName) { var diagnostic = Diagnostic.Create( Rule2, diagnosticLocation, secondParameterText, firstArgumentName); context.ReportDiagnostic(diagnostic); } } var methodIdentifier = invocationExpr.Parent .ChildNodes() .OfType <IdentifierNameSyntax>() .FirstOrDefault(); if (methodIdentifier == null) { var diagnostic = Diagnostic.Create( Rule4, invocationExpr.GetLocation()); context.ReportDiagnostic(diagnostic); } }