private string GenerateAll()
        {
            var allCode       = new CodeBuilder();
            var classInfo     = _classInfo;
            var classSyntax   = _classInfo.ContainingClassSyntax;
            var namespaceName = classInfo.ContainingClassSymbol.ContainingNamespace.ToDisplayString();

            var methodGens    = _methodInfos.Select(mi => new CalculatorMethodGenerator(_context, classInfo, mi)).ToList();
            var targetMethods = new TargetMethodsInfo(_methodInfos);

            // copy all the usings from the original file
            var root = (CompilationUnitSyntax)classSyntax.SyntaxTree.GetRoot();

            allCode.AddHeaderLine(root.Usings.ToFullString());
            allCode.AddHeaderLine();

            // namespace
            allCode.AddBlockHeader($"namespace {namespaceName}");

            // class declaration
            var classModifiersString = classSyntax.Modifiers.ToFullString();

            if (!classModifiersString.Contains("partial"))
            {
                _context.ReportUnsupportedSyntaxError(classSyntax, $"Target class '{_classInfo.ContainingClassSymbol.Name}' for '{classInfo.RecursionId}' is not partial");
                return(null);
            }

            allCode.AddBlockHeader($"{classModifiersString} class {_classInfo.ContainingClassSymbol.Name}");

            allCode.AddHeaderLine();
            allCode.AddHeaderLine(GenerateProxyMethods(methodGens));

            allCode.AddHeaderLine();
            allCode.AddHeaderLine(GenerateParamsStructs(classInfo, methodGens));

            allCode.AddHeaderLine();
            allCode.AddHeaderLine(GenerateCalculatorClass(classInfo, methodGens, targetMethods));

            return(allCode.BuildString());
        }
Exemple #2
0
        private bool AddInvocation(InvocationExpressionSyntax inv)
        {
            var parent = inv.Parent;

            if (parent == null)
            {
                _context.ReportUnsupportedSyntaxError(inv, $"Unexpected location (no parent) for recursive invocation '{inv.ToFullStringTrimmed()}'");
                return(false);
            }

            switch (parent.Kind())
            {
            case SyntaxKind.ExpressionStatement:
            {
                // In a case of a call of a void method or a call such that return value is ignored
                // the next parent seems to not matter at all.
                var exprSyntax = (ExpressionStatementSyntax)parent;
                _nodesToReplace.VoidCalls.Add((inv, exprSyntax));
                return(true);
            }

            case SyntaxKind.SimpleAssignmentExpression:
            {
                var assignment = (AssignmentExpressionSyntax)parent;
                // _context.Log(assignment.GetLocation(), "" + assignment.Left.Kind());
                // _context.Log(assignment.GetLocation(), "" + assignment.Left.GetType().FullName);
                // _context.Log(assignment.GetLocation(), assignment.ToFullStringTrimmed());
                // _context.Log(assignment.GetLocation(), "" + assignment.Parent.Kind());
                // _context.Log(assignment.GetLocation(), "" + assignment.Parent.ToFullStringTrimmed());
                // _context.Log(assignment.GetLocation(), "" + assignment.Parent.Parent.Kind());
                var assignmentParent = assignment.Parent;
                if (assignmentParent.Kind() != SyntaxKind.ExpressionStatement)
                {
                    _context.ReportUnsupportedSyntaxError(assignmentParent,
                                                          $"Unsupported parent for recursive invocation {assignmentParent.Kind()}: '{assignmentParent.ToFullStringTrimmed()}'");
                    return(false);
                }

                var containingStatement = (ExpressionStatementSyntax)assignmentParent;
                var expressionParent    = containingStatement.Parent;
                // TODO: potentially we can introduce a block ourselves here
                if (expressionParent.Kind() != SyntaxKind.Block)
                {
                    _context.ReportUnsupportedSyntaxError(expressionParent,
                                                          $"Recursive invocation should be in a block {expressionParent.Kind()}: '{expressionParent.ToFullStringTrimmed()}'");
                    return(false);
                }

                var block = (BlockSyntax)expressionParent;
                _nodesToReplace.Assignments.Add((assignment, containingStatement, block));
                return(true);
            }

            case SyntaxKind.EqualsValueClause:
            {
                var equalsValueSyntax = (EqualsValueClauseSyntax)parent;
                var varDeclarator     = (VariableDeclaratorSyntax)equalsValueSyntax.Parent;
                var varDeclaration    = (VariableDeclarationSyntax)varDeclarator.Parent;
                // TODO: support other cases such as for, foreach,...
                // the containingStatement is expected to be something like LocalDeclarationStatementSyntax
                // var containingStatement = (StatementSyntax) varDeclaration.Parent;
                var containingStatement = varDeclaration.Parent;
                if (containingStatement.Kind() != SyntaxKind.LocalDeclarationStatement)
                {
                    _context.ReportUnsupportedSyntaxError(containingStatement,
                                                          $"Unsupported location for recursive invocation {containingStatement.Kind()}: '{inv.ToFullStringTrimmed()}'");
                    return(false);
                }

                var localDeclStatement       = (LocalDeclarationStatementSyntax)containingStatement;
                var containingBlockCandidate = localDeclStatement.Parent;
                if (containingBlockCandidate.Kind() != SyntaxKind.Block)
                {
                    _context.ReportUnsupportedSyntaxError(containingBlockCandidate,
                                                          $"Unsupported location for recursive invocation {containingBlockCandidate.Kind()}: '{inv.ToFullStringTrimmed()}'");
                    return(false);
                }

                var containingBlock = containingBlockCandidate;
                _nodesToReplace.DeclarationAndAssignments.Add((varDeclarator, localDeclStatement, containingBlock));
                return(true);
            }

            case SyntaxKind.ReturnStatement:
            {
                var returnStatement = (ReturnStatementSyntax)parent;
                _nodesToReplace.ReturnsRecursive.Add(returnStatement);
                return(true);
            }

            default:
                _context.ReportUnsupportedSyntaxError(inv, $"Unsupported location for recursive invocation {parent.Kind()}: '{parent.ToFullStringTrimmed()}'");
                return(false);
            }
        }