CoolFace
Apppublic

sanket3280/code-execution

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
codeFormatter.service.js346 linesDownload Raw Back to services
1/**2 * Code Formatter Service3 * Provides language-specific code formatting using industry-standard formatters4 */5 6const { exec } = require('child_process');7const { promisify } = require('util');8const execAsync = promisify(exec);9const fs = require('fs').promises;10const fsSync = require('fs');11const path = require('path');12const os = require('os');13 14class CodeFormatterService {15  /**16   * Format code based on language17   * @param {string} code - Raw code to format18   * @param {string} language - Programming language19   * @returns {Promise<string>} - Formatted code20   */21  async formatCode(code, language) {22    try {23      switch (language.toLowerCase()) {24        case 'javascript':25        case 'typescript':26          return await this.formatJavaScript(code);27        28        case 'python':29          return await this.formatPython(code);30        31        case 'java':32          return await this.formatJava(code);33        34        case 'cpp':35        case 'c':36          return await this.formatCpp(code);37        38        case 'csharp':39          return await this.formatCSharp(code);40        41        default:42          // Return original code if formatter not available43          return code;44      }45    } catch (error) {46      console.error(`Formatting error for ${language}:`, error.message);47      // Return original code on error48      return code;49    }50  }51 52  /**53   * Format JavaScript/TypeScript using Prettier (LeetCode Style - 4 spaces)54   */55  async formatJavaScript(code) {56    try {57      const prettier = require('prettier');58      59      // LeetCode-style JavaScript formatting with 4 spaces60      const formatted = await prettier.format(code, {61        parser: 'babel',62        tabWidth: 4,63        useTabs: false,64        semi: true,65        singleQuote: true,66        bracketSpacing: true,67        arrowParens: 'always',68        printWidth: 80,69        endOfLine: 'lf',70      });71      72      return formatted;73    } catch (error) {74      console.error('Prettier formatting error:', error.message);75      // Fallback to basic formatting76      return this.basicFormat(code);77    }78  }79 80  /**81   * Format Python using Black (via CLI) - ASYNC82   */83  async formatPython(code) {84    try {85      // Create temp file86      const tempFile = path.join(os.tmpdir(), `temp_${Date.now()}.py`);87      await fs.writeFile(tempFile, code, 'utf8');88      89      // Run black formatter (async, non-blocking)90      await execAsync(`black -q "${tempFile}"`, { 91        timeout: 500092      });93      94      // Read formatted code95      const formatted = await fs.readFile(tempFile, 'utf8');96      97      // Cleanup98      await fs.unlink(tempFile).catch(() => {});99      100      return formatted;101    } catch (error) {102      console.error('Black formatting error:', error.message);103      // Fallback to basic Python formatting104      return this.basicPythonFormat(code);105    }106  }107 108  /**109   * Format Java code110   */111  async formatJava(code) {112    try {113      // Basic Java formatting (can be enhanced with google-java-format)114      return this.basicJavaFormat(code);115    } catch (error) {116      console.error('Java formatting error:', error.message);117      return code;118    }119  }120 121  /**122   * Format C/C++ code - ASYNC123   */124  async formatCpp(code) {125    try {126      // Create temp file127      const tempFile = path.join(os.tmpdir(), `temp_${Date.now()}.cpp`);128      await fs.writeFile(tempFile, code, 'utf8');129      130      // Run clang-format if available (async, non-blocking)131      const { stdout } = await execAsync(`clang-format -style=Google "${tempFile}"`, {132        timeout: 5000133      });134      135      // Cleanup136      await fs.unlink(tempFile).catch(() => {});137      138      return stdout;139    } catch (error) {140      console.error('Clang-format error:', error.message);141      // Fallback to basic formatting142      return this.basicCppFormat(code);143    }144  }145 146  /**147   * Format C# code148   */149  async formatCSharp(code) {150    return this.basicCSharpFormat(code);151  }152 153  /**154   * Basic JavaScript formatting fallback (4 spaces - LeetCode style)155   */156  basicFormat(code) {157    let indentLevel = 0;158    const lines = code.split('\n');159    const result = [];160 161    for (let line of lines) {162      const trimmed = line.trim();163      164      // Decrease indent for closing braces165      if (trimmed.startsWith('}') || trimmed.startsWith(']') || trimmed.startsWith(')')) {166        indentLevel = Math.max(0, indentLevel - 1);167      }168      169      // Add indentation (4 spaces for JavaScript - LeetCode style)170      if (trimmed) {171        const indented = '    '.repeat(indentLevel) + trimmed;172        // Add space after commas and around operators173        const formatted = indented174          .replace(/,(\S)/g, ', $1')           // Space after comma175          .replace(/([^=!<>])=([^=])/g, '$1 = $2')  // Space around =176          .replace(/\s+$/g, '');                // Remove trailing whitespace177        result.push(formatted);178      } else {179        result.push('');180      }181      182      // Increase indent for opening braces183      if (trimmed.endsWith('{') || trimmed.endsWith('[') || trimmed.endsWith('(')) {184        indentLevel++;185      }186    }187    188    return result.join('\n');189  }190 191  /**192   * Basic Python formatting fallback (PEP8 style - LeetCode compatible)193   */194  basicPythonFormat(code) {195    const lines = code.split('\n');196    const result = [];197    let indentLevel = 0;198    let prevWasBlank = false;199 200    for (let i = 0; i < lines.length; i++) {201      const line = lines[i];202      const trimmed = line.trim();203      204      // Skip empty lines but track them205      if (!trimmed) {206        if (!prevWasBlank) {207          result.push('');208          prevWasBlank = true;209        }210        continue;211      }212      213      prevWasBlank = false;214      215      // Decrease indent for dedent keywords216      if (trimmed.startsWith('elif ') || 217          trimmed.startsWith('else:') || 218          trimmed.startsWith('except') || 219          trimmed.startsWith('finally:')) {220        indentLevel = Math.max(0, indentLevel - 1);221      }222      223      // Add indentation (4 spaces for Python - PEP8)224      const indentedLine = '    '.repeat(indentLevel) + trimmed;225      226      // Add space after commas if missing227      const formatted = indentedLine228        .replace(/,(\S)/g, ', $1')  // Add space after comma229        .replace(/\s+$/g, '');       // Remove trailing whitespace230      231      result.push(formatted);232      233      // Increase indent after colon234      if (trimmed.endsWith(':')) {235        indentLevel++;236      }237      238      // Check if next line should dedent239      const nextLine = lines[i + 1];240      if (nextLine) {241        const nextTrimmed = nextLine.trim();242        if (nextTrimmed && !nextTrimmed.startsWith('elif') && 243            !nextTrimmed.startsWith('else') && 244            !nextTrimmed.startsWith('except') &&245            !nextTrimmed.startsWith('finally')) {246          // Check if current line is a single-line statement that should dedent247          if (trimmed.startsWith('return ') || 248              trimmed.startsWith('break') || 249              trimmed.startsWith('continue') ||250              trimmed === 'pass') {251            indentLevel = Math.max(0, indentLevel - 1);252          }253        }254      }255    }256    257    return result.join('\n');258  }259 260  /**261   * Basic Java formatting fallback (Google Java Style - LeetCode compatible)262   */263  basicJavaFormat(code) {264    let formatted = code;265    let indentLevel = 0;266    const lines = code.split('\n');267    const result = [];268 269    for (let line of lines) {270      const trimmed = line.trim();271      272      // Decrease indent for closing braces273      if (trimmed.startsWith('}')) {274        indentLevel = Math.max(0, indentLevel - 1);275      }276      277      // Add indentation (4 spaces for Java)278      if (trimmed) {279        const indented = '    '.repeat(indentLevel) + trimmed;280        // Add space after commas and around operators281        const formatted = indented282          .replace(/,(\S)/g, ', $1')           // Space after comma283          .replace(/([^=!<>])=([^=])/g, '$1 = $2')  // Space around =284          .replace(/\s+$/g, '');                // Remove trailing whitespace285        result.push(formatted);286      } else {287        result.push('');288      }289      290      // Increase indent for opening braces291      if (trimmed.endsWith('{')) {292        indentLevel++;293      }294    }295    296    return result.join('\n');297  }298 299  /**300   * Basic C++ formatting fallback (Google Style - LeetCode compatible)301   */302  basicCppFormat(code) {303    let indentLevel = 0;304    const lines = code.split('\n');305    const result = [];306 307    for (let line of lines) {308      const trimmed = line.trim();309      310      // Decrease indent for closing braces311      if (trimmed.startsWith('}')) {312        indentLevel = Math.max(0, indentLevel - 1);313      }314      315      // Add indentation (4 spaces for C++)316      if (trimmed) {317        const indented = '    '.repeat(indentLevel) + trimmed;318        // Add space after commas and around operators319        const formatted = indented320          .replace(/,(\S)/g, ', $1')           // Space after comma321          .replace(/([^=!<>])=([^=])/g, '$1 = $2')  // Space around =322          .replace(/\s+$/g, '');                // Remove trailing whitespace323        result.push(formatted);324      } else {325        result.push('');326      }327      328      // Increase indent for opening braces329      if (trimmed.endsWith('{')) {330        indentLevel++;331      }332    }333    334    return result.join('\n');335  }336 337  /**338   * Basic C# formatting fallback339   */340  basicCSharpFormat(code) {341    return this.basicFormat(code);342  }343}344 345module.exports = new CodeFormatterService();346