All files / src/services parser.service.js

0% Statements 0/40
0% Branches 0/13
0% Functions 0/5
0% Lines 0/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162                                                                                                                                                                                                                                                                                                                                   
/**
 * ParserService
 *
 * This service integrates TreeSitterManager with language-specific parsers
 * to provide code entity and relationship extraction from source files.
 */
 
import { TreeSitterManager } from "./parsing/treeSitterManager.js";
import { parseJavaScript } from "./parsing/javascript.parser.js";
import { parsePython } from "./parsing/python.parser.js";
import { parseTypeScript } from "./parsing/typescript.parser.js";
import { parseMarkdownContent } from "./parsing/markdown.parser.js";
import logger from "../utils/logger.js";
 
export class ParserService {
  /**
   * Create a new ParserService instance
   */
  constructor() {
    this.treeSitterManager = new TreeSitterManager();
    this.initialized = false;
  }
 
  /**
   * Initialize the ParserService
   * @param {Array<string>} configuredLanguages - Language identifiers to load ('javascript', 'python', 'typescript', 'tsx')
   * @returns {Promise<void>}
   */
  async initialize(
    configuredLanguages = ["javascript", "python", "typescript", "tsx"]
  ) {
    try {
      logger.info(
        `Initializing ParserService with languages: ${configuredLanguages.join(
          ", "
        )}`
      );
      await this.treeSitterManager.initializeGrammars(configuredLanguages);
      this.initialized = true;
      logger.info("ParserService initialized successfully");
    } catch (error) {
      logger.error(`Error initializing ParserService: ${error.message}`, {
        error,
      });
      throw error;
    }
  }
 
  /**
   * Parse a code file and extract entities and relationships
   * @param {string} filePath - Path to the file (used for logging)
   * @param {string} fileContent - Content of the file to parse
   * @param {string} language - Language identifier ('javascript', 'python', 'typescript', 'tsx')
   * @returns {Promise<Object>} Object containing entities, relationships, and errors
   */
  async parseCodeFile(filePath, fileContent, language) {
    if (!this.initialized) {
      logger.warn("ParserService.parseCodeFile called before initialization");
      return {
        entities: [],
        relationships: [],
        errors: ["ParserService not initialized"],
      };
    }
 
    try {
      logger.info(`Parsing file: ${filePath} (language: ${language})`);
 
      // Get parser for the language
      const parser = this.treeSitterManager.getParserForLanguage(language);
      if (!parser) {
        logger.error(`No parser available for language: ${language}`);
        return {
          entities: [],
          relationships: [],
          errors: [`Unsupported language or grammar not loaded: ${language}`],
        };
      }
 
      // Parse the content to get the AST
      const tree = parser.parse(fileContent);
      const astRootNode = tree.rootNode;
 
      // Delegate to the language-specific parser
      let result;
      switch (language) {
        case "javascript":
        case "jsx":
          result = parseJavaScript(astRootNode, fileContent);
          break;
        case "typescript":
        case "tsx":
          result = parseTypeScript(astRootNode, fileContent);
          break;
        case "python":
          result = parsePython(astRootNode, fileContent);
          break;
        default:
          logger.error(`No parser implementation for language: ${language}`);
          return {
            entities: [],
            relationships: [],
            errors: [`No parser implementation for language: ${language}`],
          };
      }
 
      logger.info(
        `Successfully parsed ${filePath}: found ${result.entities.length} entities and ${result.relationships.length} relationships`
      );
      return { ...result, errors: [] };
    } catch (error) {
      logger.error(`Error parsing file ${filePath}: ${error.message}`, {
        error,
      });
      return { entities: [], relationships: [], errors: [error.message] };
    }
  }
 
  /**
   * Parse a Markdown file and extract content
   * @param {string} filePath - Path to the file (used for logging)
   * @param {string} fileContent - Content of the file to parse
   * @returns {Promise<Object>} Object containing rawContent and any errors
   */
  async parseMarkdownFile(filePath, fileContent) {
    try {
      logger.info(`Parsing Markdown file: ${filePath}`);
 
      // Call the parseMarkdownContent function
      const result = parseMarkdownContent(fileContent);
 
      // Return an object compatible with what IndexingService expects
      return {
        rawContent: result.rawContent,
        errors: result.error ? [result.error] : [],
      };
    } catch (error) {
      logger.error(
        `Error parsing Markdown file ${filePath}: ${error.message}`,
        {
          error,
        }
      );
      return {
        rawContent: fileContent, // Return the original content even if parsing fails
        errors: [error.message],
      };
    }
  }
 
  /**
   * Get the list of supported languages
   * @returns {Array<string>} List of supported language identifiers
   */
  getSupportedLanguages() {
    return this.treeSitterManager.getLoadedLanguages();
  }
}
 
// Export a singleton instance
export default new ParserService();