예제 #1
0
        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());
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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());
        }
예제 #5
0
        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());
        }
예제 #7
0
 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));
     }
 }
예제 #8
0
 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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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());
        }
예제 #12
0
        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());
        }
예제 #14
0
        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());
        }