private BlockSyntax CreateMethodBody(SemanticModel model, INamedTypeSymbol typeSymbol, IMethodSymbol methodSymbol) { var currentDeclarator = SyntaxFactory.VariableDeclarator("current"); var variableCurrent = SyntaxFactory.VariableDeclaration(SyntaxFactory.IdentifierName(methodSymbol.Parameters.First().Type.Name), new SeparatedSyntaxList <VariableDeclaratorSyntax>().Add(currentDeclarator)); var allVisitMethods = GetVisitMethods(typeSymbol, true).ToList(); var thisKeyword = SyntaxFactory.Token(SyntaxKind.ThisKeyword); var expressionParam = SyntaxFactory.IdentifierName("expression"); var tryGetValue = SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("TryGetCurrent"), SyntaxFactory.ArgumentList().AddArguments(SyntaxFactory.Argument(expressionParam), SyntaxFactory.Argument(SyntaxFactory.IdentifierName(currentDeclarator.Identifier.Text)).WithRefOrOutKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)))); var ifTryGetValue = SyntaxFactory .IfStatement(SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, tryGetValue), SyntaxFactory.Block(SyntaxFactory.ReturnStatement(expressionParam))); var properties = GetProperties((INamedTypeSymbol)methodSymbol.Parameters.First().Type).Where(c => c.Name != "CanReduce").ToList(); var simpleProperties = properties .Where(c => !IsOfType(c.Type, "Expression") && !IsOfType(c.Type, "IReadOnlyList") && allVisitMethods.All(d => d.Parameters[0].Type.Name != c.Type.Name)) .ToList(); var expressionProperties = properties .Where(c => IsOfType(c.Type, "Expression") || (!IsOfType(c.Type, "IReadOnlyList") && allVisitMethods.Any(d => d.Parameters[0].Type.Name == c.Type.Name))) .ToList(); var collectionProperties = properties .Where(c => IsOfType(c.Type, "IReadOnlyList")) .ToList(); var result = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("this"), SyntaxFactory.IdentifierName("result")); var currentObject = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("this"), SyntaxFactory.IdentifierName("currentObject")); var simplePropertyChecks = simpleProperties.Select(c => { var type = c.Type; var fullname = type.ToDisplayString(new SymbolDisplayFormat(typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces)); if (type.IsValueType || fullname == "System.Type" || fullname == "System.Reflection.FieldInfo" || fullname == "System.Reflection.MethodInfo" || fullname == "System.Reflection.PropertyInfo") { return((ExpressionSyntax)SyntaxFactory.BinaryExpression ( SyntaxKind.EqualsExpression, SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("current"), SyntaxFactory.IdentifierName(c.Name)), SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("expression"), SyntaxFactory.IdentifierName(c.Name)) )); } else { return(SyntaxFactory.InvocationExpression ( SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("object"), SyntaxFactory.IdentifierName("Equals")), SyntaxFactory.ArgumentList().AddArguments ( SyntaxFactory.Argument(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("current"), SyntaxFactory.IdentifierName(c.Name))), SyntaxFactory.Argument(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("expression"), SyntaxFactory.IdentifierName(c.Name))) ) )); } }) .Select(c => SyntaxFactory.AssignmentExpression(SyntaxKind.AndAssignmentExpression, result, c)) .Select(c => SyntaxFactory.IfStatement(SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, SyntaxFactory.ParenthesizedExpression(c)), SyntaxFactory.Block(SyntaxFactory.ReturnStatement(expressionParam)))) .ToArray <StatementSyntax>(); var visitMethod = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("this"), SyntaxFactory.IdentifierName("Visit")); var expressionPropertyChecks = expressionProperties.Select(c => new StatementSyntax[] { SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, currentObject, SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("current"), SyntaxFactory.IdentifierName(c.Name)))), SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression(allVisitMethods.FirstOrDefault(d => d.Parameters[0].Type.Name == c.Type.Name) == null ? visitMethod : SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("this"), SyntaxFactory.IdentifierName(allVisitMethods.FirstOrDefault(d => d.Parameters[0].Type.Name == c.Type.Name).Name)), SyntaxFactory.ArgumentList().AddArguments(SyntaxFactory.Argument(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("expression"), SyntaxFactory.IdentifierName(c.Name)))))), SyntaxFactory.IfStatement(SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, result), SyntaxFactory.Block(SyntaxFactory.ReturnStatement(expressionParam))), }) .SelectMany(c => c) .ToArray(); var collectionPropertyChecks = collectionProperties.Select(c => { var readonlyInterface = c.Type.AllInterfaces.Concat(new [] { c.Type }).Single(d => d.Name == "IReadOnlyList"); var type = ((INamedTypeSymbol)readonlyInterface).TypeArguments[0]; var visitMethodToCall = allVisitMethods.FirstOrDefault(d => d.Parameters[0].Type.AllInterfaces.Concat(new[] { d.Parameters[0].Type as INamedTypeSymbol }).Any(e => e.Name == "IReadOnlyList" && e.TypeArguments[0].Name == type.Name)); if (visitMethodToCall == null) { if (IsOfType(type, "Expression")) { visitMethodToCall = allVisitMethods.FirstOrDefault(d => d.Parameters[0].Type.AllInterfaces.Concat(new[] { d.Parameters[0].Type as INamedTypeSymbol }).Any(e => e.Name == "IReadOnlyList" && e.TypeArguments[0].Name == nameof(Expression))); } else { visitMethodToCall = allVisitMethods.Where(d => d.Name.EndsWith("ObjectList")).FirstOrDefault(d => d.Parameters[0].Type.AllInterfaces.Concat(new[] { d.Parameters[0].Type as INamedTypeSymbol }).Any(e => e.Name == "IReadOnlyList" && e.TypeArguments[0].Name == "T")); } } var visitMethodMethodToCallExpr = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("this"), SyntaxFactory.IdentifierName(visitMethodToCall.Name)); return(new StatementSyntax[] { SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, currentObject, SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("current"), SyntaxFactory.IdentifierName(c.Name)))), SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression(visitMethodMethodToCallExpr, SyntaxFactory.ArgumentList().AddArguments(SyntaxFactory.Argument(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("expression"), SyntaxFactory.IdentifierName(c.Name)))))), SyntaxFactory.IfStatement(SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, result), SyntaxFactory.Block(SyntaxFactory.ReturnStatement(expressionParam))) }); }) .SelectMany(c => c) .ToArray(); return(SyntaxFactory .Block() .AddStatements(SyntaxFactory.LocalDeclarationStatement(variableCurrent)) .AddStatements(ifTryGetValue) .AddStatements(simplePropertyChecks) .AddStatements(expressionPropertyChecks) .AddStatements(collectionPropertyChecks) .AddStatements(SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, currentObject, SyntaxFactory.IdentifierName("current")))) .AddStatements(SyntaxFactory.ReturnStatement(expressionParam))); }
private static BlockSyntax CallNativePointerOverload(MethodDeclarationSyntax nativePointerOverload, GeneratorFlags flags, IReadOnlyDictionary <ParameterSyntax, FriendlyFlags> parametersToFriendlyTransform) { Func <ParameterSyntax, IdentifierNameSyntax> getLocalSubstituteName = p => SyntaxFactory.IdentifierName(p.Identifier.ValueText + "Local"); var invocationArguments = new Dictionary <ParameterSyntax, ArgumentSyntax>(); foreach (var p in nativePointerOverload.ParameterList.Parameters) { var refOrOut = p.Modifiers.FirstOrDefault(m => m.IsKind(SyntaxKind.RefKeyword) || m.IsKind(SyntaxKind.OutKeyword)); invocationArguments[p] = SyntaxFactory .Argument(SyntaxFactory.IdentifierName(p.Identifier)) .WithRefOrOutKeyword(refOrOut); } var prelude = new List <StatementSyntax>(); var postlude = new List <StatementSyntax>(); var fixedStatements = new List <FixedStatementSyntax>(); foreach (var parameter in nativePointerOverload.ParameterList.Parameters.Where(p => p.Type is PointerTypeSyntax)) { var parameterName = SyntaxFactory.IdentifierName(parameter.Identifier); var localVarName = getLocalSubstituteName(parameter); FriendlyFlags friendlyFlags; if (flags.HasFlag(GeneratorFlags.NativePointerToFriendly) && parametersToFriendlyTransform.TryGetValue(parameter, out friendlyFlags)) { if (friendlyFlags.HasFlag(FriendlyFlags.Array)) { var fixedArrayDecl = SyntaxFactory.VariableDeclarator(localVarName.Identifier) .WithInitializer(SyntaxFactory.EqualsValueClause(parameterName)); fixedStatements.Add(SyntaxFactory.FixedStatement( SyntaxFactory.VariableDeclaration(parameter.Type).AddVariables(fixedArrayDecl), SyntaxFactory.Block())); invocationArguments[parameter] = invocationArguments[parameter].WithExpression(localVarName); } else { if (friendlyFlags.HasFlag(FriendlyFlags.Optional)) { var nullableType = (PointerTypeSyntax)parameter.Type; var hasValueExpression = SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(parameter.Identifier), SyntaxFactory.IdentifierName(nameof(Nullable <int> .HasValue))); var valueExpression = SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(parameter.Identifier), SyntaxFactory.IdentifierName(nameof(Nullable <int> .Value))); var defaultExpression = SyntaxFactory.DefaultExpression(nullableType.ElementType); var varStatement = SyntaxFactory.VariableDeclaration(nullableType.ElementType).AddVariables( SyntaxFactory.VariableDeclarator(localVarName.Identifier) .WithInitializer(SyntaxFactory.EqualsValueClause( SyntaxFactory.ConditionalExpression( hasValueExpression, valueExpression, defaultExpression)))); prelude.Add(SyntaxFactory.LocalDeclarationStatement(varStatement)); if (friendlyFlags.HasFlag(FriendlyFlags.Out)) { // someParam = someParamLocal; var assignBackToParameter = SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, parameterName, localVarName); var conditionalStatement = SyntaxFactory.IfStatement( hasValueExpression, SyntaxFactory.ExpressionStatement(assignBackToParameter)); postlude.Add(conditionalStatement); } invocationArguments[parameter] = invocationArguments[parameter].WithExpression( SyntaxFactory.ConditionalExpression( hasValueExpression, SyntaxFactory.PrefixUnaryExpression(SyntaxKind.AddressOfExpression, localVarName), SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression))); } else if (friendlyFlags.HasFlag(FriendlyFlags.Out)) { var fixedDecl = SyntaxFactory.VariableDeclarator(localVarName.Identifier) .WithInitializer(SyntaxFactory.EqualsValueClause( SyntaxFactory.PrefixUnaryExpression( SyntaxKind.AddressOfExpression, parameterName))); fixedStatements.Add(SyntaxFactory.FixedStatement( SyntaxFactory.VariableDeclaration(parameter.Type).AddVariables(fixedDecl), SyntaxFactory.Block())); invocationArguments[parameter] = invocationArguments[parameter].WithExpression(localVarName); } else { invocationArguments[parameter] = invocationArguments[parameter] .WithExpression(SyntaxFactory.PrefixUnaryExpression(SyntaxKind.AddressOfExpression, parameterName)); } } } else if (flags.HasFlag(GeneratorFlags.NativePointerToIntPtr)) { var varStatement = SyntaxFactory.VariableDeclaration(parameter.Type); var declarator = SyntaxFactory.VariableDeclarator(localVarName.Identifier); if (parameter.Modifiers.Any(m => m.IsKind(SyntaxKind.OutKeyword))) { var assignment = SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, parameterName, SyntaxFactory.ObjectCreationExpression( IntPtrTypeSyntax, SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(localVarName))), null)); postlude.Add(SyntaxFactory.ExpressionStatement(assignment)); } else { var voidStarPointer = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(parameter.Identifier), SyntaxFactory.IdentifierName(nameof(IntPtr.ToPointer))), SyntaxFactory.ArgumentList()); var typedPointer = parameter.Type.Equals(VoidStar) ? (ExpressionSyntax)voidStarPointer : SyntaxFactory.CastExpression(parameter.Type, voidStarPointer); declarator = declarator.WithInitializer(SyntaxFactory.EqualsValueClause(typedPointer)); } varStatement = varStatement.AddVariables(declarator); prelude.Add(SyntaxFactory.LocalDeclarationStatement(varStatement)); invocationArguments[parameter] = invocationArguments[parameter].WithExpression(localVarName); } } var invocationExpression = SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName(nativePointerOverload.Identifier.ValueText), SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList( from p in nativePointerOverload.ParameterList.Parameters select invocationArguments[p]))); IdentifierNameSyntax resultVariableName = null; StatementSyntax invocationStatement; if (nativePointerOverload.ReturnType != null && (nativePointerOverload.ReturnType as PredefinedTypeSyntax)?.Keyword.Kind() != SyntaxKind.VoidKeyword) { resultVariableName = SyntaxFactory.IdentifierName("result"); // TODO: ensure this is unique. invocationStatement = SyntaxFactory.LocalDeclarationStatement( SyntaxFactory.VariableDeclaration(nativePointerOverload.ReturnType) .AddVariables( SyntaxFactory.VariableDeclarator(resultVariableName.Identifier) .WithInitializer(SyntaxFactory.EqualsValueClause(invocationExpression)))); } else { invocationStatement = SyntaxFactory.ExpressionStatement(invocationExpression); } var block = SyntaxFactory.Block() .AddStatements(prelude.ToArray()) .AddStatements(invocationStatement) .AddStatements(postlude.ToArray()); if (resultVariableName != null) { ExpressionSyntax returnedValue = nativePointerOverload.ReturnType is PointerTypeSyntax ? (ExpressionSyntax)SyntaxFactory.ObjectCreationExpression( IntPtrTypeSyntax, SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(resultVariableName))), null) : resultVariableName; block = block.AddStatements(SyntaxFactory.ReturnStatement(returnedValue)); } if (fixedStatements.Count > 0) { StatementSyntax outermost = block; foreach (var statement in fixedStatements) { outermost = statement.WithStatement(outermost); } block = SyntaxFactory.Block(outermost); } return(block); }
private static BlockSyntax CreateNewBlockParent(StatementSyntax statement, SemanticModel semanticModel, ObjectCreationExpressionSyntax objectCreationExpression, ISymbol variableSymbol) { var blockParent = statement.FirstAncestorOrSelf <BlockSyntax>(); var assignmentExpressions = ObjectInitializerAnalyzer.FindAssignmentExpressions(semanticModel, statement, variableSymbol); var newBlockParent = SyntaxFactory.Block() .WithLeadingTrivia(blockParent.GetLeadingTrivia()) .WithTrailingTrivia(blockParent.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); for (int i = 0; i < blockParent.Statements.Count; i++) { var blockStatement = blockParent.Statements[i]; if (blockStatement.Equals(statement)) { var initializationExpressions = new List <AssignmentExpressionSyntax>(); foreach (var expressionStatement in assignmentExpressions) { var assignmentExpression = expressionStatement.Expression as AssignmentExpressionSyntax; var memberAccess = assignmentExpression.Left as MemberAccessExpressionSyntax; var propertyIdentifier = memberAccess.Name as IdentifierNameSyntax; var newAssignmentExpression = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, propertyIdentifier, assignmentExpression.Right); initializationExpressions.Add(newAssignmentExpression); } if (objectCreationExpression.Initializer != null) { var existentInitilizers = objectCreationExpression.Initializer.Expressions.Cast <AssignmentExpressionSyntax>() .Where(ae => { var propertyIdentifier = ae.Left.ToFullString().Trim(); return(initializationExpressions.All(ie => ie.Left.ToFullString().Trim() != propertyIdentifier)); }) .Select(ae => ae.WithoutTrivia()) .ToList(); initializationExpressions.InsertRange(0, existentInitilizers); } var initializers = SyntaxFactory.SeparatedList <ExpressionSyntax>(initializationExpressions); var newObjectCreationExpression = objectCreationExpression.WithInitializer( SyntaxFactory.InitializerExpression( SyntaxKind.ObjectInitializerExpression, SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.OpenBraceToken, SyntaxFactory.ParseTrailingTrivia(Environment.NewLine)), initializers, SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.CloseBraceToken, SyntaxFactory.ParseTrailingTrivia("")) )) .WithLeadingTrivia(objectCreationExpression.GetLeadingTrivia()) .WithTrailingTrivia(objectCreationExpression.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); if (newObjectCreationExpression.ArgumentList?.Arguments.Count == 0) { newObjectCreationExpression = newObjectCreationExpression.WithArgumentList(null); } var newLocalDeclarationStatement = statement.ReplaceNode(objectCreationExpression, newObjectCreationExpression) .WithLeadingTrivia(statement.GetLeadingTrivia()) .WithTrailingTrivia(statement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); newBlockParent = newBlockParent.AddStatements(newLocalDeclarationStatement); i += initializationExpressions.Count; } else { newBlockParent = newBlockParent.AddStatements(blockStatement .WithLeadingTrivia(blockStatement.GetLeadingTrivia()) .WithTrailingTrivia(blockStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation)); } } return(newBlockParent); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) { return; } var span = context.Span; if (!span.IsEmpty) { return; } var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) { return; } var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) { return; } var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var property = root.FindNode(span) as PropertyDeclarationSyntax; if (property == null || !property.Identifier.Span.Contains(span)) { return; } if (property.AccessorList?.Accessors.Any(b => !IsEmptyOrNotImplemented(b.Body)) != false) //ignore properties with >=1 accessor body { return; } TypeDeclarationSyntax enclosingTypeDeclaration = property.Ancestors().OfType <TypeDeclarationSyntax>().FirstOrDefault(); if (enclosingTypeDeclaration == null || enclosingTypeDeclaration is InterfaceDeclarationSyntax) { return; } context.RegisterRefactoring( CodeActionFactory.Create( property.Identifier.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("To property with backing field"), t2 => { string name = GetNameProposal(property.Identifier.ValueText, model, root); //create our backing store var backingStore = SyntaxFactory.FieldDeclaration( SyntaxFactory.VariableDeclaration( property.Type, SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>(SyntaxFactory.VariableDeclarator(name))) ).WithModifiers(!property.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword)) ? SyntaxFactory.TokenList() : SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.StaticKeyword))) .WithAdditionalAnnotations(Formatter.Annotation); //create our new property var fieldExpression = name == "value" ? (ExpressionSyntax)SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName("value")) : SyntaxFactory.IdentifierName(name); var newPropAnno = new SyntaxAnnotation(); var syntaxList = new SyntaxList <AccessorDeclarationSyntax>(); var hasSetter = property.AccessorList.Accessors.Any(acc => acc.IsKind(SyntaxKind.SetAccessorDeclaration)); var hasGetter = property.AccessorList.Accessors.Any(acc => acc.IsKind(SyntaxKind.GetAccessorDeclaration)); if (hasGetter) { var getBody = SyntaxFactory.Block(SyntaxFactory.ReturnStatement(fieldExpression)); var getter = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, getBody); getter = getter.WithModifiers(property.AccessorList.Accessors.First(acc => acc.IsKind(SyntaxKind.GetAccessorDeclaration)).Modifiers); syntaxList = syntaxList.Add(getter); if (!hasSetter) { backingStore = backingStore.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword))); } } if (hasSetter) { var setBody = SyntaxFactory.Block(SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, fieldExpression, SyntaxFactory.IdentifierName("value")))); var setter = SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration, setBody); setter = setter.WithModifiers(property.AccessorList.Accessors.First(acc => acc.IsKind(SyntaxKind.SetAccessorDeclaration)).Modifiers); syntaxList = syntaxList.Add(setter); } var newProperty = property.WithAccessorList(SyntaxFactory.AccessorList(syntaxList)) .WithAdditionalAnnotations(newPropAnno, Formatter.Annotation); var newRoot = root.ReplaceNode((SyntaxNode)property, newProperty); return(Task.FromResult(document.WithSyntaxRoot(newRoot.InsertNodesBefore(newRoot.GetAnnotatedNodes(newPropAnno).First(), new List <SyntaxNode>() { backingStore })))); }) ); }
private static ExpressionSyntax VisitAnonymousClassCreationExpression(ConversionContext context, ObjectCreationExpr newExpr, List <BodyDeclaration> anonBody) { string baseTypeName = TypeHelper.ConvertType(newExpr.getType().getName()); string anonTypeName = string.Empty; for (int i = 0; i <= 100; i++) { if (i == 100) { throw new InvalidOperationException("Too many anonymous types"); } anonTypeName = string.Format("Anonymous{0}{1}", baseTypeName, i == 0 ? string.Empty : i.ToString()); if (!context.UsedAnonymousTypeNames.Contains(anonTypeName)) { context.UsedAnonymousTypeNames.Add(anonTypeName); break; // go with this one } } var classSyntax = SyntaxFactory.ClassDeclaration(anonTypeName) .AddModifiers( SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.SealedKeyword)) .WithBaseList(SyntaxFactory.BaseList(SyntaxFactory.SeparatedList(new List <BaseTypeSyntax> { SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseTypeName(baseTypeName)) }))); var parentField = SyntaxFactory.FieldDeclaration( SyntaxFactory.VariableDeclaration(SyntaxFactory.ParseTypeName(context.LastTypeName)).AddVariables(SyntaxFactory.VariableDeclarator("parent"))) .AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword)); var ctorSyntax = SyntaxFactory.ConstructorDeclaration(anonTypeName) .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)) .AddParameterListParameters(SyntaxFactory.Parameter(SyntaxFactory.ParseToken("parent")).WithType(SyntaxFactory.ParseTypeName(context.LastTypeName))) .AddBodyStatements(SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName("parent")), SyntaxFactory.IdentifierName("parent")))); classSyntax = classSyntax.AddMembers(ctorSyntax, parentField); foreach (var member in anonBody) { var memberSyntax = BodyDeclarationVisitor.VisitBodyDeclarationForClass(context, classSyntax, member); if (memberSyntax != null) { classSyntax = classSyntax.AddMembers(memberSyntax); } } context.PendingAnonymousTypes.Enqueue(classSyntax); var args = newExpr.getArgs().ToList <Expression>(); if (args == null || args.Count == 0) { return(SyntaxFactory.ObjectCreationExpression(SyntaxFactory.ParseTypeName(anonTypeName)) .AddArgumentListArguments(SyntaxFactory.Argument(SyntaxFactory.ThisExpression()))); } var argSyntaxes = new List <ArgumentSyntax>(); argSyntaxes.Add(SyntaxFactory.Argument(SyntaxFactory.ThisExpression())); foreach (var arg in args) { var argSyntax = ExpressionVisitor.VisitExpression(context, arg); argSyntaxes.Add(SyntaxFactory.Argument(argSyntax)); } return(SyntaxFactory.ObjectCreationExpression(SyntaxFactory.ParseTypeName(anonTypeName), SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(argSyntaxes, Enumerable.Repeat(SyntaxFactory.Token(SyntaxKind.CommaToken), argSyntaxes.Count - 1))), null)); }
public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter) { var localFns = root.DescendantNodes().OfType <LocalFunctionStatementSyntax>(); var updatedBlocks = new Dictionary <SyntaxNode, List <StatementSyntax> >(); var initForBlocks = new Dictionary <SyntaxNode, List <StatementSyntax> >(); var updatedClasses = new Dictionary <TypeDeclarationSyntax, List <DelegateDeclarationSyntax> >(); foreach (var fn in localFns) { try { var parentNode = fn.Parent; var usage = GetFirstUsageLocalFunc(model, fn, parentNode); var beforeStatement = usage?.Ancestors().OfType <StatementSyntax>().FirstOrDefault(ss => ss.Parent == parentNode); if (beforeStatement is LocalFunctionStatementSyntax beforeFn) { List <SyntaxNode> ignore = new List <SyntaxNode>(); var usageFn = usage; var beforeStatementFn = beforeStatement; while (beforeStatementFn != null && beforeStatementFn is LocalFunctionStatementSyntax) { ignore.Add(usageFn); usageFn = GetFirstUsageLocalFunc(model, fn, parentNode, ignore); beforeStatementFn = usageFn?.Ancestors().OfType <StatementSyntax>().FirstOrDefault(ss => ss.Parent == parentNode); } usage = GetFirstUsageLocalFunc(model, beforeFn, parentNode); beforeStatement = usage?.Ancestors().OfType <StatementSyntax>().FirstOrDefault(ss => ss.Parent == parentNode); if (beforeStatementFn != null && (beforeStatement == null || beforeStatementFn.SpanStart < beforeStatement.SpanStart)) { beforeStatement = beforeStatementFn; } } var customDelegate = false; if (fn.TypeParameterList != null && fn.TypeParameterList.Parameters.Count > 0) { customDelegate = true; } else { foreach (var prm in fn.ParameterList.Parameters) { if (prm.Default != null) { customDelegate = true; break; } foreach (var modifier in prm.Modifiers) { var kind = modifier.Kind(); if (kind == SyntaxKind.RefKeyword || kind == SyntaxKind.OutKeyword || kind == SyntaxKind.ParamsKeyword) { customDelegate = true; break; } } if (customDelegate) { break; } } } var returnType = fn.ReturnType.WithoutLeadingTrivia().WithoutTrailingTrivia(); var isVoid = returnType is PredefinedTypeSyntax ptsInstance && ptsInstance.Keyword.Kind() == SyntaxKind.VoidKeyword; TypeSyntax varType; if (customDelegate) { var typeDecl = parentNode.Ancestors().OfType <TypeDeclarationSyntax>().FirstOrDefault(); var delegates = updatedClasses.ContainsKey(typeDecl) ? updatedClasses[typeDecl] : new List <DelegateDeclarationSyntax>(); var name = $"___{fn.Identifier.ValueText}_Delegate_{delegates.Count}"; var delDecl = SyntaxFactory.DelegateDeclaration(returnType, SyntaxFactory.Identifier(name)) .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PrivateKeyword))) .WithParameterList(fn.ParameterList).NormalizeWhitespace(); delegates.Add(delDecl); updatedClasses[typeDecl] = delegates; varType = SyntaxFactory.IdentifierName(name); } else if (isVoid) { if (fn.ParameterList.Parameters.Count == 0) { varType = SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Action")); } else { varType = SyntaxFactory.QualifiedName ( SyntaxFactory.IdentifierName("System"), SyntaxFactory.GenericName("Action").WithTypeArgumentList ( SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(fn.ParameterList.Parameters.Select(p => p.Type))) ) ); } } else { if (fn.ParameterList.Parameters.Count == 0) { varType = SyntaxFactory.QualifiedName( SyntaxFactory.IdentifierName("System"), SyntaxFactory.GenericName("Func").WithTypeArgumentList( SyntaxFactory.TypeArgumentList(SyntaxFactory.SingletonSeparatedList(returnType)) ) ); } else { varType = SyntaxFactory.QualifiedName ( SyntaxFactory.IdentifierName("System"), SyntaxFactory.GenericName("Func").WithTypeArgumentList ( SyntaxFactory.TypeArgumentList( SyntaxFactory.SeparatedList( fn.ParameterList.Parameters.Select(p => p.Type).Concat( new TypeSyntax[] { returnType } ) ) ) ) ); } } List <ParameterSyntax> prms = new List <ParameterSyntax>(); if (customDelegate) { foreach (var prm in fn.ParameterList.Parameters) { var newPrm = prm.WithDefault(null); var idx = newPrm.Modifiers.IndexOf(SyntaxKind.ParamsKeyword); if (idx > -1) { newPrm = newPrm.WithModifiers(newPrm.Modifiers.RemoveAt(idx)); } prms.Add(newPrm); } } else { foreach (var prm in fn.ParameterList.Parameters) { prms.Add(SyntaxFactory.Parameter(prm.Identifier)); } } var initVar = SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType).WithVariables( SyntaxFactory.SingletonSeparatedList( SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(fn.Identifier.ValueText)).WithInitializer ( SyntaxFactory.EqualsValueClause(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)) ) ) )).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace(Emitter.NEW_LINE)); var lambda = SyntaxFactory.ParenthesizedLambdaExpression(fn.Body ?? (CSharpSyntaxNode)fn.ExpressionBody.Expression).WithParameterList( SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(prms)) ); if (fn.Modifiers.Any(SyntaxKind.AsyncKeyword)) { lambda = lambda.WithAsyncKeyword(SyntaxFactory.Token(SyntaxKind.AsyncKeyword)); } var assignment = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(fn.Identifier.ValueText), lambda )).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace(Emitter.NEW_LINE)); List <StatementSyntax> statements = null; if (updatedBlocks.ContainsKey(parentNode)) { statements = updatedBlocks[parentNode]; } else { if (parentNode is BlockSyntax bs) { statements = bs.Statements.ToList(); } else if (parentNode is SwitchSectionSyntax sss) { statements = sss.Statements.ToList(); } } var fnIdx = statements.IndexOf(fn); statements.Insert(beforeStatement != null ? statements.IndexOf(beforeStatement) : Math.Max(0, fnIdx), assignment); updatedBlocks[parentNode] = statements; statements = initForBlocks.ContainsKey(parentNode) ? initForBlocks[parentNode] : new List <StatementSyntax>(); statements.Insert(0, initVar); initForBlocks[parentNode] = statements; } catch (Exception e) { throw new ReplacerException(fn, e); } } foreach (var key in initForBlocks.Keys) { updatedBlocks[key] = initForBlocks[key].Concat(updatedBlocks[key]).ToList(); } if (updatedClasses.Count > 0) { root = root.ReplaceNodes(updatedClasses.Keys, (t1, t2) => { var members = updatedClasses[t1].ToArray(); t1 = t1.ReplaceNodes(updatedBlocks.Keys, (b1, b2) => { SyntaxNode result = b1 is SwitchSectionSyntax sss ? sss.WithStatements(SyntaxFactory.List(updatedBlocks[b1])) : (SyntaxNode)(((BlockSyntax)b1).WithStatements(SyntaxFactory.List(updatedBlocks[b1]))); return(result); }); var cls = t1 as ClassDeclarationSyntax; if (cls != null) { return(cls.AddMembers(members)); } var structDecl = t2 as StructDeclarationSyntax; if (structDecl != null) { return(structDecl.AddMembers(members)); } return(t1); }); } else if (updatedBlocks.Count > 0) { root = root.ReplaceNodes(updatedBlocks.Keys, (b1, b2) => { SyntaxNode result = b1 is SwitchSectionSyntax sss ? sss.WithStatements(SyntaxFactory.List(updatedBlocks[b1])) : (SyntaxNode)(((BlockSyntax)b1).WithStatements(SyntaxFactory.List(updatedBlocks[b1]))); return(result); }); } root = root.RemoveNodes(root.DescendantNodes().OfType <LocalFunctionStatementSyntax>(), SyntaxRemoveOptions.KeepTrailingTrivia | SyntaxRemoveOptions.KeepLeadingTrivia); return(root); }
private ExpressionSyntax TryRewrite(string aggregationMethod, ExpressionSyntax collection, ITypeSymbol semanticReturnType, List <LinqStep> chain, InvocationExpressionSyntax node) { var returnType = SyntaxFactory.ParseTypeName(semanticReturnType.ToDisplayString()); if (RootMethodsThatRequireYieldReturn.Contains(aggregationMethod)) { return(RewriteAsLoop( returnType, Enumerable.Empty <StatementSyntax>(), Enumerable.Empty <StatementSyntax>(), collection, chain, (inv, arguments, param) => { return SyntaxFactory.YieldStatement(SyntaxKind.YieldReturnStatement, SyntaxFactory.IdentifierName(param.Identifier.ValueText)); }, true )); } if (aggregationMethod.Contains(".Sum")) { var elementType = ((returnType as NullableTypeSyntax)?.ElementType ?? returnType); return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("sum_", SyntaxFactory.CastExpression(elementType, SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(0)))) }, new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName("sum_")) }, collection, MaybeAddSelect(chain, node.ArgumentList.Arguments.Count != 0), (inv, arguments, param) => { var currentValue = SyntaxFactory.IdentifierName(param.Identifier.ValueText); return IfNullableIsNotNull(elementType != returnType, currentValue, x => { return SyntaxFactory.CheckedStatement(SyntaxKind.CheckedStatement, SyntaxFactory.Block(SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.AddAssignmentExpression, SyntaxFactory.IdentifierName("sum_"), x)))); }); } )); } if (aggregationMethod.Contains(".Max") || aggregationMethod.Contains(".Min")) { var minmax = aggregationMethod.Contains(".Max") ? "max_" : "min_"; var elementType = ((returnType as NullableTypeSyntax)?.ElementType ?? returnType); return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("found_", SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression)), CreateLocalVariableDeclaration(minmax, SyntaxFactory.CastExpression(elementType, SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(0)))) }, new[] { SyntaxFactory.Block( SyntaxFactory.IfStatement(SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, SyntaxFactory.IdentifierName("found_")), returnType == elementType ? (StatementSyntax)CreateThrowException("System.InvalidOperationException", "The sequence did not contain any elements.") : SyntaxFactory.ReturnStatement(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)) ), SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(minmax)) ) }, collection, MaybeAddSelect(chain, node.ArgumentList.Arguments.Count != 0), (inv, arguments, param) => { var identifierNameSyntax = SyntaxFactory.IdentifierName(param.Identifier.ValueText); return IfNullableIsNotNull(elementType != returnType, identifierNameSyntax, x => { var assignmentExpressionSyntax = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(minmax), x); var condition = SyntaxFactory.BinaryExpression(aggregationMethod.Contains(".Max") ? SyntaxKind.GreaterThanExpression : SyntaxKind.LessThanExpression, x, SyntaxFactory.IdentifierName(minmax)); var kind = (elementType as PredefinedTypeSyntax).Keyword.Kind(); if (kind == SyntaxKind.DoubleKeyword || kind == SyntaxKind.FloatKeyword) { condition = SyntaxFactory.BinaryExpression(SyntaxKind.LogicalOrExpression, condition, SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, elementType, SyntaxFactory.IdentifierName("IsNaN")), CreateArguments(x))); } return SyntaxFactory.IfStatement(SyntaxFactory.IdentifierName("found_"), SyntaxFactory.Block(SyntaxFactory.IfStatement(condition, SyntaxFactory.ExpressionStatement(assignmentExpressionSyntax))), SyntaxFactory.ElseClause(SyntaxFactory.Block(SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("found_"), SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression))), SyntaxFactory.ExpressionStatement(assignmentExpressionSyntax)))); }); })); } if (aggregationMethod.Contains(".Average")) { var elementType = ((returnType as NullableTypeSyntax)?.ElementType ?? returnType); var primitive = ((PredefinedTypeSyntax)elementType).Keyword.Kind(); ExpressionSyntax sumIdentifier = SyntaxFactory.IdentifierName("sum_"); ExpressionSyntax countIdentifier = SyntaxFactory.IdentifierName("count_"); if (primitive != SyntaxKind.DecimalKeyword) { sumIdentifier = SyntaxFactory.CastExpression(CreatePrimitiveType(SyntaxKind.DoubleKeyword), sumIdentifier); countIdentifier = SyntaxFactory.CastExpression(CreatePrimitiveType(SyntaxKind.DoubleKeyword), countIdentifier); } ExpressionSyntax division = SyntaxFactory.BinaryExpression(SyntaxKind.DivideExpression, sumIdentifier, countIdentifier); if (primitive != SyntaxKind.DoubleKeyword && primitive != SyntaxKind.DecimalKeyword) { division = SyntaxFactory.CastExpression(elementType, SyntaxFactory.ParenthesizedExpression(division)); } return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("sum_", SyntaxFactory.CastExpression(primitive == SyntaxKind.IntKeyword || primitive == SyntaxKind.LongKeyword ? CreatePrimitiveType(SyntaxKind.LongKeyword) : primitive == SyntaxKind.DecimalKeyword ? CreatePrimitiveType(SyntaxKind.DecimalKeyword) : CreatePrimitiveType(SyntaxKind.DoubleKeyword), SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(0)))), CreateLocalVariableDeclaration("count_", SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.ParseToken("0L"))) }, new[] { SyntaxFactory.Block( SyntaxFactory.IfStatement(SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, SyntaxFactory.IdentifierName("count_"), SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.ParseToken("0"))), returnType == elementType ? (StatementSyntax)CreateThrowException("System.InvalidOperationException", "The sequence did not contain any elements.") : SyntaxFactory.ReturnStatement(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)) ), SyntaxFactory.ReturnStatement(division) ) }, collection, MaybeAddSelect(chain, node.ArgumentList.Arguments.Count != 0), (inv, arguments, param) => { var currentValue = SyntaxFactory.IdentifierName(param.Identifier.ValueText); return IfNullableIsNotNull(elementType != returnType, currentValue, x => { return SyntaxFactory.CheckedStatement(SyntaxKind.CheckedStatement, SyntaxFactory.Block( SyntaxFactory.ExpressionStatement(SyntaxFactory.PostfixUnaryExpression(SyntaxKind.PostIncrementExpression, SyntaxFactory.IdentifierName("count_"))), SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.AddAssignmentExpression, SyntaxFactory.IdentifierName("sum_"), x)) )); }); } )); } if (aggregationMethod == AnyMethod || aggregationMethod == AnyWithConditionMethod) { return(RewriteAsLoop( CreatePrimitiveType(SyntaxKind.BoolKeyword), Enumerable.Empty <StatementSyntax>(), new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression)) }, collection, MaybeAddFilter(chain, aggregationMethod == AnyWithConditionMethod), (inv, arguments, param) => { return SyntaxFactory.ReturnStatement(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression)); } )); } if (aggregationMethod == ListForEachMethod || aggregationMethod == IEnumerableForEachMethod) { return(RewriteAsLoop( CreatePrimitiveType(SyntaxKind.VoidKeyword), Enumerable.Empty <StatementSyntax>(), Enumerable.Empty <StatementSyntax>(), collection, chain, (inv, arguments, param) => { var lambda = inv.Lambda ?? new Lambda((AnonymousFunctionExpressionSyntax)inv.Arguments.First()); return SyntaxFactory.ExpressionStatement(InlineOrCreateMethod(lambda, CreatePrimitiveType(SyntaxKind.VoidKeyword), arguments, param)); } )); } if (aggregationMethod == ContainsMethod) { var elementType = SyntaxFactory.ParseTypeName(semantic.GetTypeInfo(node.ArgumentList.Arguments.First().Expression).ConvertedType.ToDisplayString()); var comparerIdentifier = ((elementType as NullableTypeSyntax)?.ElementType ?? elementType) is PredefinedTypeSyntax ? null : SyntaxFactory.IdentifierName("comparer_"); return(RewriteAsLoop( CreatePrimitiveType(SyntaxKind.BoolKeyword), comparerIdentifier != null ? new StatementSyntax[] { CreateLocalVariableDeclaration("comparer_", SyntaxFactory.ParseExpression("System.Collections.Generic.EqualityComparer<" + elementType.ToString() + ">.Default")) } : Enumerable.Empty <StatementSyntax>(), new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression)) }, collection, chain, (inv, arguments, param) => { var target = SyntaxFactory.IdentifierName("_target"); var current = SyntaxFactory.IdentifierName(param.Identifier.ValueText); var condition = comparerIdentifier != null ? SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, comparerIdentifier, SyntaxFactory.IdentifierName("Equals")), CreateArguments(current, target)) : (ExpressionSyntax)SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, current, target); return SyntaxFactory.IfStatement(condition, SyntaxFactory.ReturnStatement(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression))); }, additionalParameters: new[] { Tuple.Create(CreateParameter("_target", elementType), node.ArgumentList.Arguments.First().Expression) } )); } if (aggregationMethod == AllWithConditionMethod) // All alone does not exist { return(RewriteAsLoop( CreatePrimitiveType(SyntaxKind.BoolKeyword), Enumerable.Empty <StatementSyntax>(), new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression)) }, collection, chain, (inv, arguments, param) => { var lambda = (LambdaExpressionSyntax)inv.Arguments.First(); return SyntaxFactory.IfStatement(SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, SyntaxFactory.ParenthesizedExpression(InlineOrCreateMethod(new Lambda(lambda), CreatePrimitiveType(SyntaxKind.BoolKeyword), arguments, param))), SyntaxFactory.ReturnStatement(SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression) )); } )); } if (aggregationMethod == CountMethod || aggregationMethod == CountWithConditionMethod || aggregationMethod == LongCountMethod || aggregationMethod == LongCountWithConditionMethod) { return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("_count", SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.ParseToken(aggregationMethod == LongCountMethod || aggregationMethod == LongCountWithConditionMethod ? "0L" : "0"))) }, new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName("_count")) }, collection, MaybeAddFilter(chain, aggregationMethod == CountWithConditionMethod || aggregationMethod == LongCountWithConditionMethod), (inv, arguments, param) => { return SyntaxFactory.ExpressionStatement(SyntaxFactory.PostfixUnaryExpression(SyntaxKind.PostIncrementExpression, SyntaxFactory.IdentifierName("_count"))); } )); } if (aggregationMethod == ElementAtMethod || aggregationMethod == ElementAtOrDefaultMethod) { return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("_count", SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.ParseToken(aggregationMethod == LongCountMethod || aggregationMethod == LongCountWithConditionMethod ? "0L" : "0"))) }, new[] { aggregationMethod == ElementAtMethod ? (StatementSyntax)CreateThrowException("System.InvalidOperationException", "The specified index is not included in the sequence.") : SyntaxFactory.ReturnStatement(SyntaxFactory.DefaultExpression(returnType)) }, collection, MaybeAddFilter(chain, aggregationMethod == CountWithConditionMethod || aggregationMethod == LongCountWithConditionMethod), (inv, arguments, param) => { return SyntaxFactory.IfStatement(SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, SyntaxFactory.IdentifierName("_requestedPosition"), SyntaxFactory.PostfixUnaryExpression(SyntaxKind.PostIncrementExpression, SyntaxFactory.IdentifierName("_count"))), SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(param.Identifier.ValueText))); }, additionalParameters: new[] { Tuple.Create(CreateParameter("_requestedPosition", CreatePrimitiveType(SyntaxKind.IntKeyword)), node.ArgumentList.Arguments.First().Expression) } )); } if (aggregationMethod == FirstMethod || aggregationMethod == FirstWithConditionMethod) { return(RewriteAsLoop( returnType, Enumerable.Empty <StatementSyntax>(), new[] { CreateThrowException("System.InvalidOperationException", "The sequence did not contain any elements.") }, collection, MaybeAddFilter(chain, aggregationMethod == FirstWithConditionMethod), (inv, arguments, param) => { return SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(param.Identifier.ValueText)); } )); } if (aggregationMethod == FirstOrDefaultMethod || aggregationMethod == FirstOrDefaultWithConditionMethod) { return(RewriteAsLoop( returnType, Enumerable.Empty <StatementSyntax>(), new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.DefaultExpression(returnType)) }, collection, MaybeAddFilter(chain, aggregationMethod == FirstOrDefaultWithConditionMethod), (inv, arguments, param) => { return SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(param.Identifier.ValueText)); } )); } if (aggregationMethod == LastOrDefaultMethod || aggregationMethod == LastOrDefaultWithConditionMethod) { return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("_last", SyntaxFactory.DefaultExpression(returnType)) }, new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName("_last")) }, collection, MaybeAddFilter(chain, aggregationMethod == LastOrDefaultWithConditionMethod), (inv, arguments, param) => { return SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("_last"), SyntaxFactory.IdentifierName(param.Identifier.ValueText))); } )); } if (aggregationMethod == LastMethod || aggregationMethod == LastWithConditionMethod) { return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("_last", SyntaxFactory.DefaultExpression(returnType)), CreateLocalVariableDeclaration("_found", SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression)) }, new StatementSyntax[] { SyntaxFactory.IfStatement(SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, SyntaxFactory.IdentifierName("_found")), CreateThrowException("System.InvalidOperationException", "The sequence did not contain any elements.")), SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName("_last")) }, collection, MaybeAddFilter(chain, aggregationMethod == LastWithConditionMethod), (inv, arguments, param) => { return SyntaxFactory.Block( SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("_found"), SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression))), SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("_last"), SyntaxFactory.IdentifierName(param.Identifier.ValueText)))); } )); } if (aggregationMethod == SingleMethod || aggregationMethod == SingleWithConditionMethod) { return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("_last", SyntaxFactory.DefaultExpression(returnType)), CreateLocalVariableDeclaration("_found", SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression)) }, new StatementSyntax[] { SyntaxFactory.IfStatement(SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, SyntaxFactory.IdentifierName("_found")), CreateThrowException("System.InvalidOperationException", "The sequence did not contain any elements.")), SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName("_last")) }, collection, MaybeAddFilter(chain, aggregationMethod == SingleWithConditionMethod), (inv, arguments, param) => { return SyntaxFactory.Block( SyntaxFactory.IfStatement(SyntaxFactory.IdentifierName("_found"), CreateThrowException("System.InvalidOperationException", "The sequence contains more than one element.")), SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("_found"), SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression))), SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("_last"), SyntaxFactory.IdentifierName(param.Identifier.ValueText)))); } )); } if (aggregationMethod == SingleOrDefaultMethod || aggregationMethod == SingleOrDefaultWithConditionMethod) { return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("_last", SyntaxFactory.DefaultExpression(returnType)), CreateLocalVariableDeclaration("_found", SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression)) }, new StatementSyntax[] { SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName("_last")) }, collection, MaybeAddFilter(chain, aggregationMethod == SingleOrDefaultWithConditionMethod), (inv, arguments, param) => { return SyntaxFactory.Block( SyntaxFactory.IfStatement(SyntaxFactory.IdentifierName("_found"), CreateThrowException("System.InvalidOperationException", "The sequence contains more than one element.")), SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("_found"), SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression))), SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("_last"), SyntaxFactory.IdentifierName(param.Identifier.ValueText)))); } )); } if (aggregationMethod == ToListMethod || aggregationMethod == ReverseMethod) { var count = chain.All(x => MethodsThatPreserveCount.Contains(x.MethodName)) ? GetCollectionCount(collection, true) : null; var listIdentifier = SyntaxFactory.IdentifierName("_list"); return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("_list", SyntaxFactory.ObjectCreationExpression(SyntaxFactory.ParseTypeName("System.Collections.Generic.List<" + GetItemType(semanticReturnType).ToDisplayString() + ">"), CreateArguments(count != null ? new[] { count } : Enumerable.Empty <ExpressionSyntax>()), null)) }, aggregationMethod == ReverseMethod ? new StatementSyntax[] { SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("_list"), SyntaxFactory.IdentifierName("Reverse")))), SyntaxFactory.ReturnStatement(listIdentifier) } : new[] { SyntaxFactory.ReturnStatement(listIdentifier) }, collection, chain, (inv, arguments, param) => { return CreateStatement(SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, listIdentifier, SyntaxFactory.IdentifierName("Add")), CreateArguments(new[] { SyntaxFactory.IdentifierName(param.Identifier.ValueText) }))); } )); } if (/*aggregationMethod == ToDictionaryWithKeyMethod || */ aggregationMethod == ToDictionaryWithKeyValueMethod) { var dictIdentifier = SyntaxFactory.IdentifierName("_dict"); return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("_dict", SyntaxFactory.ObjectCreationExpression(returnType, CreateArguments(Enumerable.Empty <ArgumentSyntax>()), null)) }, new[] { SyntaxFactory.ReturnStatement(dictIdentifier) }, collection, chain, (inv, arguments, param) => { var keyLambda = (AnonymousFunctionExpressionSyntax)node.ArgumentList.Arguments.First().Expression; var valueLambda = (AnonymousFunctionExpressionSyntax)node.ArgumentList.Arguments.ElementAtOrDefault(1)?.Expression; return CreateStatement(SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, dictIdentifier, SyntaxFactory.IdentifierName("Add")), CreateArguments(new[] { InlineOrCreateMethod(new Lambda(keyLambda), SyntaxFactory.ParseTypeName(GetLambdaReturnType(keyLambda).ToDisplayString()), arguments, param), aggregationMethod == ToDictionaryWithKeyValueMethod ? InlineOrCreateMethod(new Lambda(valueLambda), SyntaxFactory.ParseTypeName(GetLambdaReturnType(valueLambda).ToDisplayString()), arguments, param): SyntaxFactory.IdentifierName(param.Identifier.ValueText), }))); } )); } if (aggregationMethod == ToArrayMethod) { var count = chain.All(x => MethodsThatPreserveCount.Contains(x.MethodName)) ? GetCollectionCount(collection, false) : null; if (count != null) { var arrayIdentifier = SyntaxFactory.IdentifierName("_array"); return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("_array", SyntaxFactory.ArrayCreationExpression(SyntaxFactory.ArrayType(((ArrayTypeSyntax)returnType).ElementType, SyntaxFactory.List(new[] { SyntaxFactory.ArrayRankSpecifier(CreateSeparatedList(new[] { count })) })))) }, new[] { SyntaxFactory.ReturnStatement(arrayIdentifier) }, collection, chain, (inv, arguments, param) => { return CreateStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.ElementAccessExpression(arrayIdentifier, SyntaxFactory.BracketedArgumentList(CreateSeparatedList(new[] { SyntaxFactory.Argument(SyntaxFactory.IdentifierName("_index")) }))), SyntaxFactory.IdentifierName(param.Identifier.ValueText))); } )); } else { var listIdentifier = SyntaxFactory.IdentifierName("_list"); var listType = SyntaxFactory.ParseTypeName("System.Collections.Generic.List<" + ((ArrayTypeSyntax)returnType).ElementType + ">"); return(RewriteAsLoop( returnType, new[] { CreateLocalVariableDeclaration("_list", SyntaxFactory.ObjectCreationExpression(listType, CreateArguments(Enumerable.Empty <ArgumentSyntax>()), null)) }, new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, listIdentifier, SyntaxFactory.IdentifierName("ToArray")))) }, collection, chain, (inv, arguments, param) => { return CreateStatement(SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, listIdentifier, SyntaxFactory.IdentifierName("Add")), CreateArguments(new[] { SyntaxFactory.IdentifierName(param.Identifier.ValueText) }))); } )); } } #if false if (GetMethodFullName(node) == SumWithSelectorMethod) { string itemArg = null; return(RewriteAsLoop( CreatePrimitiveType(SyntaxKind.IntKeyword), new[] { CreateLocalVariableDeclaration("sum_", SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(0))) }, arguments => { return SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.AddAssignmentExpression, SyntaxFactory.IdentifierName("sum_"), InlineOrCreateMethod((CSharpSyntaxNode)Visit(lambda.Body), arguments, CreateParameter(arg.Identifier, itemType), out itemArg))); }, new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName("sum_")) }, () => itemArg, collection )); } if (GetMethodFullName(node) == SumIntsMethod) { string itemArg = null; return(RewriteAsLoop( CreatePrimitiveType(SyntaxKind.IntKeyword), new[] { CreateLocalVariableDeclaration("sum_", SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(0))) }, arguments => { return SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.AddAssignmentExpression, SyntaxFactory.IdentifierName("sum_"), InlineOrCreateMethod(SyntaxFactory.IdentifierName(ItemName), arguments, CreateParameter(ItemName, itemType), out itemArg))); }, new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName("sum_")) }, () => itemArg, collection )); } #endif return(null); }
protected void GenerateForClass(NodeTypeInfo nodeTypeInfo, SemanticModel semanticModel) { var outputFile = (CodeFileCSharp)this.outputStream.CreateCodeFile($"{ nodeTypeInfo.DeclaredType.Name}.cs"); var unit = SyntaxFactory.CompilationUnit(); unit = unit.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Collections.Generic"))); unit = unit.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Linq"))); var nsContainer = SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(this.Settings.OutputNamespace)); var nodeClass = SyntaxFactory.ClassDeclaration(nodeTypeInfo.DeclaredType.Name); nodeClass = nodeClass.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); if (nodeTypeInfo.DeclaredType.IsAbstract) { nodeClass = nodeClass.AddModifiers(SyntaxFactory.Token(SyntaxKind.AbstractKeyword)); } nodeClass = nodeClass.AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword)); if (!string.IsNullOrEmpty(nodeTypeInfo.BaseTypeString)) { nodeClass = nodeClass .WithBaseList( SyntaxFactory .BaseList( SyntaxFactory.Token(SyntaxKind.ColonToken), SyntaxFactory.SeparatedList( new BaseTypeSyntax[] { SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseTypeName(nodeTypeInfo.BaseTypeString)) }))); } foreach (var member in nodeTypeInfo.Members.Where(m => !m.IsInherited && !m.IsCollection)) { nodeClass = nodeClass.AddMembers( SyntaxFactory.FieldDeclaration( SyntaxFactory.VariableDeclaration( SyntaxFactory.ParseTypeName(member.FullySpecifiedOutputTypeString), SyntaxFactory.SeparatedList(new VariableDeclaratorSyntax[] { SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(member.DestinationFieldName)) })))); } var constructor = SyntaxFactory.ConstructorDeclaration(nodeTypeInfo.DeclaredType.Name); constructor = constructor.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); List<StatementSyntax> statements = new List<StatementSyntax>(); foreach (var member in nodeTypeInfo.Members.Where(m => !m.IsInherited && m.IsCollection)) { ExpressionSyntax right = null; if (member.ItemTypeInheritsFromSourceNodeType) { right = SyntaxFactory.ObjectCreationExpression( SyntaxFactory.ParseTypeName(member.CollectionTypeString), SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new ArgumentSyntax[] { SyntaxFactory.Argument(SyntaxFactory.ThisExpression()) })), null); } else { right = SyntaxFactory.ObjectCreationExpression( SyntaxFactory.ParseTypeName(member.CollectionTypeString), SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList<ArgumentSyntax>()), null); } statements.Add( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(member.OriginalField.Name)), right))); } constructor = constructor.WithBody(SyntaxFactory.Block(statements)); nodeClass = nodeClass.AddMembers(constructor); foreach (var member in nodeTypeInfo.Members.Where(m => !m.IsInherited)) { if (member.IsCollection) { nodeClass = nodeClass.AddMembers( SyntaxFactory .PropertyDeclaration( SyntaxFactory.ParseTypeName(member.CollectionTypeString), member.OriginalField.Name) .WithAccessorList( SyntaxFactory.AccessorList( SyntaxFactory.List<AccessorDeclarationSyntax>(new AccessorDeclarationSyntax[] { SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)), SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) .AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword)) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)) }))) .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))); } else { List<StatementSyntax> setterStatements = new List<StatementSyntax>(); if (member.TypeInheritsFromSourceNodeType) { setterStatements.Add( SyntaxFactory.ExpressionStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName("SetAsParentFor")), SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList(new ArgumentSyntax[] { SyntaxFactory.Argument( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(member.DestinationFieldName))), SyntaxFactory.Argument(SyntaxFactory.IdentifierName("value")) }))))); } else { if (!string.IsNullOrEmpty(this.Settings.AllowedModificationCheckMethodName)) { setterStatements.Add( SyntaxFactory.ExpressionStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(this.Settings.AllowedModificationCheckMethodName)), SyntaxFactory.ArgumentList()))); } } setterStatements.Add( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(member.DestinationFieldName)), SyntaxFactory.IdentifierName("value") ))); nodeClass = nodeClass.AddMembers( SyntaxFactory .PropertyDeclaration( SyntaxFactory.ParseTypeName(member.FullySpecifiedOutputTypeString), member.OriginalField.Name) .WithAccessorList( SyntaxFactory.AccessorList( SyntaxFactory.List<AccessorDeclarationSyntax>(new AccessorDeclarationSyntax[] { SyntaxFactory.AccessorDeclaration( SyntaxKind.GetAccessorDeclaration, SyntaxFactory.Block(new StatementSyntax[] { SyntaxFactory.ReturnStatement( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(member.DestinationFieldName))) })), SyntaxFactory.AccessorDeclaration( SyntaxKind.SetAccessorDeclaration, SyntaxFactory.Block(setterStatements)) }))) .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))); } } if (!nodeTypeInfo.DeclaredType.IsAbstract) { var toLtsModelNodeMethodName = "ToLtsModelNode"; string resultVarName = "result"; List<StatementSyntax> methodStatements = new List<StatementSyntax>(); methodStatements.Add( SyntaxFactory.LocalDeclarationStatement( SyntaxFactory.VariableDeclaration( SyntaxFactory.ParseTypeName("var"), SyntaxFactory.SeparatedList(new VariableDeclaratorSyntax[] { SyntaxFactory.VariableDeclarator( SyntaxFactory.Identifier(resultVarName), null, SyntaxFactory.EqualsValueClause( SyntaxFactory.ObjectCreationExpression( SyntaxFactory.ParseTypeName(nodeTypeInfo.DeclaredType.ToMinimalDisplayString(semanticModel, 0, SymbolDisplayFormat.MinimallyQualifiedFormat)), SyntaxFactory.ArgumentList(), null))) })))); foreach (var member in nodeTypeInfo.Members) { if (member.IsCollection) { if (member.ItemTypeInheritsFromSourceNodeType) { //// Makes an assumption that source collection is List. Should be changed. var lambdaParameterName = "i"; methodStatements.Add( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(resultVarName), SyntaxFactory.IdentifierName(member.OriginalField.Name)), SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(member.OriginalField.Name)), SyntaxFactory.IdentifierName("Select")), SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList( new ArgumentSyntax[] { SyntaxFactory.Argument( SyntaxFactory.ParenthesizedLambdaExpression( SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList<ParameterSyntax>() .Add(SyntaxFactory.Parameter(SyntaxFactory.Identifier(lambdaParameterName)))), SyntaxFactory.CastExpression( SyntaxFactory.ParseTypeName(member.ItemType.ToMinimalDisplayString(semanticModel, 0, SymbolDisplayFormat.MinimallyQualifiedFormat)), SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(lambdaParameterName), SyntaxFactory.IdentifierName(toLtsModelNodeMethodName)))))) }))), SyntaxFactory.IdentifierName("ToList")))))); } else { //// Makes an assumption that collection can be constructed with IEnumerable as an argument to populate it. Not very nice. methodStatements.Add( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(resultVarName), SyntaxFactory.IdentifierName(member.OriginalField.Name)), SyntaxFactory.ObjectCreationExpression( SyntaxFactory.ParseTypeName(member.OriginalField.Type.ToMinimalDisplayString(semanticModel, 0, SymbolDisplayFormat.MinimallyQualifiedFormat)), SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList(new ArgumentSyntax[] { SyntaxFactory.Argument( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(member.OriginalField.Name))) })), null)))); } } else { if (member.TypeInheritsFromSourceNodeType) { methodStatements.Add( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(resultVarName), SyntaxFactory.IdentifierName(member.OriginalField.Name)), SyntaxFactory.CastExpression( SyntaxFactory.ParseTypeName(member.OriginalField.Type.ToMinimalDisplayString(semanticModel, 0, SymbolDisplayFormat.MinimallyQualifiedFormat)), SyntaxFactory.InvocationExpression( SyntaxFactory.ConditionalAccessExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(member.OriginalField.Name)), SyntaxFactory.MemberBindingExpression( SyntaxFactory.IdentifierName(toLtsModelNodeMethodName)) )))))); } else { methodStatements.Add( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(resultVarName), SyntaxFactory.IdentifierName(member.OriginalField.Name)), SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(member.OriginalField.Name))))); } } } methodStatements.Add(SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(resultVarName))); ////initializerExpressions = initializerExpressions.Select(e => e.WithLeadingTrivia(SyntaxFactory.Whitespace("\n"))).ToList(); nodeClass = nodeClass.AddMembers( SyntaxFactory.MethodDeclaration( SyntaxFactory.ParseTypeName(this.Settings.SourceNodeBaseType), toLtsModelNodeMethodName) .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.OverrideKeyword)) .WithBody(SyntaxFactory.Block(methodStatements)) ); } nsContainer = nsContainer.AddMembers(nodeClass); unit = unit.AddMembers(nsContainer); outputFile.SyntaxTree = unit.SyntaxTree; }
protected override IEnumerable <CodeAction> GetActions(Document document, SemanticModel semanticModel, SyntaxNode root, TextSpan span, VariableDeclaratorSyntax node, CancellationToken cancellationToken) { var declaration = node.Parent as VariableDeclarationSyntax; if (declaration == null || node.Initializer == null || (!node.Identifier.Span.Contains(span) && !node.Initializer.EqualsToken.Span.Contains(span) && node.Initializer.Value.SpanStart != span.Start)) { yield break; } var variableDecl = declaration.Parent as LocalDeclarationStatementSyntax; var forStmt = declaration.Parent as ForStatementSyntax; if (forStmt != null) { } else { if (variableDecl == null || variableDecl.Modifiers.Any(m => m.IsKind(SyntaxKind.ConstKeyword))) { yield break; } var block = variableDecl.Parent as BlockSyntax; if (block == null) { yield break; } } yield return (CodeActionFactory.Create( span, DiagnosticSeverity.Info, GettextCatalog.GetString("Split declaration and assignment"), t2 => { SyntaxNode newRoot; if (forStmt != null) { var newDeclaration = SyntaxFactory.VariableDeclaration( SyntaxFactory.ParseTypeName(""), SyntaxFactory.SeparatedList(new[] { node })) .WithAdditionalAnnotations(Formatter.Annotation); newRoot = root.ReplaceNode(forStmt, new SyntaxNode[] { SyntaxFactory.LocalDeclarationStatement( SyntaxFactory.VariableDeclaration( declaration.Type, SyntaxFactory.SeparatedList(new [] { SyntaxFactory.VariableDeclarator(node.Identifier) }) ).WithLeadingTrivia(forStmt.GetLeadingTrivia().Where(t => !t.IsKind(SyntaxKind.WhitespaceTrivia))) .WithAdditionalAnnotations(Formatter.Annotation) ).WithAdditionalAnnotations(Formatter.Annotation), forStmt.WithDeclaration(newDeclaration) .WithLeadingTrivia(forStmt.GetLeadingTrivia().Where(t => t.IsKind(SyntaxKind.WhitespaceTrivia))) }); } else { TypeSyntax newDeclarationType = declaration.Type; if (declaration.Type.ToString() == "var") { var type = semanticModel.GetTypeInfo(declaration.Type).Type; newDeclarationType = SyntaxFactory.ParseTypeName(type.ToMinimalDisplayString(semanticModel, declaration.SpanStart)) .WithLeadingTrivia(declaration.Type.GetLeadingTrivia()) .WithTrailingTrivia(declaration.Type.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); } var newDeclaration = declaration.WithType(newDeclarationType).WithVariables(SyntaxFactory.SeparatedList(declaration.Variables.Select(v => SyntaxFactory.VariableDeclarator(v.Identifier).WithAdditionalAnnotations(Formatter.Annotation)))); newRoot = root.ReplaceNode(variableDecl, new SyntaxNode[] { variableDecl.WithDeclaration(newDeclaration), SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(node.Identifier), node.Initializer.Value ) ).WithAdditionalAnnotations(Formatter.Annotation) }); } //Console.WriteLine (newRoot); return Task.FromResult(document.WithSyntaxRoot(newRoot)); } )); }
public static CompilationUnitSyntax BuildPayloadClassSyntax <TPayloadBaseType>(string className, int code) { return(SyntaxFactory.CompilationUnit() .WithUsings ( SyntaxFactory.List <UsingDirectiveSyntax> ( new UsingDirectiveSyntax[] { SyntaxFactory.UsingDirective ( SyntaxFactory.IdentifierName(nameof(FreecraftCore)) ), SyntaxFactory.UsingDirective ( SyntaxFactory.QualifiedName ( SyntaxFactory.IdentifierName(nameof(FreecraftCore)), SyntaxFactory.IdentifierName(nameof(FreecraftCore.Serializer)) ) ), SyntaxFactory.UsingDirective ( SyntaxFactory.QualifiedName ( SyntaxFactory.IdentifierName(nameof(Booma)), SyntaxFactory.IdentifierName(nameof(Booma.Proxy)) ) ) } ) ) .WithMembers ( SyntaxFactory.SingletonList <MemberDeclarationSyntax> ( SyntaxFactory.ClassDeclaration(className) .WithAttributeLists ( SyntaxFactory.List <AttributeListSyntax> ( new AttributeListSyntax[] { SyntaxFactory.AttributeList ( SyntaxFactory.SingletonSeparatedList <AttributeSyntax> ( SyntaxFactory.Attribute ( SyntaxFactory.IdentifierName(nameof(WireDataContractBaseLinkAttribute)) ) .WithArgumentList ( SyntaxFactory.AttributeArgumentList ( SyntaxFactory.SeparatedList <AttributeArgumentSyntax> ( new SyntaxNodeOrToken[] { SyntaxFactory.AttributeArgument ( SyntaxFactory.LiteralExpression ( SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(code) ) ), SyntaxFactory.Token(SyntaxKind.CommaToken), SyntaxFactory.AttributeArgument ( SyntaxFactory.TypeOfExpression ( SyntaxFactory.IdentifierName(typeof(TPayloadBaseType).Name) ) ) } ) ) ) ) ), SyntaxFactory.AttributeList ( SyntaxFactory.SingletonSeparatedList <AttributeSyntax> ( SyntaxFactory.Attribute ( SyntaxFactory.IdentifierName(nameof(WireDataContractAttribute)) ) ) ) } ) ) .WithModifiers ( SyntaxFactory.TokenList ( new[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.SealedKeyword) } ) ) .WithBaseList ( SyntaxFactory.BaseList ( SyntaxFactory.SeparatedList <BaseTypeSyntax> ( new SyntaxNodeOrToken[] { SyntaxFactory.SimpleBaseType ( SyntaxFactory.IdentifierName(typeof(TPayloadBaseType).Name) ), SyntaxFactory.Token(SyntaxKind.CommaToken), SyntaxFactory.SimpleBaseType ( SyntaxFactory.IdentifierName(nameof(IUnknownPayloadType)) ) } ) ) ) .WithMembers ( SyntaxFactory.List <MemberDeclarationSyntax> ( new MemberDeclarationSyntax[] { SyntaxFactory.PropertyDeclaration ( SyntaxFactory.PredefinedType ( SyntaxFactory.Token(SyntaxKind.BoolKeyword) ), SyntaxFactory.Identifier(nameof(PSOBBGamePacketPayloadClient.isFlagsSerialized)) ) .WithModifiers ( SyntaxFactory.TokenList ( new [] { SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.OverrideKeyword) } ) ) .WithAccessorList ( SyntaxFactory.AccessorList ( SyntaxFactory.SingletonList <AccessorDeclarationSyntax> ( SyntaxFactory.AccessorDeclaration ( SyntaxKind.GetAccessorDeclaration ) .WithSemicolonToken ( SyntaxFactory.Token(SyntaxKind.SemicolonToken) ) ) ) ) .WithInitializer ( SyntaxFactory.EqualsValueClause ( SyntaxFactory.LiteralExpression ( SyntaxKind.FalseLiteralExpression ) ) ) .WithSemicolonToken ( SyntaxFactory.Token(SyntaxKind.SemicolonToken) ), SyntaxFactory.FieldDeclaration ( SyntaxFactory.VariableDeclaration ( SyntaxFactory.ArrayType ( SyntaxFactory.PredefinedType ( SyntaxFactory.Token(SyntaxKind.ByteKeyword) ) ) .WithRankSpecifiers ( SyntaxFactory.SingletonList <ArrayRankSpecifierSyntax> ( SyntaxFactory.ArrayRankSpecifier ( SyntaxFactory.SingletonSeparatedList <ExpressionSyntax> ( SyntaxFactory.OmittedArraySizeExpression() ) ) ) ) ) .WithVariables ( SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax> ( SyntaxFactory.VariableDeclarator ( SyntaxFactory.Identifier($"_{nameof(IUnknownPayloadType.UnknownBytes)}") ) ) ) ) .WithAttributeLists ( SyntaxFactory.List <AttributeListSyntax> ( new AttributeListSyntax[] { SyntaxFactory.AttributeList ( SyntaxFactory.SingletonSeparatedList <AttributeSyntax> ( SyntaxFactory.Attribute ( SyntaxFactory.IdentifierName(nameof(ReadToEndAttribute)) ) ) ), SyntaxFactory.AttributeList ( SyntaxFactory.SingletonSeparatedList <AttributeSyntax> ( SyntaxFactory.Attribute ( SyntaxFactory.IdentifierName(nameof(WireMemberAttribute)) ) .WithArgumentList ( SyntaxFactory.AttributeArgumentList ( SyntaxFactory.SingletonSeparatedList <AttributeArgumentSyntax> ( SyntaxFactory.AttributeArgument ( SyntaxFactory.LiteralExpression ( SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1) ) ) ) ) ) ) ) } ) ) .WithModifiers ( SyntaxFactory.TokenList ( SyntaxFactory.Token(SyntaxKind.PrivateKeyword) ) ), SyntaxFactory.PropertyDeclaration ( SyntaxFactory.ArrayType ( SyntaxFactory.PredefinedType ( SyntaxFactory.Token(SyntaxKind.ByteKeyword) ) ) .WithRankSpecifiers ( SyntaxFactory.SingletonList <ArrayRankSpecifierSyntax> ( SyntaxFactory.ArrayRankSpecifier ( SyntaxFactory.SingletonSeparatedList <ExpressionSyntax> ( SyntaxFactory.OmittedArraySizeExpression() ) ) ) ), SyntaxFactory.Identifier(nameof(IUnknownPayloadType.UnknownBytes)) ) .WithModifiers ( SyntaxFactory.TokenList ( SyntaxFactory.Token(SyntaxKind.PublicKeyword) ) ) .WithAccessorList ( SyntaxFactory.AccessorList ( SyntaxFactory.List <AccessorDeclarationSyntax> ( new AccessorDeclarationSyntax[] { SyntaxFactory.AccessorDeclaration ( SyntaxKind.GetAccessorDeclaration ) .WithBody ( SyntaxFactory.Block ( SyntaxFactory.SingletonList <StatementSyntax> ( SyntaxFactory.ReturnStatement ( SyntaxFactory.IdentifierName($"_{nameof(IUnknownPayloadType.UnknownBytes)}") ) ) ) ), SyntaxFactory.AccessorDeclaration ( SyntaxKind.SetAccessorDeclaration ) .WithBody ( SyntaxFactory.Block ( SyntaxFactory.SingletonList <StatementSyntax> ( SyntaxFactory.ExpressionStatement ( SyntaxFactory.AssignmentExpression ( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName($"_{nameof(IUnknownPayloadType.UnknownBytes)}"), SyntaxFactory.IdentifierName("value") ) ) ) ) ) } ) ) ), SyntaxFactory.ConstructorDeclaration ( SyntaxFactory.Identifier(className) ) .WithModifiers ( SyntaxFactory.TokenList ( SyntaxFactory.Token(SyntaxKind.PublicKeyword) ) ) .WithBody ( SyntaxFactory.Block() ) } ) ) ) ) .NormalizeWhitespace()); }
/// <summary> /// Ajoute une initialisation du champ via un nouveau paramètre du constructeur. /// </summary> /// <param name="document">Le document.</param> /// <param name="champ">Le champ.</param> /// <param name="jetonAnnulation">Le jeton d'annulation.</param> /// <returns>Le document mis à jour.</returns> private async Task <Document> InjecterComposant(Document document, VariableDeclaratorSyntax champ, CancellationToken jetonAnnulation) { // On récupère la racine et le modèle sémantique. var racine = await document .GetSyntaxRootAsync(jetonAnnulation) .ConfigureAwait(false); var modèleSémantique = await document.GetSemanticModelAsync(jetonAnnulation); // On récupère le constructeur de la classe, s'il existe. var constructeur = racine.DescendantNodes().OfType <ConstructorDeclarationSyntax>().FirstOrDefault(); if (constructeur == null) { return(document); } // On construit le nom du paramètre en enlevant la première lettre du champ (qui doit être un _). var paramètre = SyntaxFactory.Identifier(champ.Identifier.ToString().Substring(1)); // On construit le texte de documentation en fonction du type de paramètre. var type = (champ.Parent as VariableDeclarationSyntax).Type; var texte = type is PredefinedTypeSyntax ? "Valeur injectée." : type.ToString().StartsWith("IService", System.StringComparison.Ordinal) ? "Service injecté." : type.ToString().StartsWith("IDal", System.StringComparison.Ordinal) ? "DAL injectée." : "Composant injecté."; // On met à jour le constructeur. var nouveauConstructeur = constructeur // En ajoutant le paramètre. .WithParameterList( constructeur.ParameterList.AddParameters( SyntaxFactory.Parameter( SyntaxFactory.List <AttributeListSyntax>(), SyntaxFactory.TokenList(), type, paramètre, null))) // En ajoutant la déclaration. .WithBody( constructeur.Body.AddStatements( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(champ.Identifier), SyntaxFactory.IdentifierName(paramètre))))) // Et la documentation du nouveau paramètre (ouais, tout ça, et encore je crois pas que ça soit bien correct). .WithLeadingTrivia( constructeur.GetLeadingTrivia() .Select(i => { var doc = i.GetStructure() as DocumentationCommentTriviaSyntax; if (doc == null) { return(i); } return(SyntaxFactory.Trivia( doc.AddContent( SyntaxFactory.XmlText( SyntaxFactory.TokenList( SyntaxFactory.XmlTextLiteral( SyntaxFactory.TriviaList( SyntaxFactory.DocumentationCommentExterior("/// ")), string.Empty, string.Empty, SyntaxFactory.TriviaList()))), SyntaxFactory.XmlElement( SyntaxFactory.XmlElementStartTag( SyntaxFactory.XmlName("param "), SyntaxFactory.List( new List <XmlAttributeSyntax> { SyntaxFactory.XmlNameAttribute( SyntaxFactory.XmlName("name"), SyntaxFactory.Token(SyntaxKind.DoubleQuoteToken), SyntaxFactory.IdentifierName(paramètre.ToString()), SyntaxFactory.Token(SyntaxKind.DoubleQuoteToken)) })), SyntaxFactory.List( new List <XmlNodeSyntax> { SyntaxFactory.XmlText( SyntaxFactory.TokenList( SyntaxFactory.XmlTextLiteral( SyntaxFactory.TriviaList(), texte, string.Empty, SyntaxFactory.TriviaList()))) }), SyntaxFactory.XmlElementEndTag(SyntaxFactory.XmlName("param"))), SyntaxFactory.XmlText( SyntaxFactory.TokenList( SyntaxFactory.XmlTextNewLine( SyntaxFactory.TriviaList(), "\r\n", string.Empty, SyntaxFactory.TriviaList())))))); })); // Met à jour la racine, en reformattant le document. var nouvelleRacine = Formatter.Format( racine.ReplaceNode(constructeur, nouveauConstructeur), document.Project.Solution.Workspace); return(document.WithSyntaxRoot(nouvelleRacine)); }
private static List <ExpressionStatementSyntax> CreateAssignmentStatement(IEnumerable <Assignment> additionalConstructorAssignments) { return(additionalConstructorAssignments.Select(assignment => SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression( assignment.AssignmentKind, assignment.Field, assignment.Initializer)) ).ToList()); }
public string Generate(Interface interf) { var importDeclarations = ImportNamespaceDeclarations(); var namespaceDeclarations = new List <SyntaxNode>(); foreach (var typedef in interf.Typedefs) { if (typedef.Kind == TypeKind.Struct) { AddClassType(namespaceDeclarations, interf, typedef); } else if (typedef.Kind == TypeKind.Enum) { AddEnumType(namespaceDeclarations, interf, typedef); } else { throw new NotSupportedException(); } } List <MemberDeclarationSyntax> classDeclarations = new List <MemberDeclarationSyntax>(); // InterfaceName var interfaceAddressField = SyntaxFactory.FieldDeclaration( SyntaxFactory.VariableDeclaration( SyntaxFactory.PredefinedType( SyntaxFactory.Token(SyntaxKind.StringKeyword))) .WithVariables( SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>( SyntaxFactory.VariableDeclarator( SyntaxFactory.Identifier("InterfaceName")) .WithInitializer( SyntaxFactory.EqualsValueClause( SyntaxFactory.LiteralExpression( SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(interf.Name))))))) .WithModifiers( SyntaxFactory.TokenList( new [] { SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.ConstKeyword) })); classDeclarations.Add(interfaceAddressField); string[] splitName = interf.Name.Split('.').Select(name => $"{char.ToUpper(name[0])}{name.Substring(1)}").ToArray(); string className = splitName[splitName.Length - 1]; string namespaceName = string.Join('.', splitName.Take(splitName.Length - 1)); // _conn field var connField = SyntaxFactory.FieldDeclaration( SyntaxFactory.VariableDeclaration( SyntaxFactory.IdentifierName("IConnection")) .WithVariables( SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>( SyntaxFactory.VariableDeclarator( SyntaxFactory.Identifier("_conn"))))) .WithModifiers( SyntaxFactory.TokenList( new [] { SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword) })); classDeclarations.Add(connField); // ctor var constructor = SyntaxFactory.ConstructorDeclaration( SyntaxFactory.Identifier(className)) .WithModifiers( SyntaxFactory.TokenList( SyntaxFactory.Token(SyntaxKind.PublicKeyword))) .WithParameterList( SyntaxFactory.ParameterList( SyntaxFactory.SingletonSeparatedList <ParameterSyntax>( SyntaxFactory.Parameter( SyntaxFactory.Identifier("address")) .WithType( SyntaxFactory.PredefinedType( SyntaxFactory.Token(SyntaxKind.StringKeyword)))))) .WithBody( SyntaxFactory.Block( SyntaxFactory.SingletonList <StatementSyntax>( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("_conn"), SyntaxFactory.ObjectCreationExpression( SyntaxFactory.IdentifierName("Connection")) .WithArgumentList( SyntaxFactory.ArgumentList( SyntaxFactory.SingletonSeparatedList <ArgumentSyntax>( SyntaxFactory.Argument( SyntaxFactory.IdentifierName("address")))))))))); classDeclarations.Add(constructor); foreach (var method in interf.Methods) { string methodBody = "return _conn.CallAsync"; TypeSyntax returnType; if (method.ReturnType.Members.Count > 0) { method.ReturnType.Name = $"{method.Name}Result"; AddClassType(namespaceDeclarations, interf, method.ReturnType); returnType = SyntaxFactory.ParseTypeName($"Task<{method.ReturnType.Name}>"); methodBody += $"<{method.ReturnType.Name}>"; } else { returnType = SyntaxFactory.ParseTypeName("System.Threading.Task"); } methodBody += $"(\"{interf.Name}.{method.Name}\", GetErrorParametersType"; SeparatedSyntaxList <ParameterSyntax> parameters = new SeparatedSyntaxList <ParameterSyntax>(); if (method.ParameterType.Members.Count > 0) { method.ParameterType.Name = $"{method.Name}Args"; AddClassType(namespaceDeclarations, interf, method.ParameterType); parameters = parameters.Add(SyntaxFactory.Parameter(SyntaxFactory.Identifier("args")).WithType(SyntaxFactory.ParseTypeName(method.ParameterType.Name))); methodBody += ", args);"; } else { methodBody += ");"; } MethodDeclarationSyntax newMethod = SyntaxFactory.MethodDeclaration( SyntaxFactory.List <AttributeListSyntax>(), SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword)), returnType, null, SyntaxFactory.Identifier($"{method.Name}Async"), null, SyntaxFactory.ParameterList(parameters), SyntaxFactory.List <TypeParameterConstraintClauseSyntax>(), SyntaxFactory.Block(SyntaxFactory.ParseStatement(methodBody)), SyntaxFactory.Token(SyntaxKind.SemicolonToken) ); classDeclarations.Add(newMethod); } // GetErrorParametersType var getErrorParametersTypeMethod = SyntaxFactory.MethodDeclaration( SyntaxFactory.QualifiedName( SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Type")), SyntaxFactory.Identifier("GetErrorParametersType")) .WithModifiers( SyntaxFactory.TokenList( new [] { SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword) })) .WithParameterList( SyntaxFactory.ParameterList( SyntaxFactory.SingletonSeparatedList <ParameterSyntax>( SyntaxFactory.Parameter( SyntaxFactory.Identifier("args")) .WithType( SyntaxFactory.PredefinedType( SyntaxFactory.Token(SyntaxKind.StringKeyword)))))) // TODO: generate body .WithBody( SyntaxFactory.Block( SyntaxFactory.SingletonList <StatementSyntax>( SyntaxFactory.ReturnStatement( SyntaxFactory.LiteralExpression( SyntaxKind.NullLiteralExpression))))); classDeclarations.Add(getErrorParametersTypeMethod); // TODO: generate error name const string members // dispose method var disposeMethod = SyntaxFactory.MethodDeclaration( SyntaxFactory.PredefinedType( SyntaxFactory.Token(SyntaxKind.VoidKeyword)), SyntaxFactory.Identifier("Dispose")) .WithModifiers( SyntaxFactory.TokenList( SyntaxFactory.Token(SyntaxKind.PublicKeyword))) .WithBody( SyntaxFactory.Block( SyntaxFactory.SingletonList <StatementSyntax>( SyntaxFactory.ExpressionStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("_conn"), SyntaxFactory.IdentifierName("Dispose"))))))); classDeclarations.Add(disposeMethod); namespaceDeclarations.Add( SyntaxFactory.ClassDeclaration(className) .WithBaseList( SyntaxFactory.BaseList( SyntaxFactory.SingletonSeparatedList <BaseTypeSyntax>( SyntaxFactory.SimpleBaseType( SyntaxFactory.IdentifierName("IDisposable"))))) .WithMembers( SyntaxFactory.List <MemberDeclarationSyntax>(classDeclarations)) ); var namespaceDeclaration = _generator.NamespaceDeclaration(_generator.DottedName(namespaceName), namespaceDeclarations); var compilationUnit = _generator.CompilationUnit(importDeclarations.Concat(new[] { namespaceDeclaration })); return(compilationUnit.NormalizeWhitespace().ToFullString()); }