private static TypeDeclarationSyntax AddGeneratedItems <T>(ClassModel classModel, TypeDeclarationSyntax declaration, ItemGenerationStrategyFactory <T> factory, Func <ClassModel, IEnumerable <T> > selector, bool withRegeneration)
        {
            foreach (var property in selector(classModel))
            {
                foreach (var method in factory.CreateFor(property, classModel))
                {
                    var methodName     = method.Identifier.Text;
                    var existingMethod = declaration.DescendantNodes().OfType <MethodDeclarationSyntax>().FirstOrDefault(x => string.Equals(x.Identifier.Text, methodName, StringComparison.OrdinalIgnoreCase));

                    if (existingMethod != null)
                    {
                        if (!withRegeneration)
                        {
                            throw new InvalidOperationException("One or more of the generated methods ('" + methodName + "') already exists in the test class. In order to over-write existing tests, hold left shift while right-clicking and select the 'Regenerate' option.");
                        }

                        declaration = declaration.ReplaceNode(existingMethod, method);
                    }
                    else
                    {
                        declaration = declaration.AddMembers(method);
                    }
                }
            }

            return(declaration);
        }
        private async Task <Document> AddGMapT(Document document, TypeDeclarationSyntax typeDecl, ConstructorDeclarationSyntax constructor, CancellationToken cancellationToken)
        {
            var newTypeDecl = typeDecl.AddMembers(GenerateGMapT(typeDecl, constructor));

            var sr = await document.GetSyntaxRootAsync(cancellationToken);

            var nsr = sr.ReplaceNode(typeDecl, newTypeDecl);

            return(document.WithSyntaxRoot(nsr));
        }
示例#3
0
        private async Task <Document> GenerateToStringAsync(Document document, TypeDeclarationSyntax structDec, CancellationToken cancellationToken)
        {
            var newClassDec = structDec.AddMembers(GetToStringDeclarationSyntax(structDec));

            var sr = await document.GetSyntaxRootAsync(cancellationToken);

            var nsr = sr.ReplaceNode(structDec, newClassDec);

            return(document.WithSyntaxRoot(nsr));
        }
示例#4
0
        public static TypeDeclarationSyntax UpdateOrAddWithMethod(
            TypeDeclarationSyntax typeDeclaration, IEnumerable <Field> fields)
        {
            var maybePreviousWithMethod = MaybePreviousWithMethod(typeDeclaration);

            var withMethod = MakeWithMethod(typeDeclaration, fields, maybePreviousWithMethod);

            return(maybePreviousWithMethod == null
                ? typeDeclaration.AddMembers(withMethod)
                : typeDeclaration.ReplaceNode(maybePreviousWithMethod, withMethod));
        }
示例#5
0
        public static TypeDeclarationSyntax UpdateOrAddConstructor(
            TypeDeclarationSyntax typeDeclaration, IEnumerable <Field> fields)
        {
            var maybePreviousConstructor = MaybePreviousConstructor(typeDeclaration);

            var constructor = MakeConstructor(typeDeclaration, fields, maybePreviousConstructor);

            return(maybePreviousConstructor == null
                ? typeDeclaration.AddMembers(constructor)
                : typeDeclaration.ReplaceNode(maybePreviousConstructor, constructor));
        }
        private async Task <Document> GenerateCodeSameFile(Document document, TypeDeclarationSyntax typeDecl, bool isOptional, CancellationToken cancellationToken)
        {
            var properties = typeDecl.Members.OfType <PropertyDeclarationSyntax>().Where(p => p.IsAutoProperty());
            var newCtor    = GenerateConstructor(typeDecl.Identifier.Text, properties, isOptional);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false) as CompilationUnitSyntax;

            var newTypeDecl = typeDecl.AddMembers(newCtor);

            var newRoot = root.ReplaceNode(typeDecl, newTypeDecl);

            document = document.WithSyntaxRoot(newRoot);
            return(document);
        }
        private static TypeDeclarationSyntax WithPropertyChangedEvent(this TypeDeclarationSyntax node, TypeDeclarationSyntax original, SemanticModel semanticModel, Workspace workspace)
        {
            INamedTypeSymbol classSymbol                = semanticModel.GetDeclaredSymbol(original);
            INamedTypeSymbol interfaceSymbol            = semanticModel.Compilation.GetTypeByMetadataName(InterfaceName);
            IEventSymbol     propertyChangedEventSymbol = (IEventSymbol)interfaceSymbol.GetMembers("PropertyChanged").Single();
            ISymbol          propertyChangedEvent       = classSymbol.FindImplementationForInterfaceMember(propertyChangedEventSymbol);

            // Does this class contain an implementation for the PropertyChanged event? If not, add it.
            if (propertyChangedEvent == null)
            {
                MemberDeclarationSyntax propertyChangedEventDecl = GeneratePropertyChangedEvent();
                node = node.AddMembers(propertyChangedEventDecl);
            }

            return(node);
        }
        private async Task <Document> MoveRegistrationToStaticCtorAsync(
            Document document,
            TypeDeclarationSyntax origDeclaration,
            ExpressionStatementSyntax registration,
            CancellationToken cancellationToken)
        {
            TypeDeclarationSyntax newDeclaration = origDeclaration
                                                   .RemoveNode(registration, SyntaxRemoveOptions.KeepNoTrivia);
            ConstructorDeclarationSyntax staticCtor = FindStaticCtor(origDeclaration);

            if (staticCtor == null)
            {
                staticCtor = SyntaxFactory
                             .ConstructorDeclaration(origDeclaration.Identifier)
                             .WithModifiers(
                    SyntaxTokenList.Create(
                        SyntaxFactory.Token(SyntaxKind.StaticKeyword)
                        )
                    )
                             .WithBody(SyntaxFactory.Block())
                             .WithAdditionalAnnotations(Formatter.Annotation, SyntaxAnnotation.ElasticAnnotation)
                             .NormalizeWhitespace();

                newDeclaration = newDeclaration.AddMembers(staticCtor);
            }

            BlockSyntax withRegistration = staticCtor.Body
                                           .WithStatements(staticCtor.Body.Statements.Add(registration))
                                           .WithAdditionalAnnotations(Formatter.Annotation);

            newDeclaration = newDeclaration
                             .ReplaceNode(FindStaticCtor(newDeclaration).Body, withRegistration);

            SyntaxNode root = await document
                              .GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            SyntaxNode newRoot = root.ReplaceNode(origDeclaration, newDeclaration);

            return(document.WithSyntaxRoot(newRoot));
        }
