From d2d4d93f66e8e813fd90c29d78af68c2f657ddef Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Wed, 4 Feb 2026 05:37:11 +0000 Subject: [PATCH] Initial upload: ScaffoldForge CLI tool with full codebase, tests, and CI/CD --- scaffoldforge/generators/code.py | 222 +++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 scaffoldforge/generators/code.py diff --git a/scaffoldforge/generators/code.py b/scaffoldforge/generators/code.py new file mode 100644 index 0000000..d3c7336 --- /dev/null +++ b/scaffoldforge/generators/code.py @@ -0,0 +1,222 @@ +"""Code generation functionality.""" + +from typing import Any, Dict, List + +from scaffoldforge.parsers import IssueData +from scaffoldforge.templates import TemplateEngine +from scaffoldforge.generators.models import FileSpec + + +class CodeGenerator: + """Generator for file content using templates.""" + + DEFAULT_FILES = { + "python": ["main.py", "utils.py", "models.py", "cli.py"], + "javascript": ["index.js", "utils.js"], + "go": ["main.go", "utils.go"], + "rust": ["main.rs", "lib.rs"], + } + + CONFIG_FILES = { + "python": ["pyproject.toml", "requirements.txt"], + "javascript": ["package.json", ".eslintrc.json"], + "go": ["go.mod"], + "rust": ["Cargo.toml"], + } + + def __init__(self, template_engine: TemplateEngine, issue_data: IssueData): + """Initialize the code generator. + + Args: + template_engine: TemplateEngine instance. + issue_data: Parsed issue data. + """ + self.template_engine = template_engine + self.issue_data = issue_data + + def generate_all_files( + self, language: str, issue_data: IssueData + ) -> List[FileSpec]: + """Generate all project files. + + Args: + language: Programming language. + issue_data: Parsed issue data. + + Returns: + List of FileSpec objects. + """ + files = [] + context = self.template_engine.get_template_context(issue_data) + + files.extend(self._generate_source_files(language, context)) + files.extend(self._generate_config_files(language, context)) + + return files + + def _generate_source_files( + self, language: str, context: Dict[str, Any] + ) -> List[FileSpec]: + """Generate source code files. + + Args: + language: Programming language. + context: Template context. + + Returns: + List of FileSpec objects. + """ + files = [] + source_templates = self.DEFAULT_FILES.get(language, []) + + for template_name in source_templates: + try: + content = self.template_engine.render( + template_name, context, language + ) + extension = self._get_extension(language) + filename = f"{template_name}{extension}" if not template_name.endswith(extension) else template_name + path = self._get_source_path(template_name, language) + files.append(FileSpec(path=path, content=content)) + except ValueError: + files.append(self._create_empty_file(template_name, language, context)) + + return files + + def _generate_config_files( + self, language: str, context: Dict[str, Any] + ) -> List[FileSpec]: + """Generate configuration files. + + Args: + language: Programming language. + context: Template context. + + Returns: + List of FileSpec objects. + """ + files = [] + config_templates = self.CONFIG_FILES.get(language, []) + + for config_name in config_templates: + try: + content = self.template_engine.render( + config_name, context, language + ) + files.append(FileSpec(path=config_name, content=content)) + except ValueError: + pass + + return files + + def _create_empty_file( + self, template_name: str, language: str, context: Dict[str, Any] + ) -> FileSpec: + """Create an empty file with TODO comments. + + Args: + template_name: Name of the template. + language: Programming language. + context: Template context. + + Returns: + FileSpec object. + """ + extension = self._get_extension(language) + filename = f"{template_name}{extension}" + path = self._get_source_path(template_name, language) + + todo_items = self.issue_data.get_todo_items() + + content = self._generate_todo_content( + language, template_name, todo_items + ) + + return FileSpec(path=path, content=content) + + def _generate_todo_content( + self, language: str, template_name: str, todo_items: List[str] + ) -> str: + """Generate TODO comments for a file. + + Args: + language: Programming language. + template_name: Name of the template. + todo_items: List of TODO items. + + Returns: + TODO comment content. + """ + todo_header = f"# TODO Items from GitHub Issue #{self.issue_data.number}" + lines = [todo_header] + + for item in todo_items[:5]: + lines.append(f"# TODO: {item}") + + if language == "python": + return f'"""{template_name} - {self.issue_data.title}"""\n\n' + "\n".join( + lines + ) + elif language in ("javascript",): + return f"/**\n * {template_name}\n */\n\n" + "\n".join(lines) + elif language == "go": + return f"// {template_name}\n\n" + "\n".join(lines) + elif language == "rust": + return f"// {template_name}\n\n" + "\n".join(lines) + else: + return "\n".join(lines) + + def _get_extension(self, language: str) -> str: + """Get file extension for language. + + Args: + language: Programming language. + + Returns: + File extension with dot. + """ + extensions = { + "python": ".py", + "javascript": ".js", + "go": ".go", + "rust": ".rs", + } + return extensions.get(language, ".txt") + + def _get_source_path(self, template_name: str, language: str) -> str: + """Get the path for a source file. + + Args: + template_name: Name of the template. + language: Programming language. + + Returns: + File path. + """ + src_templates = {"models", "utils", "handlers", "lib"} + if template_name.lower() in src_templates: + return f"src/{template_name}{self._get_extension(language)}" + return f"{template_name}{self._get_extension(language)}" + + def generate_single_file( + self, filename: str, language: str, extra_context: Dict[str, Any] = None + ) -> str: + """Generate content for a single file. + + Args: + filename: Name of the file. + language: Programming language. + extra_context: Additional template context. + + Returns: + Generated file content. + """ + context = self.template_engine.get_template_context(self.issue_data) + if extra_context: + context.update(extra_context) + + try: + return self.template_engine.render(filename, context, language) + except ValueError: + empty_file = self._create_empty_file(filename, language, {}) + return empty_file.content