mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-11 02:33:51 +08:00
Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -0,0 +1,266 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test for Go symbol discovery including all symbol types."""
|
||||
import pytest
|
||||
|
||||
from code_index_mcp.indexing.strategies.go_strategy import GoParsingStrategy
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_code_with_all_symbols():
|
||||
"""Fixture with variables, constants, functions, structs, interfaces and methods."""
|
||||
return '''
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt" // comment mentioning ) parentheses )
|
||||
strutil "strings"
|
||||
helper "example.com/project/toolkit"
|
||||
) // closing comment with ) ) characters
|
||||
import ("math" /* inline comment ) inside */)
|
||||
import . "errors"
|
||||
import _ "embed"
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Application version constant
|
||||
const VERSION = "1.0.0"
|
||||
|
||||
// Global variable for configuration
|
||||
var config string = "default"
|
||||
|
||||
// Add returns the sum of two integers.
|
||||
func Add(x int, y int) int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
// ComplexFunc demonstrates a complex function signature.
|
||||
// It takes multiple parameters including variadic args.
|
||||
func ComplexFunc(name string, values ...int) (int, error) {
|
||||
sum := 0
|
||||
for _, v := range values {
|
||||
sum += v
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
// Divide divides two numbers and returns the result.
|
||||
// It returns an error if the divisor is zero.
|
||||
//
|
||||
// Parameters:
|
||||
// - a: the dividend
|
||||
// - b: the divisor
|
||||
//
|
||||
// Returns:
|
||||
// - float64: the quotient
|
||||
// - error: an error if b is zero
|
||||
func Divide(a, b float64) (float64, error) {
|
||||
if b == 0 {
|
||||
return 0, errors.New("division by zero")
|
||||
}
|
||||
return a / b, nil
|
||||
}
|
||||
|
||||
// ProcessData processes the given data with options.
|
||||
//
|
||||
// The function accepts a data string and processes it according to
|
||||
// the provided options. It supports multiple processing modes.
|
||||
//
|
||||
// Args:
|
||||
// data: the input data string to process
|
||||
// options: configuration options for processing
|
||||
//
|
||||
// Returns:
|
||||
// The processed result string and any error encountered.
|
||||
//
|
||||
// Example:
|
||||
// result, err := ProcessData("hello", Options{Mode: "upper"})
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
func ProcessData(data string, options map[string]interface{}) (string, error) {
|
||||
// Implementation
|
||||
return strings.ToUpper(data), nil
|
||||
}
|
||||
|
||||
// User represents a user in the system.
|
||||
type User struct {
|
||||
ID int
|
||||
Name string
|
||||
Email string
|
||||
IsActive bool
|
||||
}
|
||||
|
||||
// NewUser creates a new User instance.
|
||||
func NewUser(id int, name string, email string) *User {
|
||||
return &User{
|
||||
ID: id,
|
||||
Name: name,
|
||||
Email: email,
|
||||
}
|
||||
}
|
||||
|
||||
// GetFullName returns the user's full name.
|
||||
func (u *User) GetFullName() string {
|
||||
return u.Name
|
||||
}
|
||||
|
||||
// Activate marks the user as active.
|
||||
// This is a pointer receiver method.
|
||||
func (u *User) Activate() {
|
||||
u.IsActive = true
|
||||
}
|
||||
|
||||
// IsValid checks if the user has valid data.
|
||||
// This is a value receiver method.
|
||||
func (u User) IsValid() bool {
|
||||
return u.ID > 0 && u.Name != ""
|
||||
}
|
||||
|
||||
// Repository interface defines data access methods.
|
||||
type Repository interface {
|
||||
// Save stores an entity
|
||||
Save(entity interface{}) error
|
||||
|
||||
// FindByID retrieves an entity by ID
|
||||
FindByID(id int) (interface{}, error)
|
||||
|
||||
// Delete removes an entity
|
||||
Delete(id int) error
|
||||
}
|
||||
|
||||
// Logger is a simple interface for logging.
|
||||
type Logger interface {
|
||||
Log(message string)
|
||||
}
|
||||
|
||||
// Calculate is a function type
|
||||
type Calculate func(a, b int) int
|
||||
'''
|
||||
|
||||
|
||||
def test_go_symbol_discovery(test_code_with_all_symbols):
|
||||
"""Test that all Go symbol types are correctly discovered."""
|
||||
strategy = GoParsingStrategy()
|
||||
symbols, file_info = strategy.parse_file("test.go", test_code_with_all_symbols)
|
||||
|
||||
# Create a lookup dict by symbol name for easier access
|
||||
# This will throw KeyError if a symbol is missing
|
||||
symbol_lookup = {}
|
||||
for symbol_id, symbol_info in symbols.items():
|
||||
# Extract the symbol name from the ID (format: "file.go::SymbolName")
|
||||
if '::' in symbol_id:
|
||||
name = symbol_id.split('::')[1]
|
||||
symbol_lookup[name] = symbol_info
|
||||
|
||||
# Verify package is extracted
|
||||
assert file_info.package == "main"
|
||||
|
||||
# Verify imports are extracted (including tricky formats and aliases)
|
||||
assert "fmt" in file_info.imports
|
||||
assert "strings" in file_info.imports
|
||||
assert "errors" in file_info.imports
|
||||
assert "example.com/project/toolkit" in file_info.imports
|
||||
assert "math" in file_info.imports
|
||||
assert "embed" in file_info.imports
|
||||
assert "time" in file_info.imports
|
||||
|
||||
# Verify all expected functions are in file_info
|
||||
discovered_functions = file_info.symbols.get('functions', [])
|
||||
expected_functions = ['Add', 'ComplexFunc', 'Divide', 'ProcessData', 'NewUser', 'GetFullName', 'Activate', 'IsValid']
|
||||
for func in expected_functions:
|
||||
assert func in discovered_functions, f"Function '{func}' not in file_info.symbols['functions']"
|
||||
|
||||
# Verify structs and interfaces are discovered (in 'classes')
|
||||
discovered_classes = file_info.symbols.get('classes', [])
|
||||
assert 'User' in discovered_classes
|
||||
assert 'Repository' in discovered_classes
|
||||
assert 'Logger' in discovered_classes
|
||||
|
||||
# Verify all symbols are in lookup
|
||||
assert 'Add' in symbol_lookup
|
||||
assert 'ComplexFunc' in symbol_lookup
|
||||
assert 'Divide' in symbol_lookup
|
||||
assert 'ProcessData' in symbol_lookup
|
||||
assert 'User' in symbol_lookup
|
||||
assert 'NewUser' in symbol_lookup
|
||||
assert 'GetFullName' in symbol_lookup
|
||||
assert 'Activate' in symbol_lookup
|
||||
assert 'IsValid' in symbol_lookup
|
||||
assert 'Repository' in symbol_lookup
|
||||
assert 'Logger' in symbol_lookup
|
||||
|
||||
# Check symbol types
|
||||
assert symbol_lookup['Add'].type == 'function'
|
||||
assert symbol_lookup['ComplexFunc'].type == 'function'
|
||||
assert symbol_lookup['Divide'].type == 'function'
|
||||
assert symbol_lookup['ProcessData'].type == 'function'
|
||||
assert symbol_lookup['NewUser'].type == 'function'
|
||||
assert symbol_lookup['GetFullName'].type == 'method'
|
||||
assert symbol_lookup['Activate'].type == 'method'
|
||||
assert symbol_lookup['IsValid'].type == 'method'
|
||||
assert symbol_lookup['User'].type == 'struct'
|
||||
assert symbol_lookup['Repository'].type == 'interface'
|
||||
assert symbol_lookup['Logger'].type == 'interface'
|
||||
|
||||
# Check signatures are captured
|
||||
assert symbol_lookup['Add'].signature is not None
|
||||
assert 'Add' in symbol_lookup['Add'].signature
|
||||
assert 'int' in symbol_lookup['Add'].signature
|
||||
|
||||
assert symbol_lookup['ComplexFunc'].signature is not None
|
||||
assert 'ComplexFunc' in symbol_lookup['ComplexFunc'].signature
|
||||
assert '...int' in symbol_lookup['ComplexFunc'].signature or 'values' in symbol_lookup['ComplexFunc'].signature
|
||||
|
||||
assert symbol_lookup['GetFullName'].signature is not None
|
||||
assert 'GetFullName' in symbol_lookup['GetFullName'].signature
|
||||
assert 'User' in symbol_lookup['GetFullName'].signature or '*User' in symbol_lookup['GetFullName'].signature
|
||||
|
||||
# Check line numbers are correct (approximate, since we know the structure)
|
||||
assert symbol_lookup['Add'].line > 10
|
||||
assert symbol_lookup['User'].line > symbol_lookup['Add'].line
|
||||
assert symbol_lookup['GetFullName'].line > symbol_lookup['User'].line
|
||||
|
||||
# Check that methods are associated with correct receivers
|
||||
# Method signatures should contain receiver information
|
||||
assert 'User' in symbol_lookup['GetFullName'].signature
|
||||
assert 'User' in symbol_lookup['Activate'].signature
|
||||
assert 'User' in symbol_lookup['IsValid'].signature
|
||||
|
||||
# Check docstrings/comments are extracted
|
||||
assert symbol_lookup['Add'].docstring == "Add returns the sum of two integers."
|
||||
assert symbol_lookup['ComplexFunc'].docstring is not None
|
||||
assert "complex function signature" in symbol_lookup['ComplexFunc'].docstring.lower()
|
||||
assert "variadic" in symbol_lookup['ComplexFunc'].docstring.lower()
|
||||
|
||||
assert symbol_lookup['User'].docstring == "User represents a user in the system."
|
||||
assert symbol_lookup['NewUser'].docstring == "NewUser creates a new User instance."
|
||||
|
||||
assert symbol_lookup['GetFullName'].docstring == "GetFullName returns the user's full name."
|
||||
assert symbol_lookup['Activate'].docstring is not None
|
||||
assert "marks the user as active" in symbol_lookup['Activate'].docstring.lower()
|
||||
|
||||
assert symbol_lookup['IsValid'].docstring is not None
|
||||
assert "checks if the user has valid data" in symbol_lookup['IsValid'].docstring.lower()
|
||||
|
||||
assert symbol_lookup['Repository'].docstring == "Repository interface defines data access methods."
|
||||
assert symbol_lookup['Logger'].docstring == "Logger is a simple interface for logging."
|
||||
|
||||
# Check Go standard docstring format with parameters and returns
|
||||
divide_doc = symbol_lookup['Divide'].docstring
|
||||
assert divide_doc is not None
|
||||
assert "divides two numbers" in divide_doc.lower()
|
||||
assert "Parameters:" in divide_doc
|
||||
assert "Returns:" in divide_doc
|
||||
assert "- a: the dividend" in divide_doc
|
||||
assert "- b: the divisor" in divide_doc
|
||||
assert "error if b is zero" in divide_doc.lower()
|
||||
|
||||
# Check detailed docstring with examples
|
||||
process_doc = symbol_lookup['ProcessData'].docstring
|
||||
assert process_doc is not None
|
||||
assert "processes the given data" in process_doc.lower()
|
||||
assert "Args:" in process_doc or "Parameters:" in process_doc.lower()
|
||||
assert "Returns:" in process_doc
|
||||
assert "Example:" in process_doc
|
||||
assert "ProcessData" in process_doc
|
||||
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test for Python symbol discovery including all symbol types.
|
||||
"""
|
||||
import pytest
|
||||
from textwrap import dedent
|
||||
|
||||
from code_index_mcp.indexing.strategies.python_strategy import PythonParsingStrategy
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_code_with_all_symbols():
|
||||
"""Fixture with variables, constants, functions, classes and methods."""
|
||||
return '''
|
||||
CONSTANT = 42
|
||||
variable = 'hello'
|
||||
|
||||
def sync_function():
|
||||
"""A regular synchronous function."""
|
||||
return "sync result"
|
||||
|
||||
async def async_function():
|
||||
"""An asynchronous function."""
|
||||
return "async result"
|
||||
|
||||
def top_level_function(x, y):
|
||||
"""Function without type hints."""
|
||||
return x + y
|
||||
|
||||
def function_with_types(name: str, age: int, active: bool = True) -> dict:
|
||||
"""
|
||||
Function with type hints and default values.
|
||||
|
||||
Args:
|
||||
name: The person's name
|
||||
age: The person's age
|
||||
active: Whether the person is active
|
||||
|
||||
Returns:
|
||||
A dictionary with person info
|
||||
"""
|
||||
return {"name": name, "age": age, "active": active}
|
||||
|
||||
def complex_function(items: list[str], *args: int, callback=None, **kwargs: str) -> tuple[int, str]:
|
||||
"""Function with complex signature including *args and **kwargs."""
|
||||
return len(items), str(args)
|
||||
|
||||
class TestClass:
|
||||
"""A test class with various methods."""
|
||||
CLASS_VAR = 123
|
||||
|
||||
def __init__(self, value: int):
|
||||
"""Initialize with a value."""
|
||||
self.value = value
|
||||
|
||||
def sync_method(self):
|
||||
"""A regular synchronous method."""
|
||||
return "sync method result"
|
||||
|
||||
async def async_method(self):
|
||||
"""An asynchronous method."""
|
||||
return "async method result"
|
||||
|
||||
def method(self):
|
||||
return self.value
|
||||
|
||||
def typed_method(self, x: float, y: float) -> float:
|
||||
"""Method with type hints.
|
||||
|
||||
Returns the sum of x and y.
|
||||
"""
|
||||
return x + y
|
||||
'''
|
||||
|
||||
|
||||
def test_python_symbol_discovery(test_code_with_all_symbols):
|
||||
"""Test that all Python symbol types are correctly discovered."""
|
||||
strategy = PythonParsingStrategy()
|
||||
symbols, file_info = strategy.parse_file("test.py", test_code_with_all_symbols)
|
||||
|
||||
# Create a lookup dict by symbol name for easier access
|
||||
# This will throw KeyError if a symbol is missing
|
||||
symbol_lookup = {}
|
||||
for symbol_id, symbol_info in symbols.items():
|
||||
# Extract the symbol name from the ID (format: "file.py::SymbolName")
|
||||
if '::' in symbol_id:
|
||||
name = symbol_id.split('::')[1]
|
||||
symbol_lookup[name] = symbol_info
|
||||
|
||||
# Verify all expected functions are in file_info
|
||||
discovered_functions = file_info.symbols.get('functions', [])
|
||||
expected_functions = ['sync_function', 'async_function', 'top_level_function',
|
||||
'function_with_types', 'complex_function']
|
||||
for func in expected_functions:
|
||||
assert func in discovered_functions, f"Function '{func}' not in file_info.symbols['functions']"
|
||||
|
||||
# Verify all expected methods are discovered
|
||||
expected_methods = ['TestClass.__init__', 'TestClass.sync_method',
|
||||
'TestClass.async_method', 'TestClass.method', 'TestClass.typed_method']
|
||||
for method in expected_methods:
|
||||
assert method in symbol_lookup, f"Method '{method}' not found in symbols"
|
||||
|
||||
# Verify class is discovered
|
||||
assert 'TestClass' in file_info.symbols.get('classes', [])
|
||||
assert 'TestClass' in symbol_lookup
|
||||
|
||||
# Check symbol types
|
||||
assert symbol_lookup['sync_function'].type == 'function'
|
||||
assert symbol_lookup['async_function'].type == 'function'
|
||||
assert symbol_lookup['top_level_function'].type == 'function'
|
||||
assert symbol_lookup['function_with_types'].type == 'function'
|
||||
assert symbol_lookup['complex_function'].type == 'function'
|
||||
assert symbol_lookup['TestClass'].type == 'class'
|
||||
assert symbol_lookup['TestClass.__init__'].type == 'method'
|
||||
assert symbol_lookup['TestClass.sync_method'].type == 'method'
|
||||
assert symbol_lookup['TestClass.async_method'].type == 'method'
|
||||
assert symbol_lookup['TestClass.method'].type == 'method'
|
||||
assert symbol_lookup['TestClass.typed_method'].type == 'method'
|
||||
|
||||
# Check docstrings explicitly
|
||||
assert symbol_lookup['sync_function'].docstring == "A regular synchronous function."
|
||||
assert symbol_lookup['async_function'].docstring == "An asynchronous function."
|
||||
assert symbol_lookup['top_level_function'].docstring == "Function without type hints."
|
||||
|
||||
expected_docstring = dedent("""
|
||||
Function with type hints and default values.
|
||||
|
||||
Args:
|
||||
name: The person's name
|
||||
age: The person's age
|
||||
active: Whether the person is active
|
||||
|
||||
Returns:
|
||||
A dictionary with person info
|
||||
""").strip()
|
||||
assert symbol_lookup['function_with_types'].docstring == expected_docstring
|
||||
|
||||
assert symbol_lookup['complex_function'].docstring == "Function with complex signature including *args and **kwargs."
|
||||
assert symbol_lookup['TestClass.__init__'].docstring == "Initialize with a value."
|
||||
assert symbol_lookup['TestClass.sync_method'].docstring == "A regular synchronous method."
|
||||
assert symbol_lookup['TestClass.async_method'].docstring == "An asynchronous method."
|
||||
assert symbol_lookup['TestClass.method'].docstring is None
|
||||
|
||||
expected_typed_method_docstring = dedent("""
|
||||
Method with type hints.
|
||||
|
||||
Returns the sum of x and y.
|
||||
""").strip()
|
||||
assert symbol_lookup['TestClass.typed_method'].docstring == expected_typed_method_docstring
|
||||
assert symbol_lookup['TestClass'].docstring == "A test class with various methods."
|
||||
|
||||
# Check signatures explicitly
|
||||
assert symbol_lookup['sync_function'].signature == "def sync_function():"
|
||||
assert symbol_lookup['async_function'].signature == "def async_function():"
|
||||
assert symbol_lookup['top_level_function'].signature == "def top_level_function(x, y):"
|
||||
assert symbol_lookup['function_with_types'].signature == "def function_with_types(name, age, active):"
|
||||
assert symbol_lookup['complex_function'].signature == "def complex_function(items, *args, **kwargs):"
|
||||
assert symbol_lookup['TestClass.__init__'].signature == "def __init__(self, value):"
|
||||
assert symbol_lookup['TestClass.sync_method'].signature == "def sync_method(self):"
|
||||
assert symbol_lookup['TestClass.async_method'].signature == "def async_method(self):"
|
||||
assert symbol_lookup['TestClass.method'].signature == "def method(self):"
|
||||
assert symbol_lookup['TestClass.typed_method'].signature == "def typed_method(self, x, y):"
|
||||
Reference in New Issue
Block a user