private async Task <Document> ImplementOperatorEquals(Document document, SyntaxNode declaration, INamedTypeSymbol typeSymbol, CancellationToken cancellationToken) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); var generator = editor.Generator; if (!typeSymbol.IsOperatorImplemented(WellKnownMemberNames.EqualityOperatorName)) { var equalityOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean), WellKnownMemberNames.EqualityOperatorName, new[] { generator.ParameterDeclaration("left", generator.TypeExpression(typeSymbol)), generator.ParameterDeclaration("right", generator.TypeExpression(typeSymbol)), }, generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException")))); editor.AddMember(declaration, equalityOperator); } if (!typeSymbol.IsOperatorImplemented(WellKnownMemberNames.InequalityOperatorName)) { var inequalityOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean), WellKnownMemberNames.InequalityOperatorName, new[] { generator.ParameterDeclaration("left", generator.TypeExpression(typeSymbol)), generator.ParameterDeclaration("right", generator.TypeExpression(typeSymbol)), }, generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException")))); editor.AddMember(declaration, inequalityOperator); } return(editor.GetChangedDocument()); }
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()); }
internal static void AddField(this DocumentEditor editor, TypeDeclarationSyntax containingType, FieldDeclarationSyntax field) { FieldDeclarationSyntax existing = null; foreach (var member in containingType.Members) { if (member is FieldDeclarationSyntax fieldDeclaration) { if (IsInsertBefore(fieldDeclaration)) { editor.InsertBefore(fieldDeclaration, field); return; } existing = fieldDeclaration; continue; } editor.InsertBefore(member, field); return; } if (existing != null) { editor.InsertAfter(existing, field); } else { editor.AddMember(containingType, field); } }
private async Task <Document> OverrideObjectGetHashCode(Document document, SyntaxNode typeDeclaration, CancellationToken cancellationToken) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); SyntaxGenerator generator = editor.Generator; SyntaxNode methodDeclaration = generator.GetHashCodeOverrideDeclaration(); editor.AddMember(typeDeclaration, methodDeclaration); return(editor.GetChangedDocument()); }
private async Task <Document> ImplementMissingMembersAsync( SyntaxNode declaration, INamedTypeSymbol typeSymbol, Document document, CancellationToken ct) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, ct).ConfigureAwait(false); SyntaxGenerator generator = editor.Generator; string language = document.Project.Language; if (!typeSymbol.OverridesEquals()) { SyntaxNode equalsMethod = generator.EqualsOverrideDeclaration(); editor.AddMember(declaration, equalsMethod); } if (!typeSymbol.OverridesGetHashCode()) { SyntaxNode getHashCodeMethod = generator.GetHashCodeOverrideDeclaration(); editor.AddMember(declaration, getHashCodeMethod); } if (!typeSymbol.ImplementsOperator(WellKnownMemberNames.EqualityOperatorName)) { SyntaxNode equalityOperator = generator.ComparisonOperatorDeclaration(OperatorKind.Equality, typeSymbol); editor.AddMember(declaration, equalityOperator); } if (!typeSymbol.ImplementsOperator(WellKnownMemberNames.InequalityOperatorName)) { SyntaxNode inequalityOperator = generator.ComparisonOperatorDeclaration(OperatorKind.Inequality, typeSymbol); editor.AddMember(declaration, inequalityOperator); } return(editor.GetChangedDocument()); }
private async Task <Document> ImplementOperatorEquals(Document document, SyntaxNode declaration, INamedTypeSymbol typeSymbol, CancellationToken cancellationToken) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); SyntaxGenerator generator = editor.Generator; if (!typeSymbol.ImplementsOperator(WellKnownMemberNames.EqualityOperatorName)) { SyntaxNode equalityOperator = generator.ComparisonOperatorDeclaration(OperatorKind.Equality, typeSymbol); editor.AddMember(declaration, equalityOperator); } if (!typeSymbol.ImplementsOperator(WellKnownMemberNames.InequalityOperatorName)) { SyntaxNode inequalityOperator = generator.ComparisonOperatorDeclaration(OperatorKind.Inequality, typeSymbol); editor.AddMember(declaration, inequalityOperator); } return(editor.GetChangedDocument()); }
internal static void GenerateMissingEvents(ClassDeclarationSyntax classDeclaration, ITypeSymbol interfaceType, ITypeSymbol classType, DocumentEditor editor, SyntaxGenerator gen) { foreach (var eventSymbol in interfaceType.GetMembers(). OfType <IEventSymbol>()) { if (classType.FindImplementationForInterfaceMember(eventSymbol) != null) { continue; } editor.AddMember(classDeclaration, GenerateEvent(gen, eventSymbol)); } }
internal static void GenerateMissingProperties(ClassDeclarationSyntax classDeclaration, ITypeSymbol interfaceType, ITypeSymbol classType, DocumentEditor editor, SyntaxGenerator gen) { foreach (var propertySymbol in interfaceType.GetMembers(). OfType <IPropertySymbol>()) { if (classType.FindImplementationForInterfaceMember(propertySymbol) != null) { continue; } editor.AddMember(classDeclaration, GenerateProperty(gen, propertySymbol, Constants.ImplementationFieldName)); } }
public static void AddUninitializedFieldNamed(this DocumentEditor editor, ClassDeclarationSyntax oldClass, string name, string typeName) { var fieldDeclaration = FieldDeclaration( VariableDeclaration( IdentifierName(typeName)) .WithVariables( SingletonSeparatedList <VariableDeclaratorSyntax>( VariableDeclarator( Identifier(name))))) .WithModifiers( TokenList( Token(SyntaxKind.PrivateKeyword))) .WithAdditionalAnnotations(Formatter.Annotation); editor.AddMember(oldClass, fieldDeclaration); }
public static void AddDisposeMethodAndDisposeCallToMember(this DocumentEditor editor, ClassDeclarationSyntax oldClass, string memberName, bool castToDisposable) { var disposeMethod = SyntaxFactory .MethodDeclaration( SyntaxFactory.PredefinedType( SyntaxFactory.Token(SyntaxKind.VoidKeyword)), SyntaxFactory.Identifier(Constants.Dispose)) .WithModifiers( SyntaxFactory.TokenList( SyntaxFactory.Token(SyntaxKind.PublicKeyword))) .WithBody( SyntaxFactory.Block( SyntaxFactory.SingletonList <StatementSyntax>( CreateDisposeCall(memberName, castToDisposable)))) .WithoutAnnotations(Formatter.Annotation); editor.AddMember(oldClass, disposeMethod); }
private async Task <Document> ImplementComparable(Document document, SyntaxNode declaration, INamedTypeSymbol typeSymbol, CancellationToken cancellationToken) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); SyntaxGenerator generator = editor.Generator; if (!typeSymbol.OverridesEquals()) { SyntaxNode equalsMethod = generator.EqualsOverrideDeclaration(); editor.AddMember(declaration, equalsMethod); } if (!typeSymbol.OverridesGetHashCode()) { SyntaxNode getHashCodeMethod = generator.GetHashCodeOverrideDeclaration(); editor.AddMember(declaration, getHashCodeMethod); } if (!typeSymbol.ImplementsOperator(WellKnownMemberNames.EqualityOperatorName)) { SyntaxNode equalityOperator = generator.ComparisonOperatorDeclaration(OperatorKind.Equality, typeSymbol); editor.AddMember(declaration, equalityOperator); } if (!typeSymbol.ImplementsOperator(WellKnownMemberNames.InequalityOperatorName)) { SyntaxNode inequalityOperator = generator.ComparisonOperatorDeclaration(OperatorKind.Inequality, typeSymbol); editor.AddMember(declaration, inequalityOperator); } if (!typeSymbol.ImplementsOperator(WellKnownMemberNames.LessThanOperatorName)) { SyntaxNode lessThanOperator = generator.ComparisonOperatorDeclaration(OperatorKind.LessThan, typeSymbol); editor.AddMember(declaration, lessThanOperator); } if (!typeSymbol.ImplementsOperator(WellKnownMemberNames.GreaterThanOperatorName)) { SyntaxNode greaterThanOperator = generator.ComparisonOperatorDeclaration(OperatorKind.GreaterThan, typeSymbol); editor.AddMember(declaration, greaterThanOperator); } return(editor.GetChangedDocument()); }
internal static void GenerateMissingMethods(ClassDeclarationSyntax classDeclaration, ITypeSymbol interfaceType, ITypeSymbol classType, DocumentEditor editor, SyntaxGenerator gen, SemanticModel model, int minificationLocation, bool includeAsyncAwait) { foreach (var member in interfaceType.GetMembers(). OfType <IMethodSymbol>(). Where(m => m.MethodKind == MethodKind.Ordinary)) { if (classType.FindImplementationForInterfaceMember(member) != null) { continue; } editor.AddMember(classDeclaration, GenerateMethodImplementation(gen, model, minificationLocation, member, Constants.ImplementationFieldName, includeAsyncAwait)); } }
private static async Task <Document> AddConstructorsAsync(Document document, IEnumerable <Diagnostic> diagnostics, SyntaxNode root, CancellationToken cancellationToken) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); SyntaxGenerator generator = editor.Generator; SemanticModel model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); CodeAnalysis.Text.TextSpan diagnosticSpan = diagnostics.First().Location.SourceSpan; // All the diagnostics are reported at the same location -- the name of the declared class -- so it doesn't matter which one we pick SyntaxNode node = root.FindNode(diagnosticSpan); SyntaxNode targetNode = editor.Generator.GetDeclaration(node, DeclarationKind.Class); if (model.GetDeclaredSymbol(targetNode, cancellationToken) is not INamedTypeSymbol typeSymbol) { return(document); } foreach (Diagnostic diagnostic in diagnostics) { var missingCtorSignature = (ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature)Enum.Parse(typeof(ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature), diagnostic.Properties["Signature"]); switch (missingCtorSignature) { case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithNoParameter: // Add missing CtorWithNoParameter SyntaxNode newConstructorNode1 = generator.ConstructorDeclaration(typeSymbol.Name, accessibility: Accessibility.Public); editor.AddMember(targetNode, newConstructorNode1); break; case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithStringParameter: // Add missing CtorWithStringParameter SyntaxNode newConstructorNode2 = generator.ConstructorDeclaration( containingTypeName: typeSymbol.Name, parameters: new[] { generator.ParameterDeclaration("message", generator.TypeExpression(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_String))) }, accessibility: Accessibility.Public, baseConstructorArguments: new[] { generator.Argument(generator.IdentifierName("message")) }); editor.AddMember(targetNode, newConstructorNode2); break; case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithStringAndExceptionParameters: // Add missing CtorWithStringAndExceptionParameters SyntaxNode newConstructorNode3 = generator.ConstructorDeclaration( containingTypeName: typeSymbol.Name, parameters: new[] { generator.ParameterDeclaration("message", generator.TypeExpression(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_String))), generator.ParameterDeclaration("innerException", generator.TypeExpression(editor.SemanticModel.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemException))) }, accessibility: Accessibility.Public, baseConstructorArguments: new[] { generator.Argument(generator.IdentifierName("message")), generator.Argument(generator.IdentifierName("innerException")) }); editor.AddMember(targetNode, newConstructorNode3); break; } } return(editor.GetChangedDocument()); }
private async Task <Document> ImplementComparable(Document document, SyntaxNode declaration, INamedTypeSymbol typeSymbol, CancellationToken cancellationToken) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); var generator = editor.Generator; if (!OverrideMethodsOnComparableTypesAnalyzer.DoesOverrideEquals(typeSymbol)) { var equalsMethod = generator.MethodDeclaration(WellKnownMemberNames.ObjectEquals, new[] { generator.ParameterDeclaration("obj", generator.TypeExpression(SpecialType.System_Object)) }, returnType: generator.TypeExpression(SpecialType.System_Boolean), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Override, statements: new[] { generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException"))) }); editor.AddMember(declaration, equalsMethod); } if (!OverrideMethodsOnComparableTypesAnalyzer.DoesOverrideGetHashCode(typeSymbol)) { var getHashCodeMethod = generator.MethodDeclaration(WellKnownMemberNames.ObjectGetHashCode, returnType: generator.TypeExpression(SpecialType.System_Int32), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Override, statements: new[] { generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException"))) }); editor.AddMember(declaration, getHashCodeMethod); } if (!OverrideMethodsOnComparableTypesAnalyzer.IsOperatorImplemented(typeSymbol, WellKnownMemberNames.EqualityOperatorName)) { var equalityOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean), WellKnownMemberNames.EqualityOperatorName, new[] { generator.ParameterDeclaration("left", generator.TypeExpression(typeSymbol)), generator.ParameterDeclaration("right", generator.TypeExpression(typeSymbol)), }, generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException")))); editor.AddMember(declaration, equalityOperator); } if (!OverrideMethodsOnComparableTypesAnalyzer.IsOperatorImplemented(typeSymbol, WellKnownMemberNames.InequalityOperatorName)) { var inequalityOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean), WellKnownMemberNames.InequalityOperatorName, new[] { generator.ParameterDeclaration("left", generator.TypeExpression(typeSymbol)), generator.ParameterDeclaration("right", generator.TypeExpression(typeSymbol)), }, generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException")))); editor.AddMember(declaration, inequalityOperator); } if (!OverrideMethodsOnComparableTypesAnalyzer.IsOperatorImplemented(typeSymbol, WellKnownMemberNames.LessThanOperatorName)) { var lessThanOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean), WellKnownMemberNames.LessThanOperatorName, new[] { generator.ParameterDeclaration("left", generator.TypeExpression(typeSymbol)), generator.ParameterDeclaration("right", generator.TypeExpression(typeSymbol)), }, generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException")))); editor.AddMember(declaration, lessThanOperator); } if (!OverrideMethodsOnComparableTypesAnalyzer.IsOperatorImplemented(typeSymbol, WellKnownMemberNames.GreaterThanOperatorName)) { var greaterThanOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean), WellKnownMemberNames.GreaterThanOperatorName, new[] { generator.ParameterDeclaration("left", generator.TypeExpression(typeSymbol)), generator.ParameterDeclaration("right", generator.TypeExpression(typeSymbol)), }, generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException")))); editor.AddMember(declaration, greaterThanOperator); } return(editor.GetChangedDocument()); }