|
44 | 44 | """ |
45 | 45 |
|
46 | 46 | import os |
| 47 | +import sys |
47 | 48 | from pathlib import Path |
48 | 49 |
|
| 50 | +# Add current directory to path for local imports |
| 51 | +sys.path.insert(0, os.path.dirname(__file__)) |
| 52 | + |
| 53 | +try: |
| 54 | + from code_extractor import CodeExtractor, create_extractor |
| 55 | + from code_extractor.models import SymbolKind |
| 56 | +except ImportError as e: |
| 57 | + print(f"Error: Code extractor library not found: {e}") |
| 58 | + print("Make sure it's installed or run from the correct directory.") |
| 59 | + exit(1) |
| 60 | + |
49 | 61 | try: |
50 | 62 | from tree_sitter_languages import get_language, get_parser |
51 | 63 | except ImportError: |
@@ -366,147 +378,23 @@ def get_symbols(file_path: str) -> list: |
366 | 378 | if not os.path.exists(file_path): |
367 | 379 | return [{"error": f"File not found: {file_path}"}] |
368 | 380 |
|
369 | | - lang_name = get_language_for_file(file_path) |
370 | | - if lang_name == 'text': |
371 | | - return [] # Just return empty for unsupported files |
372 | | - |
373 | 381 | try: |
374 | | - parser = get_parser(lang_name) |
375 | | - |
376 | | - with open(file_path, 'rb') as f: |
377 | | - source = f.read() |
378 | | - |
379 | | - tree = parser.parse(source) |
380 | | - symbols = [] |
381 | | - |
382 | | - # Combined function and class types for each language |
383 | | - symbol_types = { |
384 | | - 'python': { |
385 | | - 'function_definition': 'function', |
386 | | - 'async_function_definition': 'function', |
387 | | - 'class_definition': 'class', |
388 | | - }, |
389 | | - 'javascript': { |
390 | | - 'function_declaration': 'function', |
391 | | - 'function_expression': 'function', |
392 | | - 'arrow_function': 'function', |
393 | | - 'class_declaration': 'class', |
394 | | - }, |
395 | | - 'typescript': { |
396 | | - 'function_declaration': 'function', |
397 | | - 'function_expression': 'function', |
398 | | - 'arrow_function': 'function', |
399 | | - 'method_definition': 'method', |
400 | | - 'class_declaration': 'class', |
401 | | - 'interface_declaration': 'interface', |
402 | | - }, |
403 | | - 'tsx': { |
404 | | - 'function_declaration': 'function', |
405 | | - 'function_expression': 'function', |
406 | | - 'arrow_function': 'function', |
407 | | - 'method_definition': 'method', |
408 | | - 'class_declaration': 'class', |
409 | | - 'interface_declaration': 'interface', |
410 | | - }, |
411 | | - 'go': { |
412 | | - 'function_declaration': 'function', |
413 | | - 'method_declaration': 'method', |
414 | | - 'type_declaration': 'type', |
415 | | - }, |
416 | | - 'rust': { |
417 | | - 'function_item': 'function', |
418 | | - 'struct_item': 'struct', |
419 | | - 'enum_item': 'enum', |
420 | | - }, |
421 | | - 'java': { |
422 | | - 'method_declaration': 'method', |
423 | | - 'constructor_declaration': 'constructor', |
424 | | - 'class_declaration': 'class', |
425 | | - }, |
426 | | - 'c': { |
427 | | - 'function_definition': 'function', |
428 | | - }, |
429 | | - 'cpp': { |
430 | | - 'function_definition': 'function', |
431 | | - 'class_specifier': 'class', |
432 | | - }, |
433 | | - 'c_sharp': { |
434 | | - 'method_declaration': 'method', |
435 | | - 'constructor_declaration': 'constructor', |
436 | | - 'class_declaration': 'class', |
437 | | - }, |
438 | | - 'ruby': { |
439 | | - 'method': 'method', |
440 | | - 'singleton_method': 'method', |
441 | | - 'class': 'class', |
442 | | - }, |
443 | | - 'php': { |
444 | | - 'function_definition': 'function', |
445 | | - 'method_declaration': 'method', |
446 | | - 'class_declaration': 'class', |
447 | | - }, |
448 | | - 'swift': { |
449 | | - 'function_declaration': 'function', |
450 | | - 'class_declaration': 'class', |
451 | | - }, |
452 | | - 'kotlin': { |
453 | | - 'function_declaration': 'function', |
454 | | - 'class_declaration': 'class', |
455 | | - }, |
456 | | - 'scala': { |
457 | | - 'function_definition': 'function', |
458 | | - 'class_definition': 'class', |
459 | | - }, |
460 | | - } |
461 | | - |
462 | | - lang_symbols = symbol_types.get(lang_name, {}) |
463 | | - |
464 | | - def extract_symbols(node, depth=0): |
465 | | - if node.type in lang_symbols: |
466 | | - # Extract name |
467 | | - name = None |
468 | | - for child in node.children: |
469 | | - if child.type in ['identifier', 'type_identifier', 'property_identifier', 'field_identifier']: |
470 | | - name = source[child.start_byte:child.end_byte].decode( |
471 | | - 'utf-8') |
472 | | - break |
473 | | - |
474 | | - # Try field-based access as fallback |
475 | | - if not name and hasattr(node, 'child_by_field_name'): |
476 | | - name_node = node.child_by_field_name('name') |
477 | | - if name_node: |
478 | | - name = source[name_node.start_byte:name_node.end_byte].decode( |
479 | | - 'utf-8') |
480 | | - |
481 | | - if name: |
482 | | - start_line = source[:node.start_byte].count(b'\n') + 1 |
483 | | - end_line = source[:node.end_byte].count(b'\n') + 1 |
484 | | - |
485 | | - # Get first line as preview |
486 | | - first_line = source[node.start_byte:node.end_byte].decode( |
487 | | - 'utf-8').split('\n')[0] |
488 | | - if len(first_line) > 80: |
489 | | - first_line = first_line[:77] + "..." |
490 | | - |
491 | | - symbols.append({ |
492 | | - 'name': name, |
493 | | - 'type': lang_symbols[node.type], |
494 | | - 'start_line': start_line, |
495 | | - 'end_line': end_line, |
496 | | - 'lines': f"{start_line}-{end_line}", |
497 | | - 'preview': first_line |
498 | | - }) |
499 | | - |
500 | | - # Recurse |
501 | | - for child in node.children: |
502 | | - extract_symbols(child, depth + 1) |
503 | | - |
504 | | - extract_symbols(tree.root_node) |
505 | | - return symbols |
506 | | - |
| 382 | + extractor = create_extractor(file_path) |
| 383 | + |
| 384 | + with open(file_path, 'r', encoding='utf-8') as f: |
| 385 | + source_code = f.read() |
| 386 | + |
| 387 | + symbols = extractor.extract_symbols(source_code) |
| 388 | + |
| 389 | + # Convert to dict format for MCP compatibility |
| 390 | + result = [] |
| 391 | + for symbol in symbols: |
| 392 | + result.append(symbol.to_dict()) |
| 393 | + |
| 394 | + return result |
| 395 | + |
507 | 396 | except Exception as e: |
508 | | - import traceback |
509 | | - return [{"error": f"Failed to parse '{file_path}': {e.__class__.__name__}: {e}", "traceback": traceback.format_exc()}] |
| 397 | + return [{"error": f"Failed to parse '{file_path}': {str(e)}"}] |
510 | 398 |
|
511 | 399 |
|
512 | 400 | @mcp.tool() |
|
0 commit comments