private void ReplaceQualifiedNames() { IEnumerable <QualifiedNameSyntax> qualifiedNames = tree.GetRoot().DescendantNodes().OfType <QualifiedNameSyntax>(); foreach (QualifiedNameSyntax oldQualifiedNameNode in qualifiedNames) // iterate over all qualified names in the file { if (!(oldQualifiedNameNode.Parent is QualifiedNameSyntax)) { var qualifiedSymbolInfo = semanticModel.GetSymbolInfo(oldQualifiedNameNode); string nsString = oldQualifiedNameNode.Left.WithoutTrivia().GetText().ToString(); if (qualifiedSymbolInfo.Symbol != null) { string className = qualifiedSymbolInfo.Symbol.Name.ToString(); sdk_map2 sdkMap = SDKMappingSQLConnector.GetInstance().GetSDKMapFromClassAndNamespace(TransformProject.sdkId, nsString, className); if (sdkMap != null) { string newNamespace = sdkMap.namespace_map.new_namespace; string newClassName = sdkMap.new_classname; QualifiedNameSyntax newQualifiedNameNode = QualifiedName(IdentifierName(newNamespace), IdentifierName(newClassName)).WithTriviaFrom(oldQualifiedNameNode); documentEditor.ReplaceNode(oldQualifiedNameNode, newQualifiedNameNode); } } } } }
internal static void AddOnPropertyChanged(this DocumentEditor editor, ExpressionSyntax mutation, ExpressionStatementSyntax onPropertyChanged) { switch (mutation.Parent) { case SimpleLambdaExpressionSyntax lambda: editor.ReplaceNode( lambda, x => x.AddStatements(onPropertyChanged)); break; case ParenthesizedLambdaExpressionSyntax lambda: editor.ReplaceNode( lambda, x => x.AddStatements(onPropertyChanged)); break; case ExpressionStatementSyntax expressionStatement: editor.AddOnPropertyChangedAfter(expressionStatement, onPropertyChanged); break; case PrefixUnaryExpressionSyntax { Parent: IfStatementSyntax ifNot } unary when unary.IsKind(SyntaxKind.LogicalNotExpression) : editor.AddOnPropertyChangedAfter(ifNot, onPropertyChanged); break; } }
private static void ConvertToLambda(DocumentEditor editor, SyntaxNode toReplace, IMethodSymbol method, MethodDeclarationSyntax declaration, CancellationToken cancellationToken) { if (method.Parameters.TrySingle(out var parameter)) { if (declaration.ExpressionBody is ArrowExpressionClauseSyntax expressionBody) { editor.ReplaceNode( toReplace, SyntaxFactory.ParseExpression($"{parameter.Name} => {expressionBody.Expression}") .WithLeadingTriviaFrom(toReplace)); RemoveMethod(editor, method, declaration, cancellationToken); } else if (declaration.Body is BlockSyntax body && body.Statements.TrySingle(out var statement) && statement is ReturnStatementSyntax returnStatement) { editor.ReplaceNode( toReplace, SyntaxFactory.ParseExpression($"{parameter.Name} => {returnStatement.Expression}") .WithLeadingTriviaFrom(toReplace)); RemoveMethod(editor, method, declaration, cancellationToken); } } if (method.Parameters.Length == 2 && method.Parameters.TryElementAt(0, out var parameter1) && method.Parameters.TryElementAt(1, out var parameter2)) { if (declaration.ExpressionBody is ArrowExpressionClauseSyntax expressionBody) { editor.ReplaceNode( toReplace, SyntaxFactory.ParseExpression($"({parameter1.Name}, {parameter2.Name}) => {expressionBody.Expression}") .WithLeadingTriviaFrom(toReplace)); RemoveMethod(editor, method, declaration, cancellationToken); } else if (declaration.Body is BlockSyntax body && body.Statements.TrySingle(out var statement)) { switch (statement) { case ReturnStatementSyntax returnStatement: editor.ReplaceNode( toReplace, SyntaxFactory.ParseExpression($"({parameter1.Name}, {parameter2.Name}) => {returnStatement.Expression}") .WithLeadingTriviaFrom(toReplace)); RemoveMethod(editor, method, declaration, cancellationToken); break; case ExpressionStatementSyntax expressionStatement: editor.ReplaceNode( toReplace, SyntaxFactory.ParseExpression($"({parameter1.Name}, {parameter2.Name}) => {expressionStatement.Expression}") .WithLeadingTriviaFrom(toReplace)); RemoveMethod(editor, method, declaration, cancellationToken); break; } } } }
private static void UseLambda(DocumentEditor editor, IdentifierNameSyntax identifierName, CancellationToken cancellationToken) { if (editor.SemanticModel.TryGetSymbol(identifierName, cancellationToken, out IMethodSymbol method)) { if (method.Parameters.Length == 0) { _ = editor.ReplaceNode( identifierName, x => SyntaxFactory.ParseExpression($"() => {x.Identifier.ValueText}()")); } else if (method.Parameters.TrySingle(out var parameter)) { var parameterName = SafeParameterName(parameter, identifierName); _ = editor.ReplaceNode( identifierName, x => SyntaxFactory.ParseExpression($"{parameterName} => {x.Identifier.ValueText}({parameterName})")); } else { var parameters = string.Join(", ", method.Parameters.Select(x => SafeParameterName(x, identifierName))); _ = editor.ReplaceNode( identifierName, x => SyntaxFactory.ParseExpression($"({parameters}) => {x.Identifier.ValueText}({parameters})")); } } }
private static void ApplyInitializeInCtorFix( DocumentEditor editor, ConstructorDeclarationSyntax ctor, PropertyDeclarationSyntax property, ObjectCreationExpressionSyntax objectCreation) { var member = editor.SemanticModel.UnderscoreFields() ? (ExpressionSyntax)SyntaxFactory.IdentifierName(property.Identifier.ValueText) : SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.Token(SyntaxKind.DotToken), SyntaxFactory.IdentifierName(property.Identifier.ValueText)); var assignment = SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, member, objectCreation)); editor.ReplaceNode(ctor.Body, (x, _) => ((BlockSyntax)x).AddStatements(assignment)); editor.ReplaceNode( property, (x, _) => ((PropertyDeclarationSyntax)x).WithExpressionBody(null) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)) .WithAccessorList(GetOnlyAccessorList)); }
private static void RemoveExpression(DocumentEditor editor, ArgumentSyntax argument, IMethodSymbol invoker, bool usesUnderscoreNames, CancellationToken cancellationToken) { var invocation = argument.FirstAncestorOrSelf <InvocationExpressionSyntax>(); if (PropertyChanged.TryGetInvokedPropertyChangedName(invocation, editor.SemanticModel, cancellationToken, out var name) == AnalysisResult.Yes) { var property = editor.SemanticModel.GetDeclaredSymbolSafe(argument.FirstAncestorOrSelf <PropertyDeclarationSyntax>(), cancellationToken); if (property?.Name == name) { editor.ReplaceNode( invocation, SyntaxFactory.ParseExpression(Snippet.OnPropertyChanged(invoker, property?.Name, usesUnderscoreNames).TrimEnd(';')) .WithSimplifiedNames() .WithLeadingElasticLineFeed() .WithTrailingElasticLineFeed() .WithAdditionalAnnotations(Formatter.Annotation)); } else { editor.ReplaceNode( invocation, SyntaxFactory.ParseExpression(Snippet.OnOtherPropertyChanged(invoker, name, usesUnderscoreNames).TrimEnd(';')) .WithSimplifiedNames() .WithLeadingElasticLineFeed() .WithTrailingElasticLineFeed() .WithAdditionalAnnotations(Formatter.Annotation)); } } }
private static void ReplaceMagicStrings( Dictionary <string, string> constants, SyntaxNode classNode, DocumentEditor editor, MagicStringsReplacementStatistics stats) { foreach (var child in classNode.DescendantNodes().OfType <LiteralExpressionSyntax>().Where(s => s.Kind() == SyntaxKind.StringLiteralExpression)) { var value = child.WithoutTrivia().GetText().ToString(); if (value == "\"\"") { if (IsIgnoredEmptyStringNode(child)) { continue; } var stringEmpty = SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.StringKeyword)), SyntaxFactory.IdentifierName("Empty")); if (child.HasLeadingTrivia) { stringEmpty = stringEmpty.WithLeadingTrivia(child.GetLeadingTrivia()); } if (child.HasTrailingTrivia) { stringEmpty = stringEmpty.WithTrailingTrivia(child.GetTrailingTrivia()); } editor.ReplaceNode(child, stringEmpty); stats.EmptyStringsReplaced++; } if (constants.TryGetValue(value, out var name)) { if (IsNodeConst(child)) { continue; } var useConstant = SyntaxFactory.IdentifierName(name); if (child.HasLeadingTrivia) { useConstant = useConstant.WithLeadingTrivia(child.GetLeadingTrivia()); } if (child.HasTrailingTrivia) { useConstant = useConstant.WithTrailingTrivia(child.GetTrailingTrivia()); } editor.ReplaceNode(child, useConstant); stats.MagicStringsReplaced++; } } }
private static void MakeAutoPropertyNotifyWhenValueChanges(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol invoker, SemanticModel semanticModel, CancellationToken cancellationToken) { if (Property.IsMutableAutoProperty(propertyDeclaration, out var getter, out var setter)) { if (getter.Body != null || getter.ContainsSkippedText || setter.Body != null || setter.ContainsSkippedText) { return; } var underscoreFields = CodeStyle.UnderscoreFields(semanticModel); var property = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken); var backingField = editor.AddBackingField(propertyDeclaration, underscoreFields, cancellationToken); var fieldAccess = underscoreFields ? backingField.Name() : $"this.{backingField.Name()}"; var code = StringBuilderPool.Borrow() .AppendLine($"public Type PropertyName") .AppendLine("{") .AppendLine($" get => {fieldAccess};") .AppendLine() .AppendLine(" set") .AppendLine(" {") .AppendLine($" if ({Snippet.EqualityCheck(property.Type, "value", fieldAccess, semanticModel)})") .AppendLine(" {") .AppendLine($" return;") .AppendLine(" }") .AppendLine() .AppendLine($" {fieldAccess} = value;") .AppendLine($" {Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields)}") .AppendLine(" }") .AppendLine("}") .Return(); var template = ParseProperty(code); editor.ReplaceNode( getter, x => x.WithExpressionBody(template.Getter().ExpressionBody) .WithTrailingElasticLineFeed() .WithAdditionalAnnotations(Formatter.Annotation)); editor.ReplaceNode( setter, x => x.WithBody(template.Setter().Body) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)) .WithAdditionalAnnotations(Formatter.Annotation)); if (propertyDeclaration.Initializer != null) { editor.ReplaceNode( propertyDeclaration, x => x.WithoutInitializer()); } editor.ReplaceNode(propertyDeclaration, x => x.WithAdditionalAnnotations(Formatter.Annotation)); } }
private static async Task <Solution> InlineAndRemoveMethodAsync( Document document, ExpressionStatementSyntax expressionStatement, MethodDeclarationSyntax methodDeclaration, StatementSyntax[] statements, ParameterInfo[] parameterInfos, CancellationToken cancellationToken = default(CancellationToken)) { if (expressionStatement.SyntaxTree.Equals(methodDeclaration.SyntaxTree)) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); Solution solution = document.Project.Solution; StatementSyntax[] newStatements = await ReplaceParameterExpressionWithArgumentExpressionAsync( parameterInfos, statements, solution, cancellationToken).ConfigureAwait(false); newStatements[0] = newStatements[0].WithLeadingTrivia(expressionStatement.GetLeadingTrivia()); newStatements[statements.Length - 1] = newStatements[statements.Length - 1].WithTrailingTrivia(expressionStatement.GetTrailingTrivia()); if (expressionStatement.Parent.IsKind(SyntaxKind.Block)) { var block = (BlockSyntax)expressionStatement.Parent; BlockSyntax newBlock = block.WithStatements(block.Statements.ReplaceRange(expressionStatement, newStatements)); editor.ReplaceNode(block, newBlock); } else { editor.ReplaceNode(expressionStatement, Block(newStatements)); } editor.RemoveNode(methodDeclaration); document = editor.GetChangedDocument(); return(document.Project.Solution); } else { Solution solution = document.Project.Solution; document = await InlineMethodAsync(document, expressionStatement, statements, parameterInfos, cancellationToken).ConfigureAwait(false); DocumentId documentId = solution.GetDocumentId(methodDeclaration.SyntaxTree); solution = document.Project.Solution; return(await RemoveMethodAsync(solution.GetDocument(documentId), methodDeclaration, cancellationToken).ConfigureAwait(false)); } }
private static void FixArgument(DocumentEditor editor, AttributeSyntax attributeSyntax, ITypeSymbol inType, ITypeSymbol outType) { editor.ReplaceNode( attributeSyntax.ArgumentList.Arguments[0], editor.Generator.AttributeArgument( editor.Generator.TypeOfExpression(editor.Generator.TypeExpression(inType)))); editor.ReplaceNode( attributeSyntax.ArgumentList.Arguments[1], editor.Generator.AttributeArgument( editor.Generator.TypeOfExpression(editor.Generator.TypeExpression(outType)))); }
private static void MakeAutoPropertySet(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol setAndRaise, SemanticModel semanticModel, CancellationToken cancellationToken) { var classDeclaration = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>(); if (classDeclaration == null) { return; } if (Property.IsMutableAutoProperty(propertyDeclaration, out var getter, out var setter)) { if (getter.Body != null || getter.ContainsSkippedText || setter.Body != null || setter.ContainsSkippedText) { return; } var underscoreFields = CodeStyle.UnderscoreFields(semanticModel); var backingField = editor.AddBackingField(propertyDeclaration, underscoreFields, cancellationToken); var fieldAccess = underscoreFields ? backingField.Name() : $"this.{backingField.Name()}"; var code = StringBuilderPool.Borrow() .AppendLine($"public Type PropertyName") .AppendLine("{") .AppendLine($" get => {fieldAccess};") .AppendLine($" set => {(underscoreFields ? string.Empty : "this.")}{setAndRaise.Name}(ref {fieldAccess}, value);") .AppendLine("}") .Return(); var template = ParseProperty(code); editor.ReplaceNode( getter, x => x.WithExpressionBody(template.Getter().ExpressionBody) .WithLeadingLineFeed()); editor.ReplaceNode( setter, x => x.WithExpressionBody(template.Setter().ExpressionBody) .WithLeadingLineFeed() .WithTrailingLineFeed()); if (propertyDeclaration.Initializer != null) { editor.ReplaceNode( propertyDeclaration, (node, g) => ((PropertyDeclarationSyntax)node).WithoutInitializer()); } editor.ReplaceNode(propertyDeclaration, x => x.WithAdditionalAnnotations(Formatter.Annotation)); } }
internal static void AddOnPropertyChanged(this DocumentEditor editor, BlockSyntax block, ExpressionStatementSyntax onPropertyChangedStatement, int after) { _ = editor.ReplaceNode( block, x => { if (onPropertyChangedStatement.Expression is InvocationExpressionSyntax onPropertyChanged) { for (var i = after; i < x.Statements.Count; i++) { var statement = x.Statements[i]; // We can't use the semantic model here as it may not track nodes added before in fixall switch (statement) { case ExpressionStatementSyntax { Expression: AssignmentExpressionSyntax _ } : break; case ExpressionStatementSyntax { Expression: InvocationExpressionSyntax other } when onPropertyChanged.IsEquivalentTo(other) : return(x);
internal static FieldDeclarationSyntax AddBackingField(this DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, bool usesUnderscoreNames, CancellationToken cancellationToken) { var property = editor.SemanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken); var name = usesUnderscoreNames ? $"_{property.Name.ToFirstCharLower()}" : property.Name.ToFirstCharLower(); while (property.ContainingType.MemberNames.Any(x => x == name)) { name += "_"; } if (SyntaxFacts.GetKeywordKind(name) != SyntaxKind.None || SyntaxFacts.GetContextualKeywordKind(name) != SyntaxKind.None) { name = "@" + name; } var backingField = (FieldDeclarationSyntax)editor.Generator.FieldDeclaration( name, accessibility: Accessibility.Private, modifiers: DeclarationModifiers.None, type: propertyDeclaration.Type, initializer: propertyDeclaration.Initializer?.Value); var type = (TypeDeclarationSyntax)propertyDeclaration.Parent; editor.ReplaceNode( type, (node, generator) => AddBackingField((TypeDeclarationSyntax)node, backingField, property.Name, generator)); return(backingField); }
private static void AddUsingToEndOfBlock(DocumentEditor editor, BlockSyntax block, ExpressionSyntax expression) { foreach (var statementSyntax in block.Statements) { editor.RemoveNode(statementSyntax); } editor.ReplaceNode( block, SyntaxFactory.Block( SyntaxFactory.UsingStatement( declaration: null, expression: GetExpression(), statement: block.WithAdditionalAnnotations(Formatter.Annotation)))); ExpressionSyntax GetExpression() { if (expression is DeclarationExpressionSyntax declaration && declaration.Designation is SingleVariableDesignationSyntax singleVariable) { return(SyntaxFactory.IdentifierName(singleVariable.Identifier)); } return(expression); } }
private static void ReplaceWithUsing(DocumentEditor editor, InvocationExpressionSyntax invocation, CancellationToken cancellationToken) { if (DisposeCall.TryGetDisposedRootMember(invocation, editor.SemanticModel, cancellationToken, out var root) && editor.SemanticModel.TryGetSymbol(root, cancellationToken, out ILocalSymbol local) && local.TrySingleDeclaration(cancellationToken, out VariableDeclarationSyntax declaration) && invocation.TryFirstAncestor(out ExpressionStatementSyntax expressionStatement) && declaration.Parent is LocalDeclarationStatementSyntax localDeclarationStatement) { if (expressionStatement.Parent is BlockSyntax finallyBlock && finallyBlock.Parent is FinallyClauseSyntax finallyClause && finallyClause.Parent is TryStatementSyntax tryStatement && !tryStatement.Catches.Any()) { if (declaration.Variables.TrySingle(out var declarator) && declarator.Initializer?.Value.IsKind(SyntaxKind.NullLiteralExpression) == true && tryStatement.Block.Statements.TryFirst(out var statement) && statement is ExpressionStatementSyntax assignExpressionStatement && assignExpressionStatement.Expression is AssignmentExpressionSyntax assignment) { editor.ReplaceNode( tryStatement, SyntaxFactory.UsingStatement( SyntaxFactory.VariableDeclaration( SyntaxFactory.ParseTypeName("var"), SyntaxFactory.SingletonSeparatedList( declarator.WithInitializer(SyntaxFactory.EqualsValueClause(assignment.Right)))), null, tryStatement.Block.WithStatements(tryStatement.Block.Statements.RemoveAt(0)))); editor.RemoveNode(localDeclarationStatement); }
public async Task <Solution> InlineAndRemoveMethodAsync(InvocationExpressionSyntax invocation, ExpressionSyntax expression) { if (invocation.SyntaxTree == MethodDeclaration.SyntaxTree) { DocumentEditor editor = await DocumentEditor.CreateAsync(Document, CancellationToken).ConfigureAwait(false); ExpressionSyntax newExpression = RewriteExpression(invocation, expression); editor.ReplaceNode(invocation, newExpression); editor.RemoveNode(MethodDeclaration); return(editor.GetChangedDocument().Solution()); } else { Document newDocument = await InlineMethodAsync(invocation, expression).ConfigureAwait(false); DocumentId documentId = Document.Solution().GetDocumentId(MethodDeclaration.SyntaxTree); newDocument = await newDocument.Solution().GetDocument(documentId).RemoveMemberAsync(MethodDeclaration, CancellationToken).ConfigureAwait(false); return(newDocument.Solution()); } }
private static async Task <Document> SwapArgumentsOrderAsync(Document document, IObjectCreationOperation creation, int paramPosition, int argumentCount, CancellationToken token) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, token).ConfigureAwait(false); SyntaxNode parameter = AddNameOfIfLiteral(creation.Arguments[paramPosition].Value, editor.Generator); SyntaxNode newCreation; if (argumentCount == 2) { if (paramPosition == 0) { newCreation = editor.Generator.ObjectCreationExpression(creation.Type, creation.Arguments[1].Syntax, parameter); } else { newCreation = editor.Generator.ObjectCreationExpression(creation.Type, parameter, creation.Arguments[0].Syntax); } } else { Debug.Assert(argumentCount == 3); if (paramPosition == 0) { newCreation = editor.Generator.ObjectCreationExpression(creation.Type, creation.Arguments[1].Syntax, parameter, creation.Arguments[2].Syntax); } else { newCreation = editor.Generator.ObjectCreationExpression(creation.Type, parameter, creation.Arguments[1].Syntax, creation.Arguments[0].Syntax); } } editor.ReplaceNode(creation.Syntax, newCreation); return(editor.GetChangedDocument()); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { Document doc = context.Document; CancellationToken cancellationToken = context.CancellationToken; SyntaxNode root = await doc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SemanticModel model = await doc.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); // If we're able to make the desired substitution... var(targetNode, replacementField) = GetTaskCreationOptionsField(context, root, model, cancellationToken); if (replacementField != null) { // ...then offer it. string title = MicrosoftNetCoreAnalyzersResources.DoNotCreateTaskCompletionSourceWithWrongArgumentsFix; context.RegisterCodeFix( new MyCodeAction(title, async ct => { // Replace "TaskContinuationOptions.Value" with "TaskCreationOptions.Value" DocumentEditor editor = await DocumentEditor.CreateAsync(doc, ct).ConfigureAwait(false); editor.ReplaceNode(targetNode, editor.Generator.Argument( editor.Generator.MemberAccessExpression( editor.Generator.TypeExpressionForStaticMemberAccess(replacementField.ContainingType), replacementField.Name))); return(editor.GetChangedDocument()); }, equivalenceKey: title), context.Diagnostics); }
private static void ApplyFixGU0005(DocumentEditor editor, ArgumentSyntax nameArgument, CancellationToken cancellationToken) { var argumentListSyntax = nameArgument.FirstAncestorOrSelf <ArgumentListSyntax>(); var arguments = new ArgumentSyntax[argumentListSyntax.Arguments.Count]; var method = editor.SemanticModel.GetSymbolSafe(argumentListSyntax.Parent, cancellationToken) as IMethodSymbol; var messageIndex = ParameterIndex(method, "message"); var nameIndex = ParameterIndex(method, "paramName"); for (var i = 0; i < argumentListSyntax.Arguments.Count; i++) { if (i == messageIndex) { arguments[nameIndex] = argumentListSyntax.Arguments[i]; continue; } if (i == nameIndex) { arguments[messageIndex] = argumentListSyntax.Arguments[i]; continue; } arguments[i] = argumentListSyntax.Arguments[i]; } var updated = argumentListSyntax.WithArguments(SyntaxFactory.SeparatedList(arguments, argumentListSyntax.Arguments.GetSeparators())); editor.ReplaceNode(argumentListSyntax, updated); }
private void VisitExpression(ExpressionSyntax node) { var newNode = this.Command.NewExpression .WithAdditionalAnnotations(new SyntaxAnnotation($"{Id}")); DocumentEditor.ReplaceNode(node, newNode); }
public static void UpdateMethodBody(DocumentEditor editor, SyntaxNode syntaxNode, string src) { var methodDeclaration = syntaxNode.FirstAncestorOrSelf <MethodDeclarationSyntax>(); var body = (BlockSyntax)SyntaxFactory.ParseStatement(src).WithAdditionalAnnotations(Formatter.Annotation); editor.ReplaceNode(methodDeclaration.Body, body); }
private static async Task <Document> ConvertToArrayEmptyAsync(Document document, SyntaxNode nodeToFix, CancellationToken cancellationToken) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); SyntaxGenerator generator = editor.Generator; INamedTypeSymbol?arrayTypeSymbol = semanticModel.Compilation.GetSpecialType(SpecialType.System_Array); if (arrayTypeSymbol == null) { return(document); } ITypeSymbol?elementType = GetArrayElementType(nodeToFix, semanticModel, cancellationToken); if (elementType == null) { return(document); } SyntaxNode arrayEmptyInvocation = GenerateArrayEmptyInvocation(generator, arrayTypeSymbol, elementType).WithTriviaFrom(nodeToFix); editor.ReplaceNode(nodeToFix, arrayEmptyInvocation); return(editor.GetChangedDocument()); }
/// <summary> /// if a nested type is being moved, this ensures its containing type is partial. /// </summary> private void AddPartialModifiersToTypeChain( DocumentEditor documentEditor, bool removeAttributesAndComments) { var semanticFacts = State.SemanticDocument.Document.GetLanguageService <ISemanticFactsService>(); var typeChain = State.TypeNode.Ancestors().OfType <TTypeDeclarationSyntax>(); foreach (var node in typeChain) { var symbol = (ITypeSymbol)State.SemanticDocument.SemanticModel.GetDeclaredSymbol(node, CancellationToken); if (!semanticFacts.IsPartial(symbol, CancellationToken)) { documentEditor.SetModifiers(node, documentEditor.Generator.GetModifiers(node) | DeclarationModifiers.Partial); } if (removeAttributesAndComments) { documentEditor.RemoveAllAttributes(node); documentEditor.RemoveAllComments(node); } } documentEditor.ReplaceNode(State.TypeNode, (currentNode, generator) => { var currentTypeNode = (TTypeDeclarationSyntax)currentNode; // Trim leading whitespace from the type so we don't have excessive // leading blank lines. return(RemoveLeadingWhitespace(currentTypeNode)); }); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { Document doc = context.Document; CancellationToken cancellationToken = context.CancellationToken; SyntaxNode root = await doc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (root.FindNode(context.Span) is SyntaxNode expression) { string title = MicrosoftNetCoreAnalyzersResources.PreferTypedStringBuilderAppendOverloadsRemoveToString; context.RegisterCodeFix( new MyCodeAction(title, async ct => { SemanticModel model = await doc.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.GetOperationWalkingUpParentChain(expression, cancellationToken) is IArgumentOperation arg && arg.Value is IInvocationOperation invoke && invoke.Instance?.Syntax is SyntaxNode replacement) { DocumentEditor editor = await DocumentEditor.CreateAsync(doc, ct).ConfigureAwait(false); editor.ReplaceNode(expression, editor.Generator.Argument(replacement)); return(editor.GetChangedDocument()); } return(doc); }, equivalenceKey: title), context.Diagnostics); } }
private async Task <Document> ConvertToStringLengthComparison(CodeFixContext context, FixResolution fixResolution) { DocumentEditor editor = await DocumentEditor.CreateAsync(context.Document, context.CancellationToken).ConfigureAwait(false); SyntaxNode leftOperand = GetLeftOperand(fixResolution.BinaryExpressionSyntax); SyntaxNode rightOperand = GetRightOperand(fixResolution.BinaryExpressionSyntax); // Take the below example: // if (f == String.Empty) ... // The comparison operand, f, will now become 'f.Length' and a the other operand will become '0' SyntaxNode zeroLengthSyntax = editor.Generator.LiteralExpression(0); if (leftOperand == fixResolution.ComparisonOperand) { leftOperand = editor.Generator.MemberAccessExpression(leftOperand, "Length"); rightOperand = zeroLengthSyntax.WithTriviaFrom(rightOperand); } else { leftOperand = zeroLengthSyntax; rightOperand = editor.Generator.MemberAccessExpression(rightOperand.WithoutTrivia(), "Length"); } SyntaxNode replacementSyntax = fixResolution.UsesEqualsOperator ? editor.Generator.ValueEqualsExpression(leftOperand, rightOperand) : editor.Generator.ValueNotEqualsExpression(leftOperand, rightOperand); SyntaxNode replacementAnnotatedSyntax = replacementSyntax.WithAdditionalAnnotations(Formatter.Annotation); editor.ReplaceNode(fixResolution.BinaryExpressionSyntax, replacementAnnotatedSyntax); return(editor.GetChangedDocument()); }
protected override async Task <SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return(null); } DocumentEditor editor = await DocumentEditor.CreateAsync(document, fixAllContext.CancellationToken).ConfigureAwait(false); SyntaxNode root = editor.GetChangedRoot(); ImmutableList <SyntaxNode> nodesToChange = ImmutableList.Create <SyntaxNode>(); // Make sure all nodes we care about are tracked foreach (var diagnostic in diagnostics) { var location = diagnostic.Location; var syntaxNode = root.FindNode(location.SourceSpan); if (syntaxNode != null) { editor.TrackNode(syntaxNode); nodesToChange = nodesToChange.Add(syntaxNode); } } foreach (var node in nodesToChange) { editor.ReplaceNode(node, node.WithLeadingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed)); } return(editor.GetChangedRoot()); }
public virtual async Task <Solution> InlineAndRemoveAsync( SyntaxNode node, ExpressionSyntax expression, CancellationToken cancellationToken = default(CancellationToken)) { if (node.SyntaxTree == Declaration.SyntaxTree) { DocumentEditor editor = await DocumentEditor.CreateAsync(Document, cancellationToken).ConfigureAwait(false); ExpressionSyntax newExpression = RewriteExpression(node, expression); editor.ReplaceNode(node, newExpression); editor.RemoveNode(Declaration); return(editor.GetChangedDocument().Solution()); } else { Document newDocument = await InlineAsync(node, expression, cancellationToken).ConfigureAwait(false); DocumentId documentId = Document.Solution().GetDocumentId(Declaration.SyntaxTree); newDocument = await newDocument.Solution().GetDocument(documentId).RemoveMemberAsync(Declaration, cancellationToken).ConfigureAwait(false); return(newDocument.Solution()); } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { Document doc = context.Document; SemanticModel model = await doc.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); SyntaxNode root = await doc.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); if (root.FindNode(context.Span, getInnermostNodeForTie: true) is SyntaxNode node && model.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemEnvironment, out var environmentType) && model.GetOperation(node, context.CancellationToken) is IPropertyReferenceOperation operation) { string title = MicrosoftNetCoreAnalyzersResources.UseEnvironmentProcessIdFix; context.RegisterCodeFix( new MyCodeAction(title, async cancellationToken => { DocumentEditor editor = await DocumentEditor.CreateAsync(doc, cancellationToken).ConfigureAwait(false); var replacement = editor.Generator.MemberAccessExpression(editor.Generator.TypeExpressionForStaticMemberAccess(environmentType), "ProcessId"); editor.ReplaceNode(node, replacement.WithTriviaFrom(node)); return(editor.GetChangedDocument()); }, equivalenceKey: title), context.Diagnostics); } }
private static async Task <Document> ImplementIDisposable(Document document, SyntaxNode declaration, CancellationToken cancellationToken) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); SyntaxGenerator generator = editor.Generator; SemanticModel model = editor.SemanticModel; // Add the interface to the baselist. SyntaxNode interfaceType = generator.TypeExpression(WellKnownTypes.IDisposable(model.Compilation)); editor.AddInterfaceType(declaration, interfaceType); // Find a Dispose method. If one exists make that implement IDisposable, else generate a new method. var typeSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol; IMethodSymbol disposeMethod = (typeSymbol?.GetMembers("Dispose"))?.OfType <IMethodSymbol>()?.Where(m => m.Parameters.Length == 0).FirstOrDefault(); if (disposeMethod != null && disposeMethod.DeclaringSyntaxReferences.Length == 1) { SyntaxNode memberPartNode = await disposeMethod.DeclaringSyntaxReferences.Single().GetSyntaxAsync(cancellationToken).ConfigureAwait(false); memberPartNode = generator.GetDeclaration(memberPartNode); editor.ReplaceNode(memberPartNode, generator.AsPublicInterfaceImplementation(memberPartNode, interfaceType)); } else { SyntaxNode throwStatement = generator.ThrowStatement(generator.ObjectCreationExpression(WellKnownTypes.NotImplementedException(model.Compilation))); SyntaxNode member = generator.MethodDeclaration(TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzer <SyntaxNode> .Dispose, statements: new[] { throwStatement }); member = generator.AsPublicInterfaceImplementation(member, interfaceType); editor.AddMember(declaration, member); } return(editor.GetChangedDocument()); }
public static void UpdateMethodBody(DocumentEditor editor, SyntaxNode syntaxNode, string src) { var methodBlock = syntaxNode.FirstAncestorOrSelf <MethodBlockSyntax>(); var statements = new SyntaxList <StatementSyntax>().AddRange(GetStatements(src)); editor.ReplaceNode(methodBlock, methodBlock.WithStatements(statements)); }