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