private static bool CanRefactor( SeparatedSyntaxListSelection <ArgumentSyntax> selection, SemanticModel semanticModel, CancellationToken cancellationToken) { for (int i = selection.StartIndex; i <= selection.EndIndex; i++) { ArgumentSyntax argument = selection.Items[i]; NameColonSyntax nameColon = argument.NameColon; if (nameColon == null || nameColon.IsMissing) { IParameterSymbol parameterSymbol = semanticModel.DetermineParameter( argument, allowParams: false, cancellationToken: cancellationToken); if (parameterSymbol != null) { return(true); } } } return(false); }
private static bool TryGetParameterInfos( ArgumentListSyntax argumentList, SemanticModel semanticModel, CancellationToken cancellationToken, out List <ParameterInfo> parameterInfos) { List <ParameterInfo> list = null; foreach (ArgumentSyntax argument in argumentList.Arguments) { IParameterSymbol parameterSymbol = semanticModel.DetermineParameter(argument, cancellationToken: cancellationToken); if (parameterSymbol != null) { (list ?? (list = new List <ParameterInfo>())).Add(new ParameterInfo(parameterSymbol, argument.Expression)); } else { parameterInfos = null; return(false); } } parameterInfos = list; return(true); }
private static List <ParameterInfo> GetParameterInfos( ArgumentListSyntax argumentList, SemanticModel semanticModel, CancellationToken cancellationToken) { var list = new List <ParameterInfo>(); foreach (ArgumentSyntax argument in argumentList.Arguments) { IParameterSymbol parameterSymbol = semanticModel.DetermineParameter(argument, cancellationToken: cancellationToken); if (parameterSymbol != null) { list.Add(new ParameterInfo(parameterSymbol, argument.Expression)); } else { return(null); } } return(list); }
private static ArgumentSyntax AddParameterName( ArgumentSyntax argument, SemanticModel semanticModel, CancellationToken cancellationToken = default) { if (argument.NameColon?.IsMissing != false) { IParameterSymbol parameterSymbol = semanticModel.DetermineParameter( argument, allowParams: false, cancellationToken: cancellationToken); if (parameterSymbol != null) { return(argument .WithNameColon( NameColon(parameterSymbol.ToDisplayString(_symbolDisplayFormat)) .WithTrailingTrivia(Space)) .WithTriviaFrom(argument)); } } return(argument); }
private static async Task <bool> CanAddParameterNameAsync( RefactoringContext context, AttributeArgumentSyntax[] arguments) { foreach (AttributeArgumentSyntax argument in arguments) { if (argument.NameColon?.IsMissing != false) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); IParameterSymbol parameterSymbol = semanticModel.DetermineParameter( argument, allowParams: false, cancellationToken: context.CancellationToken); if (parameterSymbol != null) { return(true); } } } return(false); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out ArgumentSyntax argument)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.ArgumentMustBePassedWithRefOrOutKeyword: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddOutModifierToArgument)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); IParameterSymbol parameter = semanticModel.DetermineParameter(argument, allowCandidate: true, cancellationToken: context.CancellationToken); if (parameter == null) { return; } SyntaxToken refOrOutKeyword = default; if (parameter.RefKind == RefKind.Out) { refOrOutKeyword = Token(SyntaxKind.OutKeyword); } else if (parameter.RefKind == RefKind.Ref) { refOrOutKeyword = Token(SyntaxKind.RefKeyword); } else { return; } CodeAction codeAction = CodeAction.Create( $"Add '{SyntaxFacts.GetText(refOrOutKeyword.Kind())}' modifier", cancellationToken => { ArgumentSyntax newArgument = argument .WithRefOrOutKeyword(refOrOutKeyword) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(argument, newArgument, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ArgumentShouldNotBePassedWithRefOrOutKeyword: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveRefModifier)) { return; } CodeAction codeAction = CodeAction.Create( "Remove 'ref' modifier", cancellationToken => { ArgumentSyntax newArgument = argument .WithRefOrOutKeyword(default(SyntaxToken)) .PrependToLeadingTrivia(argument.RefOrOutKeyword.GetAllTrivia()) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(argument, newArgument, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CannotConvertArgumentType: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue)) { ExpressionSyntax expression = argument.Expression; if (expression.Kind() == SyntaxKind.NullLiteralExpression && argument.Parent is ArgumentListSyntax argumentList) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ImmutableArray <IParameterSymbol> parameterSymbols = FindParameters(argumentList, semanticModel, context.CancellationToken); if (!parameterSymbols.IsDefault) { int index = argumentList.Arguments.IndexOf(argument); IParameterSymbol parameterSymbol = parameterSymbols[index]; ITypeSymbol typeSymbol = parameterSymbol.Type; if (typeSymbol.IsValueType) { CodeFixRegistrator.ReplaceNullWithDefaultValue( context, diagnostic, expression, typeSymbol, CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue); } } } } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddArgumentList)) { ExpressionSyntax expression = argument.Expression; if (expression.IsKind( SyntaxKind.IdentifierName, SyntaxKind.GenericName, SyntaxKind.SimpleMemberAccessExpression)) { InvocationExpressionSyntax invocationExpression = InvocationExpression( expression.WithoutTrailingTrivia(), ArgumentList().WithTrailingTrivia(expression.GetTrailingTrivia())); SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (semanticModel.GetSpeculativeMethodSymbol(expression.SpanStart, invocationExpression) != null) { CodeAction codeAction = CodeAction.Create( "Add argument list", cancellationToken => { ArgumentSyntax newNode = argument.WithExpression(invocationExpression); return(context.Document.ReplaceNodeAsync(argument, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.AddArgumentList)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.CreateSingletonArray)) { ExpressionSyntax expression = argument.Expression; if (expression?.IsMissing == false) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression); if (typeSymbol?.IsErrorType() == false) { foreach (ITypeSymbol typeSymbol2 in DetermineParameterTypeHelper.DetermineParameterTypes(argument, semanticModel, context.CancellationToken)) { if (!typeSymbol.Equals(typeSymbol2) && typeSymbol2 is IArrayTypeSymbol arrayType && semanticModel.IsImplicitConversion(expression, arrayType.ElementType)) { CodeAction codeAction = CodeAction.Create( "Create singleton array", cancellationToken => CreateSingletonArrayRefactoring.RefactorAsync(context.Document, expression, arrayType.ElementType, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.CreateSingletonArray)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } } } break; } case CompilerDiagnosticIdentifiers.ReadOnlyFieldCannotBePassedAsRefOrOutValue: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeFieldWritable)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(argument.Expression, context.CancellationToken); if (symbolInfo.CandidateReason != CandidateReason.NotAVariable) { return; } if (!(symbolInfo.CandidateSymbols.SingleOrDefault(shouldThrow: false) is IFieldSymbol fieldSymbol)) { return; } if (fieldSymbol.DeclaredAccessibility != Accessibility.Private) { return; } if (!(fieldSymbol.GetSyntax().Parent.Parent is FieldDeclarationSyntax fieldDeclaration)) { return; } TypeDeclarationSyntax containingTypeDeclaration = fieldDeclaration.FirstAncestor <TypeDeclarationSyntax>(); if (!argument.Ancestors().Any(f => f == containingTypeDeclaration)) { return; } ModifiersCodeFixRegistrator.RemoveModifier( context, diagnostic, fieldDeclaration, SyntaxKind.ReadOnlyKeyword, title: $"Make '{fieldSymbol.Name}' writable", additionalKey: CodeFixIdentifiers.MakeFieldWritable); break; } } } }
private static ArgumentListPair RewriteArgumentLists( ArgumentListSyntax argumentList, SemanticModel semanticModel, CancellationToken cancellationToken) { ArgumentSyntax pattern = null; ArgumentSyntax regexOptions = null; ArgumentSyntax matchTimeout = null; SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments; SeparatedSyntaxList <ArgumentSyntax> newArguments = arguments; for (int i = arguments.Count - 1; i >= 0; i--) { IParameterSymbol parameterSymbol = semanticModel.DetermineParameter(arguments[i], cancellationToken: cancellationToken); Debug.Assert(parameterSymbol != null, ""); if (parameterSymbol != null) { if (pattern == null && parameterSymbol.Type.IsString() && parameterSymbol.Name == "pattern") { pattern = arguments[i]; newArguments = newArguments.RemoveAt(i); } if (regexOptions == null && parameterSymbol.Type.Equals(semanticModel.GetTypeByMetadataName(MetadataNames.System_Text_RegularExpressions_RegexOptions))) { regexOptions = arguments[i]; newArguments = newArguments.RemoveAt(i); } if (matchTimeout == null && parameterSymbol.Type.Equals(semanticModel.GetTypeByMetadataName(MetadataNames.System_TimeSpan))) { matchTimeout = arguments[i]; newArguments = newArguments.RemoveAt(i); } } } argumentList = argumentList.WithArguments(newArguments); var arguments2 = new List <ArgumentSyntax>(); if (pattern != null) { arguments2.Add(pattern); } if (regexOptions != null) { arguments2.Add(regexOptions); } if (matchTimeout != null) { arguments2.Add(matchTimeout); } return(new ArgumentListPair(argumentList, ArgumentList(arguments2.ToArray()))); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out ArgumentSyntax argument)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CS1620_ArgumentMustBePassedWithRefOrOutKeyword: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddOutModifierToArgument, context.Document, root.SyntaxTree)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); IParameterSymbol parameter = semanticModel.DetermineParameter(argument, allowCandidate: true, cancellationToken: context.CancellationToken); if (parameter == null) { return; } SyntaxToken refOrOutKeyword = default; if (parameter.RefKind == RefKind.Out) { refOrOutKeyword = Token(SyntaxKind.OutKeyword); } else if (parameter.RefKind == RefKind.Ref) { refOrOutKeyword = Token(SyntaxKind.RefKeyword); } else { return; } CodeAction codeAction = CodeAction.Create( $"Add '{SyntaxFacts.GetText(refOrOutKeyword.Kind())}' modifier", ct => { ArgumentSyntax newArgument = argument .WithRefOrOutKeyword(refOrOutKeyword) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(argument, newArgument, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS1615_ArgumentShouldNotBePassedWithRefOrOutKeyword: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveRefModifier, context.Document, root.SyntaxTree)) { return; } CodeAction codeAction = CodeAction.Create( "Remove 'ref' modifier", ct => { ArgumentSyntax newArgument = argument .WithRefOrOutKeyword(default(SyntaxToken)) .PrependToLeadingTrivia(argument.RefOrOutKeyword.GetAllTrivia()) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(argument, newArgument, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS0192_ReadOnlyFieldCannotBePassedAsRefOrOutValue: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeFieldWritable, context.Document, root.SyntaxTree)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(argument.Expression, context.CancellationToken); if (symbolInfo.CandidateReason != CandidateReason.NotAVariable) { return; } if (symbolInfo.CandidateSymbols.SingleOrDefault(shouldThrow: false) is not IFieldSymbol fieldSymbol) { return; } if (fieldSymbol.DeclaredAccessibility != Accessibility.Private) { return; } if (fieldSymbol.GetSyntax().Parent.Parent is not FieldDeclarationSyntax fieldDeclaration) { return; } TypeDeclarationSyntax containingTypeDeclaration = fieldDeclaration.FirstAncestor <TypeDeclarationSyntax>(); if (!argument.Ancestors().Any(f => f == containingTypeDeclaration)) { return; } ModifiersCodeFixRegistrator.RemoveModifier( context, diagnostic, fieldDeclaration, SyntaxKind.ReadOnlyKeyword, title: $"Make '{fieldSymbol.Name}' writable", additionalKey: CodeFixIdentifiers.MakeFieldWritable); break; } } } }