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)); }
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)); }
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)); }
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)); }
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(); }
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); }