示例#9
0
        public static T AddEquality <T>(
            this T syntax,
            string typeName,
            IReadOnlyList <PropertyDescriptor> properties,
            bool generateRecordEquality = false)
            where T : TypeDeclarationSyntax
        {
            TypeDeclarationSyntax modified = syntax;

            var builder    = new StringBuilder();
            var codeWriter = new CodeWriter(builder);

            if (!generateRecordEquality)
            {
                modified = modified.AddImplements(TypeNames.IEquatable.WithGeneric(typeName));

                BuildObjectEqualsMethod(typeName).Build(codeWriter);
                codeWriter.Flush();
                var overrideMethod = builder.ToString();
                builder.Clear();

                modified = modified.AddMembers(
                    CSharpSyntaxTree
                    .ParseText(overrideMethod,
                               new CSharpParseOptions(kind: SourceCodeKind.Script))
                    .GetCompilationUnitRoot()
                    .Members
                    .ToArray());
            }

            BuildEqualsMethod(typeName, properties).Build(codeWriter);
            codeWriter.Flush();
            var equalsMethod = builder.ToString();

            builder.Clear();

            modified = modified.AddMembers(
                CSharpSyntaxTree
                .ParseText(
                    equalsMethod,
                    new CSharpParseOptions(kind: SourceCodeKind.Script))
                .GetCompilationUnitRoot()
                .Members
                .ToArray());


            BuildGetHashCodeMethod(properties).Build(codeWriter);
            codeWriter.Flush();
            var hashCodeMethod = builder.ToString();

            builder.Clear();
            modified = modified.AddMembers(
                CSharpSyntaxTree
                .ParseText(hashCodeMethod, new CSharpParseOptions(kind: SourceCodeKind.Script))
                .GetCompilationUnitRoot()
                .Members
                .ToArray());

            if (modified is T target)
            {
                return(target);
            }

            throw new InvalidOperationException();
        }
