Files

282 lines
8.5 KiB
Python

"""API dataclass definitions for codexlens LSP API.
This module defines all result dataclasses used by the public API layer,
following the patterns established in mcp/schema.py.
"""
from __future__ import annotations
from dataclasses import dataclass, field, asdict
from typing import List, Optional, Dict, Tuple
# =============================================================================
# Section 4.2: file_context dataclasses
# =============================================================================
@dataclass
class CallInfo:
"""Call relationship information.
Attributes:
symbol_name: Name of the called/calling symbol
file_path: Target file path (may be None if unresolved)
line: Line number of the call
relationship: Type of relationship (call | import | inheritance)
"""
symbol_name: str
file_path: Optional[str]
line: int
relationship: str # call | import | inheritance
def to_dict(self) -> dict:
"""Convert to dictionary, filtering None values."""
return {k: v for k, v in asdict(self).items() if v is not None}
@dataclass
class MethodContext:
"""Method context with call relationships.
Attributes:
name: Method/function name
kind: Symbol kind (function | method | class)
line_range: Start and end line numbers
signature: Function signature (if available)
calls: List of outgoing calls
callers: List of incoming calls
"""
name: str
kind: str # function | method | class
line_range: Tuple[int, int]
signature: Optional[str]
calls: List[CallInfo] = field(default_factory=list)
callers: List[CallInfo] = field(default_factory=list)
def to_dict(self) -> dict:
"""Convert to dictionary, filtering None values."""
result = {
"name": self.name,
"kind": self.kind,
"line_range": list(self.line_range),
"calls": [c.to_dict() for c in self.calls],
"callers": [c.to_dict() for c in self.callers],
}
if self.signature is not None:
result["signature"] = self.signature
return result
@dataclass
class FileContextResult:
"""File context result with method summaries.
Attributes:
file_path: Path to the analyzed file
language: Programming language
methods: List of method contexts
summary: Human-readable summary
discovery_status: Status flags for call resolution
"""
file_path: str
language: str
methods: List[MethodContext]
summary: str
discovery_status: Dict[str, bool] = field(default_factory=lambda: {
"outgoing_resolved": False,
"incoming_resolved": True,
"targets_resolved": False
})
def to_dict(self) -> dict:
"""Convert to dictionary for JSON serialization."""
return {
"file_path": self.file_path,
"language": self.language,
"methods": [m.to_dict() for m in self.methods],
"summary": self.summary,
"discovery_status": self.discovery_status,
}
# =============================================================================
# Section 4.3: find_definition dataclasses
# =============================================================================
@dataclass
class DefinitionResult:
"""Definition lookup result.
Attributes:
name: Symbol name
kind: Symbol kind (class, function, method, etc.)
file_path: File where symbol is defined
line: Start line number
end_line: End line number
signature: Symbol signature (if available)
container: Containing class/module (if any)
score: Match score for ranking
"""
name: str
kind: str
file_path: str
line: int
end_line: int
signature: Optional[str] = None
container: Optional[str] = None
score: float = 1.0
def to_dict(self) -> dict:
"""Convert to dictionary, filtering None values."""
return {k: v for k, v in asdict(self).items() if v is not None}
# =============================================================================
# Section 4.4: find_references dataclasses
# =============================================================================
@dataclass
class ReferenceResult:
"""Reference lookup result.
Attributes:
file_path: File containing the reference
line: Line number
column: Column number
context_line: The line of code containing the reference
relationship: Type of reference (call | import | type_annotation | inheritance)
"""
file_path: str
line: int
column: int
context_line: str
relationship: str # call | import | type_annotation | inheritance
def to_dict(self) -> dict:
"""Convert to dictionary."""
return asdict(self)
@dataclass
class GroupedReferences:
"""References grouped by definition.
Used when a symbol has multiple definitions (e.g., overloads).
Attributes:
definition: The definition this group refers to
references: List of references to this definition
"""
definition: DefinitionResult
references: List[ReferenceResult] = field(default_factory=list)
def to_dict(self) -> dict:
"""Convert to dictionary."""
return {
"definition": self.definition.to_dict(),
"references": [r.to_dict() for r in self.references],
}
# =============================================================================
# Section 4.5: workspace_symbols dataclasses
# =============================================================================
@dataclass
class SymbolInfo:
"""Symbol information for workspace search.
Attributes:
name: Symbol name
kind: Symbol kind
file_path: File where symbol is defined
line: Line number
container: Containing class/module (if any)
score: Match score for ranking
"""
name: str
kind: str
file_path: str
line: int
container: Optional[str] = None
score: float = 1.0
def to_dict(self) -> dict:
"""Convert to dictionary, filtering None values."""
return {k: v for k, v in asdict(self).items() if v is not None}
# =============================================================================
# Section 4.6: get_hover dataclasses
# =============================================================================
@dataclass
class HoverInfo:
"""Hover information for a symbol.
Attributes:
name: Symbol name
kind: Symbol kind
signature: Symbol signature
documentation: Documentation string (if available)
file_path: File where symbol is defined
line_range: Start and end line numbers
type_info: Type information (if available)
"""
name: str
kind: str
signature: str
documentation: Optional[str]
file_path: str
line_range: Tuple[int, int]
type_info: Optional[str] = None
def to_dict(self) -> dict:
"""Convert to dictionary, filtering None values."""
result = {
"name": self.name,
"kind": self.kind,
"signature": self.signature,
"file_path": self.file_path,
"line_range": list(self.line_range),
}
if self.documentation is not None:
result["documentation"] = self.documentation
if self.type_info is not None:
result["type_info"] = self.type_info
return result
# =============================================================================
# Section 4.7: semantic_search dataclasses
# =============================================================================
@dataclass
class SemanticResult:
"""Semantic search result.
Attributes:
symbol_name: Name of the matched symbol
kind: Symbol kind
file_path: File where symbol is defined
line: Line number
vector_score: Vector similarity score (None if not available)
structural_score: Structural match score (None if not available)
fusion_score: Combined fusion score
snippet: Code snippet
match_reason: Explanation of why this matched (optional)
"""
symbol_name: str
kind: str
file_path: str
line: int
vector_score: Optional[float]
structural_score: Optional[float]
fusion_score: float
snippet: str
match_reason: Optional[str] = None
def to_dict(self) -> dict:
"""Convert to dictionary, filtering None values."""
return {k: v for k, v in asdict(self).items() if v is not None}