use serde::Serialize;
use serde_json::Value;
use super::graph_cache;
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ProvenanceData {
pub source: &'static str,
#[serde(skip_serializing_if = "Option::is_none")]
pub coordinates: Option<String>,
pub is_direct: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub jar_path: Option<String>,
}
pub struct ToolExecution<T>
where
T: Serialize,
{
pub data: T,
pub used_index: bool,
pub used_graph: bool,
pub graph_metadata: Option<GraphMetadata>,
pub execution_ms: u64,
pub next_page_token: Option<String>,
pub total: Option<u64>,
pub truncated: Option<bool>,
pub candidates_scanned: Option<u64>,
pub workspace_path: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GraphMetadata {
pub total_nodes: u64,
pub total_edges: u64,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub languages: Vec<String>,
pub cross_language_edges: u64,
pub graph_version: String,
pub rebuild_epoch_ms: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub cache: Option<GraphCacheMetadata>,
#[serde(default, skip_serializing_if = "std::collections::HashMap::is_empty")]
pub confidence: std::collections::HashMap<String, sqry_core::confidence::ConfidenceMetadata>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GraphCacheMetadata {
pub strategy: GraphCacheStrategyMetadata,
pub trace_path: CacheMetricsSummary,
pub subgraph: CacheMetricsSummary,
#[serde(skip_serializing_if = "Option::is_none")]
pub current_request: Option<CacheRequestEvent>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GraphCacheStrategyMetadata {
pub policy: &'static str,
pub ttl_seconds: u64,
pub trace_path_capacity: usize,
pub subgraph_capacity: usize,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CacheMetricsSummary {
pub hits: u64,
pub misses: u64,
pub evictions: u64,
pub expired: u64,
pub hit_rate: f64,
#[serde(skip_serializing_if = "Option::is_none")]
pub warm_latency: Option<graph_cache::LatencyStatsSnapshot>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cold_latency: Option<graph_cache::LatencyStatsSnapshot>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_event: Option<graph_cache::CacheEvent>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CacheRequestEvent {
pub tool: &'static str,
pub state: graph_cache::CacheState,
pub latency_ms: u64,
pub timestamp_ms: u64,
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct CacheRequestContext {
pub tool: &'static str,
pub state: graph_cache::CacheState,
pub latency_ms: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RangeData {
pub start: PositionData,
pub end: PositionData,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PositionData {
pub line: u32,
pub character: u32,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeContext {
pub code: String,
pub lines_before: usize,
pub lines_after: usize,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NodeRefData {
pub name: String,
#[serde(rename = "qualifiedName")]
pub qualified_name: String,
pub kind: String,
pub language: String,
#[serde(rename = "fileUri")]
pub file_uri: String,
pub range: RangeData,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Value>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SearchHit {
pub name: String,
#[serde(rename = "qualifiedName")]
pub qualified_name: String,
pub kind: String,
pub language: String,
#[serde(rename = "fileUri")]
pub file_uri: String,
pub range: RangeData,
pub score: f64,
#[serde(skip_serializing_if = "Option::is_none")]
pub context: Option<CodeContext>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub relations: Option<SearchHitRelations>,
#[serde(skip_serializing_if = "Option::is_none")]
pub macro_metadata: Option<MacroMetadataResponse>,
#[serde(skip_serializing_if = "Option::is_none")]
pub provenance: Option<ProvenanceData>,
}
#[derive(Debug, Clone, Serialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct SearchHitRelations {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub callers: Vec<NodeRefData>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub callees: Vec<NodeRefData>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SemanticSearchData {
pub results: Vec<SearchHit>,
pub total: u64,
pub truncated: bool,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct IndexStatusData {
pub has_index: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub root_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub indexed_symbols: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub files_indexed: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub index_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub has_relations: Option<bool>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RebuildIndexData {
pub success: bool,
pub root_path: String,
pub node_count: u64,
pub edge_count: u64,
pub files_indexed: u64,
pub built_at: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RelationEdgeData {
#[serde(skip_serializing_if = "Option::is_none")]
pub from: Option<NodeRefData>,
#[serde(skip_serializing_if = "Option::is_none")]
pub to: Option<NodeRefData>,
#[serde(rename = "type")]
pub relation_type: String,
pub depth: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Value>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RelationQueryData {
pub relation_type: String,
pub relations: Vec<RelationEdgeData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CallHierarchyNode {
pub symbol: NodeRefData,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub children: Vec<CallHierarchyNode>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub call_ranges: Vec<RangeData>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CallHierarchyData {
pub root: NodeRefData,
pub direction: String,
pub items: Vec<CallHierarchyNode>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ExplainRelations {
#[serde(skip_serializing_if = "Option::is_none")]
pub callers: Option<Vec<NodeRefData>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub callees: Option<Vec<NodeRefData>>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ExplainCodeData {
pub symbol: NodeRefData,
#[serde(skip_serializing_if = "Option::is_none")]
pub documentation: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub context: Option<CodeContext>,
#[serde(skip_serializing_if = "Option::is_none")]
pub relations: Option<ExplainRelations>,
#[serde(skip_serializing_if = "Option::is_none")]
pub provenance: Option<ProvenanceData>,
}
#[derive(Debug, Clone, Serialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct DependencyGraphData {
pub nodes: Vec<NodeRefData>,
pub edges: Vec<RelationEdgeData>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rendered: Option<String>,
}
impl DependencyGraphData {
#[must_use]
pub fn empty() -> Self {
Self::default()
}
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PathStep {
pub symbol: NodeRefData,
pub edge_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<f64>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CallPath {
pub steps: Vec<PathStep>,
pub length: u32,
pub score: f64,
pub cross_language: bool,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TracePathData {
pub paths: Vec<CallPath>,
pub from_symbol: String,
pub to_symbol: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CrossLanguageEdgesData {
pub edges: Vec<RelationEdgeData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SimilarSymbolData {
pub symbol: NodeRefData,
pub similarity: f64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FindSimilarData {
pub reference: NodeRefData,
pub results: Vec<SimilarSymbolData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ImpactedSymbol {
pub symbol: NodeRefData,
pub depth: u32,
pub impact_type: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DependencyImpactData {
pub target_symbol: String,
pub impacted_symbols: Vec<ImpactedSymbol>,
#[serde(skip_serializing_if = "Option::is_none")]
pub affected_files: Option<Vec<String>>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NodeChange {
pub symbol_name: String,
pub qualified_name: String,
pub kind: String,
pub change_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub base_location: Option<NodeRefData>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target_location: Option<NodeRefData>,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature_before: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature_after: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SemanticDiffData {
pub base_ref: String,
pub target_ref: String,
pub changes: Vec<NodeChange>,
pub summary: DiffSummary,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DiffSummary {
pub added: u64,
pub removed: u64,
pub modified: u64,
pub renamed: u64,
pub signature_changed: u64,
pub unchanged: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NlDisambiguationOption {
pub command: String,
pub intent: String,
pub description: String,
pub confidence: f32,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NlTranslationData {
pub response_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub command: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub intent: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub suggestions: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub options: Vec<NlDisambiguationOption>,
#[serde(skip_serializing_if = "Option::is_none")]
pub execution_output: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DuplicateSymbolData {
pub name: String,
pub qualified_name: String,
pub kind: String,
pub file_uri: String,
pub line: u32,
pub language: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DuplicateGroupData {
pub group_id: String,
pub count: usize,
pub symbols: Vec<DuplicateSymbolData>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FindDuplicatesData {
pub duplicate_type: String,
pub threshold: u32,
pub groups: Vec<DuplicateGroupData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CycleNodeData {
pub name: String,
pub qualified_name: String,
pub file_uri: String,
pub line: u32,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CycleData {
pub depth: usize,
pub nodes: Vec<CycleNodeData>,
pub chain: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FindCyclesData {
pub cycle_type: String,
pub cycles: Vec<CycleData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UnusedSymbolData {
pub name: String,
pub qualified_name: String,
pub kind: String,
pub file_uri: String,
pub line: u32,
pub language: String,
pub visibility: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FindUnusedData {
pub scope: String,
pub symbols: Vec<UnusedSymbolData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NodeInCycleData {
pub symbol: String,
pub in_cycle: bool,
pub cycle_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub cycle: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PatternSearchData {
pub pattern: String,
pub matches: Vec<PatternMatchData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PatternMatchData {
pub name: String,
pub qualified_name: String,
pub kind: String,
pub file_uri: String,
pub line: u32,
pub language: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub provenance: Option<ProvenanceData>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DirectCallersData {
pub target: String,
pub callers: Vec<CallerCalleeData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DirectCalleesData {
pub source: String,
pub callees: Vec<CallerCalleeData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CallerCalleeData {
pub name: String,
pub qualified_name: String,
pub kind: String,
pub file_uri: String,
pub line: u32,
pub language: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FileEntryData {
pub path: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ListFilesData {
pub files: Vec<FileEntryData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SymbolEntryData {
pub name: String,
pub qualified_name: String,
pub kind: String,
pub file_path: String,
pub line: u32,
pub language: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ListSymbolsData {
pub symbols: Vec<SymbolEntryData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GraphStatsData {
pub total_nodes: u64,
pub total_edges: u64,
pub total_files: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace_nodes: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub classpath_nodes: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace_files: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub classpath_files: Option<u64>,
pub nodes_by_kind: std::collections::HashMap<String, u64>,
pub files_by_language: std::collections::HashMap<String, u64>,
pub graph_epoch: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DefinitionData {
pub name: String,
pub qualified_name: String,
pub kind: String,
pub file_path: String,
pub line: u32,
pub column: u32,
pub language: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub preview: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub macro_metadata: Option<MacroMetadataResponse>,
#[serde(skip_serializing_if = "Option::is_none")]
pub provenance: Option<ProvenanceData>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GetDefinitionData {
pub definitions: Vec<DefinitionData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ReferenceLocationData {
pub file_path: String,
pub line: u32,
pub column: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub preview: Option<String>,
pub is_declaration: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub provenance: Option<ProvenanceData>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GetReferencesData {
pub symbol: String,
pub references: Vec<ReferenceLocationData>,
pub total: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub macro_metadata: Option<MacroMetadataResponse>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HoverInfoData {
pub name: String,
pub qualified_name: String,
pub kind: String,
pub file_path: String,
pub line: u32,
pub language: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub documentation: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub provenance: Option<ProvenanceData>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentSymbolData {
pub name: String,
pub kind: String,
pub line: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_line: Option<u32>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub children: Vec<DocumentSymbolData>,
#[serde(skip_serializing_if = "Option::is_none")]
pub macro_metadata: Option<MacroMetadataResponse>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GetDocumentSymbolsData {
pub file_path: String,
pub symbols: Vec<DocumentSymbolData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceSymbolData {
pub name: String,
pub qualified_name: String,
pub kind: String,
pub file_path: String,
pub line: u32,
pub language: String,
pub score: f64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GetWorkspaceSymbolsData {
pub query: String,
pub symbols: Vec<WorkspaceSymbolData>,
pub total: u64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LanguageStatsData {
pub language: String,
pub files: usize,
pub symbols: usize,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct KindStatsData {
pub kind: String,
pub count: usize,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HealthIndicatorsData {
pub cycles: usize,
pub unused_symbols: usize,
pub duplicate_groups: usize,
pub cross_language_edges: usize,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GetInsightsData {
pub total_files: usize,
pub total_symbols: usize,
pub total_edges: usize,
pub languages: Vec<LanguageStatsData>,
pub symbol_kinds: Vec<KindStatsData>,
pub health: HealthIndicatorsData,
#[serde(skip_serializing_if = "Option::is_none")]
pub macro_boundaries: Option<MacroBoundariesStatsData>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ComplexityMetricData {
pub name: String,
pub qualified_name: String,
pub kind: String,
pub file_path: String,
pub complexity: u32,
pub lines: u32,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ComplexityMetricsData {
pub metrics: Vec<ComplexityMetricData>,
pub total: usize,
pub average_complexity: f64,
pub max_complexity: u32,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MacroMetadataResponse {
#[serde(skip_serializing_if = "Option::is_none")]
pub macro_generated: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub macro_source: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cfg_condition: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cfg_active: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub proc_macro_kind: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expansion_cached: Option<bool>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub unresolved_attributes: Vec<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MacroBoundariesStatsData {
pub attribute_macros_detected: usize,
pub cfg_gated_symbols: usize,
pub macro_generated_symbols: usize,
pub unresolved_attributes: usize,
pub expand_cache_status: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ExpandCacheStatusData {
pub cache_exists: bool,
pub cache_path: String,
pub cache_files: usize,
pub total_size_bytes: u64,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub crates: Vec<CrateCacheEntry>,
pub status: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CrateCacheEntry {
pub crate_name: String,
pub file_name: String,
pub size_bytes: u64,
pub generated_symbols: usize,
pub confidence: String,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_position_data_creation() {
let pos = PositionData {
line: 10,
character: 5,
};
assert_eq!(pos.line, 10);
assert_eq!(pos.character, 5);
}
#[test]
fn test_position_data_serialization() {
let pos = PositionData {
line: 42,
character: 15,
};
let json = serde_json::to_string(&pos).unwrap();
assert!(json.contains("\"line\":42"));
assert!(json.contains("\"character\":15"));
}
#[test]
fn test_range_data_creation() {
let range = RangeData {
start: PositionData {
line: 1,
character: 0,
},
end: PositionData {
line: 10,
character: 20,
},
};
assert_eq!(range.start.line, 1);
assert_eq!(range.end.line, 10);
}
#[test]
fn test_range_data_serialization() {
let range = RangeData {
start: PositionData {
line: 5,
character: 10,
},
end: PositionData {
line: 5,
character: 25,
},
};
let json = serde_json::to_string(&range).unwrap();
assert!(json.contains("\"start\""));
assert!(json.contains("\"end\""));
}
#[test]
fn test_code_context_creation() {
let ctx = CodeContext {
code: "fn main() {}".to_string(),
lines_before: 3,
lines_after: 3,
};
assert_eq!(ctx.code, "fn main() {}");
assert_eq!(ctx.lines_before, 3);
assert_eq!(ctx.lines_after, 3);
}
#[test]
fn test_code_context_serialization() {
let ctx = CodeContext {
code: "let x = 1;".to_string(),
lines_before: 2,
lines_after: 2,
};
let json = serde_json::to_string(&ctx).unwrap();
assert!(json.contains("\"code\""));
assert!(json.contains("\"linesBefore\""));
assert!(json.contains("\"linesAfter\""));
}
#[test]
fn test_dependency_graph_data_empty() {
let graph = DependencyGraphData::empty();
assert!(graph.nodes.is_empty());
assert!(graph.edges.is_empty());
assert!(graph.rendered.is_none());
}
#[test]
fn test_dependency_graph_data_default() {
let graph = DependencyGraphData::default();
assert!(graph.nodes.is_empty());
assert!(graph.edges.is_empty());
assert!(graph.rendered.is_none());
}
#[test]
fn test_dependency_graph_data_serialization_empty() {
let graph = DependencyGraphData::empty();
let json = serde_json::to_string(&graph).unwrap();
assert!(json.contains("\"nodes\":[]"));
assert!(json.contains("\"edges\":[]"));
assert!(!json.contains("\"rendered\""));
}
#[test]
fn test_search_hit_relations_default() {
let relations = SearchHitRelations::default();
assert!(relations.callers.is_empty());
assert!(relations.callees.is_empty());
}
#[test]
fn test_search_hit_relations_serialization_empty() {
let relations = SearchHitRelations::default();
let json = serde_json::to_string(&relations).unwrap();
assert_eq!(json, "{}");
}
#[test]
fn test_diff_summary_creation() {
let summary = DiffSummary {
added: 10,
removed: 5,
modified: 3,
renamed: 1,
signature_changed: 2,
unchanged: 100,
};
assert_eq!(summary.added, 10);
assert_eq!(summary.removed, 5);
assert_eq!(summary.modified, 3);
assert_eq!(summary.renamed, 1);
assert_eq!(summary.signature_changed, 2);
assert_eq!(summary.unchanged, 100);
}
#[test]
fn test_diff_summary_serialization() {
let summary = DiffSummary {
added: 1,
removed: 2,
modified: 3,
renamed: 0,
signature_changed: 1,
unchanged: 50,
};
let json = serde_json::to_string(&summary).unwrap();
assert!(json.contains("\"added\":1"));
assert!(json.contains("\"removed\":2"));
assert!(json.contains("\"signatureChanged\":1"));
}
#[test]
#[allow(clippy::float_cmp)] fn test_nl_disambiguation_option_creation() {
let option = NlDisambiguationOption {
command: "query kind:function".to_string(),
intent: "search".to_string(),
description: "Search for functions".to_string(),
confidence: 0.85,
};
assert_eq!(option.command, "query kind:function");
assert_eq!(option.intent, "search");
assert_eq!(option.confidence, 0.85);
}
#[test]
fn test_nl_disambiguation_option_serialization() {
let option = NlDisambiguationOption {
command: "test".to_string(),
intent: "execute".to_string(),
description: "Run tests".to_string(),
confidence: 0.9,
};
let json = serde_json::to_string(&option).unwrap();
assert!(json.contains("\"command\":\"test\""));
assert!(json.contains("\"confidence\":0.9"));
}
#[test]
fn test_nl_translation_data_execute() {
let data = NlTranslationData {
response_type: "execute".to_string(),
command: Some("query kind:function".to_string()),
confidence: Some(0.95),
intent: Some("search".to_string()),
prompt: None,
reason: None,
suggestions: vec![],
options: vec![],
execution_output: None,
};
assert_eq!(data.response_type, "execute");
assert!(data.command.is_some());
}
#[test]
fn test_nl_translation_data_reject() {
let data = NlTranslationData {
response_type: "reject".to_string(),
command: None,
confidence: None,
intent: None,
prompt: None,
reason: Some("Query too vague".to_string()),
suggestions: vec!["Be more specific".to_string()],
options: vec![],
execution_output: None,
};
assert_eq!(data.response_type, "reject");
assert_eq!(data.reason, Some("Query too vague".to_string()));
}
#[test]
fn test_nl_translation_data_serialization_skips_none() {
let data = NlTranslationData {
response_type: "execute".to_string(),
command: Some("test".to_string()),
confidence: None,
intent: None,
prompt: None,
reason: None,
suggestions: vec![],
options: vec![],
execution_output: None,
};
let json = serde_json::to_string(&data).unwrap();
assert!(!json.contains("\"confidence\""));
assert!(!json.contains("\"suggestions\""));
}
#[test]
#[allow(clippy::float_cmp)] fn test_call_path_creation() {
let path = CallPath {
steps: vec![],
length: 3,
score: 0.85,
cross_language: false,
};
assert_eq!(path.length, 3);
assert_eq!(path.score, 0.85);
assert!(!path.cross_language);
}
#[test]
fn test_call_path_cross_language() {
let path = CallPath {
steps: vec![],
length: 5,
score: 0.7,
cross_language: true,
};
assert!(path.cross_language);
}
#[test]
fn test_impacted_symbol_creation() {
let symbol = ImpactedSymbol {
symbol: NodeRefData {
name: "test_fn".to_string(),
qualified_name: "module::test_fn".to_string(),
kind: "function".to_string(),
language: "rust".to_string(),
file_uri: "file:///test.rs".to_string(),
range: RangeData {
start: PositionData {
line: 1,
character: 0,
},
end: PositionData {
line: 5,
character: 1,
},
},
metadata: None,
},
depth: 2,
impact_type: "caller".to_string(),
};
assert_eq!(symbol.depth, 2);
assert_eq!(symbol.impact_type, "caller");
}
#[test]
fn test_graph_metadata_creation() {
let metadata = GraphMetadata {
total_nodes: 1000,
total_edges: 5000,
languages: vec!["rust".to_string(), "python".to_string()],
cross_language_edges: 50,
graph_version: "2.0.0".to_string(),
#[allow(clippy::unreadable_literal)] rebuild_epoch_ms: 1704067200000,
cache: None,
confidence: std::collections::HashMap::new(),
};
assert_eq!(metadata.total_nodes, 1000);
assert_eq!(metadata.total_edges, 5000);
assert_eq!(metadata.languages.len(), 2);
}
#[test]
fn test_graph_metadata_serialization() {
let metadata = GraphMetadata {
total_nodes: 100,
total_edges: 200,
languages: vec![],
cross_language_edges: 0,
graph_version: "1.0.0".to_string(),
rebuild_epoch_ms: 0,
cache: None,
confidence: std::collections::HashMap::new(),
};
let json = serde_json::to_string(&metadata).unwrap();
assert!(json.contains("\"totalNodes\":100"));
assert!(json.contains("\"graphVersion\":\"1.0.0\""));
assert!(!json.contains("\"languages\""));
assert!(!json.contains("\"confidence\""));
}
#[test]
fn test_graph_metadata_with_confidence() {
use sqry_core::confidence::{ConfidenceLevel, ConfidenceMetadata};
let mut confidence = std::collections::HashMap::new();
confidence.insert(
"rust".to_string(),
ConfidenceMetadata {
level: ConfidenceLevel::AstOnly,
limitations: vec!["No type inference".to_string()],
unavailable_features: vec!["rust-analyzer".to_string()],
},
);
let metadata = GraphMetadata {
total_nodes: 100,
total_edges: 200,
languages: vec!["rust".to_string()],
cross_language_edges: 0,
graph_version: "2.8.0".to_string(),
rebuild_epoch_ms: 0,
cache: None,
confidence,
};
let json = serde_json::to_string(&metadata).unwrap();
assert!(json.contains("\"confidence\""), "confidence field missing");
assert!(json.contains("\"rust\""), "rust language key missing");
assert!(json.contains("\"level\""), "level field missing");
assert!(
json.contains("\"ast_only\""),
"ast_only value missing in: {json}"
);
assert!(json.contains("\"No type inference\""), "limitation missing");
}
#[test]
fn test_index_status_data_no_index() {
let status = IndexStatusData {
has_index: false,
root_path: None,
indexed_symbols: None,
files_indexed: None,
index_version: None,
created_at: None,
updated_at: None,
has_relations: None,
};
assert!(!status.has_index);
}
#[test]
fn test_index_status_data_with_index() {
let status = IndexStatusData {
has_index: true,
root_path: Some("/project".to_string()),
indexed_symbols: Some(5000),
files_indexed: Some(100),
index_version: Some("2.0.0".to_string()),
created_at: Some("2024-01-01T00:00:00Z".to_string()),
updated_at: Some("2024-01-02T00:00:00Z".to_string()),
has_relations: Some(true),
};
assert!(status.has_index);
assert_eq!(status.indexed_symbols, Some(5000));
}
#[test]
fn test_macro_metadata_response_serialization_skips_empty_fields() {
let response = MacroMetadataResponse {
macro_generated: Some(true),
macro_source: None,
cfg_condition: None,
cfg_active: None,
proc_macro_kind: None,
expansion_cached: None,
unresolved_attributes: vec![],
};
let json = serde_json::to_value(&response).unwrap();
assert_eq!(json.get("macroGenerated").unwrap(), true);
assert!(json.get("macroSource").is_none());
assert!(json.get("cfgCondition").is_none());
assert!(json.get("unresolvedAttributes").is_none());
}
#[test]
fn test_macro_metadata_response_full_serialization() {
let response = MacroMetadataResponse {
macro_generated: Some(true),
macro_source: Some("derive_Debug".to_string()),
cfg_condition: Some("test".to_string()),
cfg_active: Some(true),
proc_macro_kind: Some("derive".to_string()),
expansion_cached: Some(false),
unresolved_attributes: vec!["custom_attr".to_string()],
};
let json = serde_json::to_value(&response).unwrap();
assert_eq!(json.get("macroGenerated").unwrap(), true);
assert_eq!(json.get("macroSource").unwrap(), "derive_Debug");
assert_eq!(json.get("cfgCondition").unwrap(), "test");
assert_eq!(json.get("cfgActive").unwrap(), true);
assert_eq!(json.get("procMacroKind").unwrap(), "derive");
assert_eq!(json.get("expansionCached").unwrap(), false);
let attrs = json
.get("unresolvedAttributes")
.unwrap()
.as_array()
.unwrap();
assert_eq!(attrs.len(), 1);
assert_eq!(attrs[0], "custom_attr");
}
#[test]
fn test_macro_boundaries_stats_data_serialization() {
let stats = MacroBoundariesStatsData {
attribute_macros_detected: 5,
cfg_gated_symbols: 3,
macro_generated_symbols: 10,
unresolved_attributes: 2,
expand_cache_status: "fresh".to_string(),
};
let json = serde_json::to_value(&stats).unwrap();
assert_eq!(json.get("attributeMacrosDetected").unwrap(), 5);
assert_eq!(json.get("cfgGatedSymbols").unwrap(), 3);
assert_eq!(json.get("macroGeneratedSymbols").unwrap(), 10);
assert_eq!(json.get("unresolvedAttributes").unwrap(), 2);
assert_eq!(json.get("expandCacheStatus").unwrap(), "fresh");
}
#[test]
fn test_expand_cache_status_data_serialization() {
let data = ExpandCacheStatusData {
cache_exists: true,
cache_path: ".sqry/expand-cache".to_string(),
cache_files: 2,
total_size_bytes: 4096,
crates: vec![CrateCacheEntry {
crate_name: "my_crate".to_string(),
file_name: "my_crate.json".to_string(),
size_bytes: 2048,
generated_symbols: 5,
confidence: "heuristic".to_string(),
}],
status: "fresh".to_string(),
};
let json = serde_json::to_value(&data).unwrap();
assert_eq!(json.get("cacheExists").unwrap(), true);
assert_eq!(json.get("cacheFiles").unwrap(), 2);
assert_eq!(json.get("status").unwrap(), "fresh");
let crates = json.get("crates").unwrap().as_array().unwrap();
assert_eq!(crates.len(), 1);
assert_eq!(crates[0].get("crateName").unwrap(), "my_crate");
assert_eq!(crates[0].get("generatedSymbols").unwrap(), 5);
}
#[test]
fn test_expand_cache_status_data_empty_crates_skipped() {
let data = ExpandCacheStatusData {
cache_exists: false,
cache_path: ".sqry/expand-cache".to_string(),
cache_files: 0,
total_size_bytes: 0,
crates: vec![],
status: "absent".to_string(),
};
let json = serde_json::to_value(&data).unwrap();
assert!(json.get("crates").is_none());
assert_eq!(json.get("status").unwrap(), "absent");
}
#[test]
fn test_definition_data_with_macro_metadata() {
let def = DefinitionData {
name: "my_fn".to_string(),
qualified_name: "crate::my_fn".to_string(),
kind: "Function".to_string(),
file_path: "src/lib.rs".to_string(),
line: 10,
column: 1,
language: "rust".to_string(),
preview: None,
macro_metadata: Some(MacroMetadataResponse {
macro_generated: Some(true),
macro_source: Some("derive_Debug".to_string()),
cfg_condition: None,
cfg_active: None,
proc_macro_kind: None,
expansion_cached: None,
unresolved_attributes: vec![],
}),
provenance: None,
};
let json = serde_json::to_value(&def).unwrap();
let mm = json.get("macroMetadata").unwrap();
assert_eq!(mm.get("macroGenerated").unwrap(), true);
assert_eq!(mm.get("macroSource").unwrap(), "derive_Debug");
}
#[test]
fn test_definition_data_without_macro_metadata() {
let def = DefinitionData {
name: "my_fn".to_string(),
qualified_name: "crate::my_fn".to_string(),
kind: "Function".to_string(),
file_path: "src/lib.rs".to_string(),
line: 10,
column: 1,
language: "rust".to_string(),
preview: None,
macro_metadata: None,
provenance: None,
};
let json = serde_json::to_value(&def).unwrap();
assert!(json.get("macroMetadata").is_none());
}
#[test]
fn test_get_insights_data_with_macro_boundaries() {
let data = GetInsightsData {
total_files: 10,
total_symbols: 100,
total_edges: 50,
languages: vec![],
symbol_kinds: vec![],
health: HealthIndicatorsData {
cycles: 0,
unused_symbols: 5,
duplicate_groups: 2,
cross_language_edges: 0,
},
macro_boundaries: Some(MacroBoundariesStatsData {
attribute_macros_detected: 3,
cfg_gated_symbols: 7,
macro_generated_symbols: 12,
unresolved_attributes: 1,
expand_cache_status: "stale".to_string(),
}),
};
let json = serde_json::to_value(&data).unwrap();
let mb = json.get("macroBoundaries").unwrap();
assert_eq!(mb.get("attributeMacrosDetected").unwrap(), 3);
assert_eq!(mb.get("expandCacheStatus").unwrap(), "stale");
}
#[test]
fn test_get_insights_data_without_macro_boundaries() {
let data = GetInsightsData {
total_files: 10,
total_symbols: 100,
total_edges: 50,
languages: vec![],
symbol_kinds: vec![],
health: HealthIndicatorsData {
cycles: 0,
unused_symbols: 0,
duplicate_groups: 0,
cross_language_edges: 0,
},
macro_boundaries: None,
};
let json = serde_json::to_value(&data).unwrap();
assert!(json.get("macroBoundaries").is_none());
}
}