Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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));
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
        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));
            }
                     ));
        }
Ejemplo n.º 10
0
 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());
 }
Ejemplo n.º 11
0
        /// <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());
 }
Ejemplo n.º 13
0
        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());
        }