示例#10
0
        private T GenerateProperties <T>(
            T typeDeclarationSyntax,
            SyntaxKind setAccessorKind,
            string infoInterfaceType,
            InputObjectTypeDescriptor descriptor)
            where T : TypeDeclarationSyntax
        {
            TypeDeclarationSyntax current = typeDeclarationSyntax;

            foreach (var prop in descriptor.Properties)
            {
                VariableDeclaratorSyntax variable =
                    VariableDeclarator(
                        Identifier(CreateInputValueField(prop.Name)));

                if (prop.Type.IsNonNullableType() && !prop.Type.GetRuntimeType().IsValueType)
                {
                    variable = variable.WithSuppressNullableWarningExpression();
                }

                current = current.AddMembers(
                    FieldDeclaration(
                        VariableDeclaration(
                            prop.Type.ToTypeSyntax(),
                            SingletonSeparatedList(variable)))
                    .AddModifiers(Token(SyntaxKind.PrivateKeyword)));

                current = current.AddMembers(
                    FieldDeclaration(
                        VariableDeclaration(
                            ParseTypeName(TypeNames.Boolean),
                            SingletonSeparatedList(
                                VariableDeclarator(
                                    Identifier(CreateIsSetField(prop.Name))))))
                    .AddModifiers(Token(SyntaxKind.PrivateKeyword)));
            }

            foreach (var prop in descriptor.Properties)
            {
                PropertyDeclarationSyntax property =
                    PropertyDeclaration(prop.Type.ToTypeSyntax(), prop.Name)
                    .AddModifiers(Token(SyntaxKind.PublicKeyword))
                    .AddSummary(prop.Description)
                    .AddAccessorListAccessors(
                        AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                        .WithExpressionBody(
                            ArrowExpressionClause(
                                IdentifierName(CreateInputValueField(prop.Name))))
                        .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
                        AccessorDeclaration(setAccessorKind)
                        .WithBody(
                            Block(
                                ExpressionStatement(
                                    AssignmentExpression(
                                        SyntaxKind.SimpleAssignmentExpression,
                                        IdentifierName(CreateIsSetField(prop.Name)),
                                        LiteralExpression(
                                            SyntaxKind.TrueLiteralExpression))),
                                ExpressionStatement(
                                    AssignmentExpression(
                                        SyntaxKind.SimpleAssignmentExpression,
                                        IdentifierName(CreateInputValueField(prop.Name)),
                                        IdentifierName("value"))))));

                current = current.AddMembers(property);

                current = current.AddMembers(
                    PropertyDeclaration(
                        ParseTypeName(TypeNames.Boolean),
                        CreateIsSetProperty(prop.Name))
                    .WithExplicitInterfaceSpecifier(
                        ExplicitInterfaceSpecifier(
                            IdentifierName(infoInterfaceType)))
                    .WithExpressionBody(
                        ArrowExpressionClause(
                            IdentifierName(CreateIsSetField(prop.Name))))
                    .WithSemicolonToken(
                        Token(SyntaxKind.SemicolonToken)));
            }

            return((T)current);
        }
        private static TypeDeclarationSyntax EnsureAllConstructorParametersHaveFields(IFrameworkSet frameworkSet, ClassModel classModel, TypeDeclarationSyntax targetType)
        {
            var setupMethod = frameworkSet.TestFramework.CreateSetupMethod(frameworkSet.GetTargetTypeName(classModel, true));

            BaseMethodDeclarationSyntax foundMethod = null, updatedMethod = null;

            if (setupMethod is MethodDeclarationSyntax methodSyntax)
            {
                updatedMethod = foundMethod = targetType.Members.OfType <MethodDeclarationSyntax>().FirstOrDefault(x => x.Identifier.Text == methodSyntax.Identifier.Text && x.ParameterList.Parameters.Count == 0);
            }
            else if (setupMethod is ConstructorDeclarationSyntax)
            {
                updatedMethod = foundMethod = targetType.Members.OfType <ConstructorDeclarationSyntax>().FirstOrDefault(x => x.ParameterList.Parameters.Count == 0);
            }

            if (foundMethod != null)
            {
                var parametersEmitted = new HashSet <string>();
                var allFields         = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

                var fields = new List <FieldDeclarationSyntax>();
                foreach (var parameterModel in classModel.Constructors.SelectMany(x => x.Parameters))
                {
                    allFields.Add(classModel.GetConstructorParameterFieldName(parameterModel));
                }

                // generate fields for each constructor parameter that doesn't have an existing field
                foreach (var parameterModel in classModel.Constructors.SelectMany(x => x.Parameters))
                {
                    if (!parametersEmitted.Add(parameterModel.Name))
                    {
                        continue;
                    }

                    var fieldName = classModel.GetConstructorParameterFieldName(parameterModel);

                    var fieldExists = targetType.Members.OfType <FieldDeclarationSyntax>().Any(x => x.Declaration.Variables.Any(v => v.Identifier.Text == fieldName));

                    if (!fieldExists)
                    {
                        var variable = SyntaxFactory.VariableDeclaration(parameterModel.TypeInfo.ToTypeSyntax(frameworkSet.Context))
                                       .AddVariables(SyntaxFactory.VariableDeclarator(fieldName));
                        var field = SyntaxFactory.FieldDeclaration(variable)
                                    .AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword));

                        fields.Add(field);

                        var defaultExpression = AssignmentValueHelper.GetDefaultAssignmentValue(parameterModel.TypeInfo, classModel.SemanticModel, frameworkSet);

                        var statement = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(fieldName), defaultExpression));

                        var body = updatedMethod.Body ?? SyntaxFactory.Block();

                        SyntaxList <StatementSyntax> newStatements;
                        var index = body.Statements.LastIndexOf(x => x.DescendantNodes().OfType <AssignmentExpressionSyntax>().Any(a => a.Left is IdentifierNameSyntax identifierName && allFields.Contains(identifierName.Identifier.Text)));
                        if (index >= 0 && index < body.Statements.Count - 1)
                        {
                            newStatements = body.Statements.Insert(index + 1, statement);
                        }
                        else
                        {
                            newStatements = body.Statements.Add(statement);
                        }

                        updatedMethod = updatedMethod.WithBody(body.WithStatements(newStatements));
                    }
                }

                if (fields.Any())
                {
                    targetType = targetType.ReplaceNode(foundMethod, updatedMethod);
                    var existingField = targetType.Members.OfType <FieldDeclarationSyntax>().LastOrDefault();
                    if (existingField != null)
                    {
                        targetType = targetType.InsertNodesAfter(existingField, fields);
                    }
                    else
                    {
                        targetType = targetType.AddMembers(fields.OfType <MemberDeclarationSyntax>().ToArray());
                    }
                }
            }

            return(targetType);
        }