use crate::intent::Goal;
use ryo_analysis::SymbolKind;
use ryo_suggest::EnhancedSuggestion;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
pub use ryo_query_language::{QueryResponse, ViewMode};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum StatusCode {
Ok,
NoChange,
Resolved,
Invalid,
NotFound,
Conflict,
SyntaxError,
}
impl StatusCode {
pub fn is_success(&self) -> bool {
matches!(self, Self::Ok | Self::NoChange | Self::Resolved)
}
pub fn is_error(&self) -> bool {
!self.is_success()
}
pub fn as_http_code(&self) -> u16 {
match self {
Self::Ok => 200,
Self::NoChange => 204,
Self::Resolved => 206,
Self::Invalid => 400,
Self::NotFound => 404,
Self::Conflict => 409,
Self::SyntaxError => 422,
}
}
pub fn label(&self) -> &'static str {
match self {
Self::Ok => "OK",
Self::NoChange => "NO_CHANGE",
Self::Resolved => "RESOLVED",
Self::Invalid => "INVALID",
Self::NotFound => "NOT_FOUND",
Self::Conflict => "CONFLICT",
Self::SyntaxError => "SYNTAX_ERROR",
}
}
}
impl std::fmt::Display for StatusCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.label())
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct StatusDetail {
pub reason: String,
pub explanation: Option<String>,
pub suggestions: Vec<String>,
pub context: Vec<String>,
}
impl StatusDetail {
pub fn new(reason: impl Into<String>) -> Self {
Self {
reason: reason.into(),
..Default::default()
}
}
pub fn with_explanation(mut self, explanation: impl Into<String>) -> Self {
self.explanation = Some(explanation.into());
self
}
pub fn with_suggestion(mut self, suggestion: impl Into<String>) -> Self {
self.suggestions.push(suggestion.into());
self
}
pub fn with_suggestions(
mut self,
suggestions: impl IntoIterator<Item = impl Into<String>>,
) -> Self {
self.suggestions
.extend(suggestions.into_iter().map(Into::into));
self
}
pub fn with_context(mut self, context: impl Into<String>) -> Self {
self.context.push(context.into());
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutionStatus {
pub code: StatusCode,
pub detail: StatusDetail,
}
impl ExecutionStatus {
pub fn new(code: StatusCode, detail: StatusDetail) -> Self {
Self { code, detail }
}
pub fn ok(reason: impl Into<String>) -> Self {
Self::new(StatusCode::Ok, StatusDetail::new(reason))
}
pub fn no_change(reason: impl Into<String>) -> Self {
Self::new(StatusCode::NoChange, StatusDetail::new(reason))
}
pub fn resolved(reason: impl Into<String>) -> Self {
Self::new(StatusCode::Resolved, StatusDetail::new(reason))
}
pub fn invalid(reason: impl Into<String>) -> Self {
Self::new(StatusCode::Invalid, StatusDetail::new(reason))
}
pub fn not_found(reason: impl Into<String>) -> Self {
Self::new(StatusCode::NotFound, StatusDetail::new(reason))
}
pub fn conflict(reason: impl Into<String>) -> Self {
Self::new(StatusCode::Conflict, StatusDetail::new(reason))
}
pub fn syntax_error(reason: impl Into<String>) -> Self {
Self::new(StatusCode::SyntaxError, StatusDetail::new(reason))
}
pub fn with_explanation(mut self, explanation: impl Into<String>) -> Self {
self.detail.explanation = Some(explanation.into());
self
}
pub fn with_suggestion(mut self, suggestion: impl Into<String>) -> Self {
self.detail.suggestions.push(suggestion.into());
self
}
pub fn with_suggestions(
mut self,
suggestions: impl IntoIterator<Item = impl Into<String>>,
) -> Self {
self.detail
.suggestions
.extend(suggestions.into_iter().map(Into::into));
self
}
pub fn with_context(mut self, context: impl Into<String>) -> Self {
self.detail.context.push(context.into());
self
}
pub fn is_success(&self) -> bool {
self.code.is_success()
}
pub fn is_error(&self) -> bool {
self.code.is_error()
}
}
impl std::fmt::Display for ExecutionStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.code, self.detail.reason)
}
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
pub enum SortOrder {
Alpha,
#[default]
Refs,
Impls,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiscoverRequest {
pub pattern: String,
pub kind: Option<SymbolKind>,
pub sort: Option<SortOrder>,
pub limit: Option<usize>,
#[serde(default)]
pub view: Option<ViewMode>,
#[serde(default)]
pub is_async: Option<bool>,
#[serde(default)]
pub is_unsafe: Option<bool>,
#[serde(default)]
pub scope_path: Option<String>,
#[serde(default)]
pub ignore_case: bool,
#[serde(default)]
pub ignore_word_separate: bool,
#[serde(default)]
pub attr: Option<String>,
#[serde(default)]
pub is_id: bool,
}
impl Default for DiscoverRequest {
fn default() -> Self {
Self {
pattern: "*".to_string(),
kind: None,
sort: None,
limit: None,
view: None,
is_async: None,
is_unsafe: None,
scope_path: None,
ignore_case: false,
ignore_word_separate: false,
attr: None,
is_id: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiscoveredSymbol {
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uuid: Option<String>,
pub path: String,
pub name: String,
pub kind: String,
pub view_mode: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub definition: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub doc: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub body: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub snippet: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiscoverResponse {
pub status: String,
pub symbols: Vec<DiscoveredSymbol>,
pub total: usize,
pub elapsed_ms: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hint: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct OverviewRequest {}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrateOverview {
pub name: String,
pub modules: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OverviewSymbol {
pub path: String,
pub count: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OverviewStats {
pub crate_count: usize,
pub by_kind: Vec<(String, usize)>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OverviewResponse {
pub crates: Vec<CrateOverview>,
pub top_structs: Vec<OverviewSymbol>,
pub top_traits: Vec<OverviewSymbol>,
pub stats: OverviewStats,
pub elapsed_ms: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LiteralSearchRequest {
pub pattern: String,
#[serde(default)]
pub kind: Option<String>,
#[serde(default = "default_literal_limit")]
pub limit: usize,
}
fn default_literal_limit() -> usize {
100
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LiteralMatchResult {
pub value: String,
pub kind: String,
pub symbol_id: String,
pub file_path: String,
pub score: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LiteralSearchResponse {
pub matches: Vec<LiteralMatchResult>,
pub total: usize,
pub elapsed_ms: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RyoqlRequest {
pub query: String,
#[serde(default)]
pub default_view: Option<ViewMode>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SuggestRequest {
pub pattern_filter: Option<String>,
pub high_impact: bool,
pub quick: bool,
pub scan: bool,
#[serde(default)]
pub precheck: bool,
#[serde(default)]
pub exclude_rules: Vec<String>,
#[serde(default)]
pub enhanced: bool,
#[serde(default)]
pub scope_filter: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Suggestion {
pub id: String,
pub rule_id: Option<String>,
pub title: String,
pub description: String,
pub category: String,
pub impact: String,
pub file: PathBuf,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub symbol_path: Option<String>,
pub fix_intent: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SuggestionSummary {
pub total: usize,
pub high_impact: usize,
pub by_category: Vec<(String, usize)>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SuggestResponse {
pub suggestions: Vec<Suggestion>,
pub summary: SuggestionSummary,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub enhanced: Vec<EnhancedSuggestion>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SuggestApplyRequest {
pub ids: Vec<String>,
pub dry_run: bool,
pub check_syntax: bool,
#[serde(default)]
pub choice_id: Option<String>,
#[serde(default)]
pub verify: bool,
}
impl SuggestApplyRequest {
pub fn new(ids: Vec<String>) -> Self {
Self {
ids,
dry_run: false,
check_syntax: false,
choice_id: None,
verify: false,
}
}
pub fn dry_run(mut self) -> Self {
self.dry_run = true;
self
}
pub fn check_syntax(mut self) -> Self {
self.check_syntax = true;
self
}
pub fn choice(mut self, choice_id: impl Into<String>) -> Self {
self.choice_id = Some(choice_id.into());
self
}
pub fn verify(mut self) -> Self {
self.verify = true;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SuggestApplyResponse {
pub success: bool,
pub files_modified: usize,
pub total_changes: usize,
pub modified_files: Vec<PathBuf>,
pub applied_ids: Vec<String>,
pub failed: Vec<(String, String)>,
pub syntax_errors: Vec<String>,
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SuggestChoicesRequest {
pub id: String,
}
impl SuggestChoicesRequest {
pub fn new(id: impl Into<String>) -> Self {
Self { id: id.into() }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DesignChoiceInfo {
pub id: String,
pub label: String,
pub title: String,
pub description: String,
pub extensibility: u8,
pub performance: u8,
pub complexity: u8,
pub breaking_change: bool,
pub affected_files: usize,
pub recommended: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SuggestChoicesResponse {
pub suggestion_id: String,
pub pattern_name: String,
pub choices: Vec<DesignChoiceInfo>,
pub has_choices: bool,
pub error: Option<String>,
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
pub enum VerifyLevel {
#[default]
Light,
Full,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SuggestVerifyRequest {
pub id: String,
#[serde(default)]
pub choice_id: Option<String>,
#[serde(default)]
pub level: VerifyLevel,
}
impl SuggestVerifyRequest {
pub fn new(id: impl Into<String>) -> Self {
Self {
id: id.into(),
choice_id: None,
level: VerifyLevel::default(),
}
}
pub fn choice(mut self, choice_id: impl Into<String>) -> Self {
self.choice_id = Some(choice_id.into());
self
}
pub fn level(mut self, level: VerifyLevel) -> Self {
self.level = level;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SuggestVerifyResponse {
pub suggestion_id: String,
pub choice_id: Option<String>,
pub passed: bool,
pub level: String,
pub duration_ms: u64,
pub diagnostics: Vec<String>,
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SuggestCompareRequest {
pub id: String,
}
impl SuggestCompareRequest {
pub fn new(id: impl Into<String>) -> Self {
Self { id: id.into() }
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SuggestCompareResponse {
pub suggestion_id: String,
pub comparison_table: String,
pub ranked_choices: Vec<DesignChoiceInfo>,
pub recommendation_reason: Option<String>,
pub error: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SuggestGenerateRequest {
pub pattern: Option<String>,
#[serde(default)]
pub params: std::collections::HashMap<String, String>,
#[serde(default)]
pub list: bool,
#[serde(default)]
pub apply: bool,
#[serde(default)]
pub dry_run: bool,
}
impl SuggestGenerateRequest {
pub fn list_patterns() -> Self {
Self {
list: true,
..Default::default()
}
}
pub fn generate(pattern: impl Into<String>) -> Self {
Self {
pattern: Some(pattern.into()),
..Default::default()
}
}
pub fn with_param(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.params.insert(key.into(), value.into());
self
}
pub fn apply(mut self) -> Self {
self.apply = true;
self
}
pub fn dry_run(mut self) -> Self {
self.dry_run = true;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PatternInfo {
pub name: String,
pub description: String,
pub category: String,
pub params: Vec<ParamInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ParamInfo {
pub name: String,
pub description: String,
pub required: bool,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SuggestGenerateResponse {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub patterns: Vec<PatternInfo>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub suggestions: Vec<Suggestion>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub preview: Option<String>,
#[serde(default)]
pub applied: bool,
#[serde(default)]
pub files_modified: usize,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RunRequest {
pub goal: Goal,
pub dry_run: bool,
pub check_syntax: bool,
}
impl RunRequest {
pub fn new(goal: Goal) -> Self {
Self {
goal,
dry_run: false,
check_syntax: false,
}
}
pub fn dry_run(mut self) -> Self {
self.dry_run = true;
self
}
pub fn check_syntax(mut self) -> Self {
self.check_syntax = true;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct RunResponse {
pub success: bool,
pub files_modified: usize,
pub total_changes: usize,
pub modified_files: Vec<PathBuf>,
pub conflicts: Vec<String>,
pub syntax_errors: Vec<String>,
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CascadeRequest {
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uuid: Option<String>,
pub depth: Option<usize>,
}
impl CascadeRequest {
pub fn new(id: impl Into<String>) -> Self {
Self {
id: id.into(),
uuid: None,
depth: None,
}
}
pub fn with_uuid(uuid: impl Into<String>) -> Self {
Self {
id: String::new(),
uuid: Some(uuid.into()),
depth: None,
}
}
pub fn depth(mut self, depth: usize) -> Self {
self.depth = Some(depth);
self
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CascadeResponse {
pub display_name: String,
pub callers: Vec<String>,
pub users: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub match_functions: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub containing_types: Vec<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct GraphSummaryRequest {
#[serde(default)]
pub detailed: bool,
#[serde(default)]
pub compact: bool,
#[serde(default)]
pub max_items: Option<usize>,
}
impl GraphSummaryRequest {
pub fn new() -> Self {
Self::default()
}
pub fn detailed(mut self) -> Self {
self.detailed = true;
self
}
pub fn compact(mut self) -> Self {
self.compact = true;
self
}
pub fn max_items(mut self, n: usize) -> Self {
self.max_items = Some(n);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GraphSummaryResponse {
pub content: String,
pub build_time_ms: u64,
pub node_count: usize,
pub edge_count: usize,
pub file_count: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PingResponse {
pub version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatusResponse {
pub project: PathBuf,
pub symbols: usize,
pub files: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ApiErrorKind {
NotFound { name: String },
ParseError { message: String },
InvalidRequest { message: String },
Internal { message: String },
}
impl std::fmt::Display for ApiErrorKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NotFound { name } => write!(f, "not found: {}", name),
Self::ParseError { message } => write!(f, "parse error: {}", message),
Self::InvalidRequest { message } => write!(f, "invalid request: {}", message),
Self::Internal { message } => write!(f, "internal error: {}", message),
}
}
}
impl std::error::Error for ApiErrorKind {}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpecRequest {
pub query: SpecQueryKind,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SpecQueryKind {
Show,
Groups,
TypesInGroup { group: String },
Dependencies { type_name: String },
Dependents { type_name: String },
Stats,
Lint,
Mermaid,
}
impl SpecRequest {
pub fn show() -> Self {
Self {
query: SpecQueryKind::Show,
}
}
pub fn groups() -> Self {
Self {
query: SpecQueryKind::Groups,
}
}
pub fn types_in_group(group: impl Into<String>) -> Self {
Self {
query: SpecQueryKind::TypesInGroup {
group: group.into(),
},
}
}
pub fn stats() -> Self {
Self {
query: SpecQueryKind::Stats,
}
}
pub fn lint() -> Self {
Self {
query: SpecQueryKind::Lint,
}
}
pub fn mermaid() -> Self {
Self {
query: SpecQueryKind::Mermaid,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SpecResponse {
Show(SpecShowData),
Groups(Vec<String>),
TypesInGroup(Vec<SpecInfoData>),
Dependencies(Vec<String>),
Dependents(Vec<String>),
Stats(SpecStatsData),
Lint(SpecLintData),
Mermaid(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpecShowData {
pub groups: Vec<SpecGroupData>,
pub relations: Vec<SpecRelationData>,
pub stats: SpecStatsData,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpecGroupData {
pub name: String,
pub specs: Vec<SpecInfoData>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpecInfoData {
pub alias_name: String,
pub wrapped_type_name: String,
pub source: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpecRelationData {
pub from: String,
pub to: String,
pub kind: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpecStatsData {
pub groups: usize,
pub specs: usize,
pub nodes: usize,
pub edges: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpecLintData {
pub issues: Vec<SpecLintIssueData>,
pub warnings: usize,
pub errors: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpecLintIssueData {
pub severity: String,
pub message: String,
pub location: Option<String>,
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
pub enum TypeAnalysisMode {
Definition,
Usage,
#[default]
Impact,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeAnalysisRequest {
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uuid: Option<String>,
#[serde(default)]
pub mode: TypeAnalysisMode,
#[serde(default)]
pub depth: Option<usize>,
}
impl TypeAnalysisRequest {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: Some(name.into()),
id: None,
uuid: None,
mode: TypeAnalysisMode::default(),
depth: None,
}
}
pub fn with_id(id: impl Into<String>) -> Self {
Self {
name: None,
id: Some(id.into()),
uuid: None,
mode: TypeAnalysisMode::default(),
depth: None,
}
}
pub fn with_uuid(uuid: impl Into<String>) -> Self {
Self {
name: None,
id: None,
uuid: Some(uuid.into()),
mode: TypeAnalysisMode::default(),
depth: None,
}
}
pub fn mode(mut self, mode: TypeAnalysisMode) -> Self {
self.mode = mode;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeAnalysisResponse {
pub symbol_id: String,
pub display_name: String,
pub mod_path: Option<String>,
pub kind: Option<String>,
pub usage_count: usize,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub usages: Vec<TypeUsageInfo>,
pub impact: Option<TypeImpactInfo>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub supertraits: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub implementors: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub fields: Vec<TypeFieldInfo>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub variants: Vec<TypeVariantInfo>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub params: Vec<TypeParamInfo>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub return_type: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub methods: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub generics: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub attrs: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeFieldInfo {
pub name: String,
pub ty: String,
pub is_public: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeVariantInfo {
pub name: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub fields: Vec<TypeFieldInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeParamInfo {
pub name: String,
pub ty: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeUsageInfo {
pub context: String,
pub ref_kind: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub container: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeImpactInfo {
pub direct_usages: usize,
pub bound_usages: usize,
pub containing_types: Vec<String>,
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
pub enum FlowAnalysisMode {
Provenance,
Impact,
#[default]
Chain,
Sources,
Sinks,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FlowAnalysisRequest {
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uuid: Option<String>,
#[serde(default)]
pub mode: FlowAnalysisMode,
#[serde(default)]
pub depth: Option<usize>,
}
impl FlowAnalysisRequest {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: Some(name.into()),
id: None,
uuid: None,
mode: FlowAnalysisMode::default(),
depth: None,
}
}
pub fn with_id(id: impl Into<String>) -> Self {
Self {
name: None,
id: Some(id.into()),
uuid: None,
mode: FlowAnalysisMode::default(),
depth: None,
}
}
pub fn with_uuid(uuid: impl Into<String>) -> Self {
Self {
name: None,
id: None,
uuid: Some(uuid.into()),
mode: FlowAnalysisMode::default(),
depth: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VarInfo {
pub name: String,
pub kind: String,
pub parent: String,
pub symbol_path: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FlowAnalysisResponse {
pub display_name: String,
pub found_vars: Vec<VarInfo>,
pub provenance: Vec<VarInfo>,
pub impact: Vec<VarInfo>,
pub sources: Vec<VarInfo>,
pub sinks: Vec<VarInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BorrowAnalysisRequest {
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uuid: Option<String>,
#[serde(default)]
pub conflicts_only: bool,
}
impl BorrowAnalysisRequest {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: Some(name.into()),
id: None,
uuid: None,
conflicts_only: false,
}
}
pub fn with_id(id: impl Into<String>) -> Self {
Self {
name: None,
id: Some(id.into()),
uuid: None,
conflicts_only: false,
}
}
pub fn with_uuid(uuid: impl Into<String>) -> Self {
Self {
name: None,
id: None,
uuid: Some(uuid.into()),
conflicts_only: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BorrowStatus {
pub var_name: String,
pub line: u32,
pub parent_info: String,
pub has_conflict: bool,
pub errors: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BorrowAnalysisResponse {
pub display_name: String,
pub found_count: usize,
pub statuses: Vec<BorrowStatus>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LockAnalysisRequest {
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uuid: Option<String>,
#[serde(default)]
pub suggest: bool,
}
impl LockAnalysisRequest {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: Some(name.into()),
id: None,
uuid: None,
suggest: false,
}
}
pub fn with_id(id: impl Into<String>) -> Self {
Self {
name: None,
id: Some(id.into()),
uuid: None,
suggest: false,
}
}
pub fn with_uuid(uuid: impl Into<String>) -> Self {
Self {
name: None,
id: None,
uuid: Some(uuid.into()),
suggest: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LockStats {
pub total_locks: u32,
pub mutex_count: u32,
pub rwlock_count: u32,
pub refcell_count: u32,
pub total_field_accesses: u32,
pub max_cs_span: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LockAcquisition {
pub lock_name: String,
pub lock_type: String,
pub line: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LockSuggestionInfo {
pub kind: String,
pub target: String,
pub description: String,
pub line: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LockAnalysisResponse {
pub display_name: String,
pub stats: LockStats,
pub acquisitions: Vec<LockAcquisition>,
pub suggestions: Vec<LockSuggestionInfo>,
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
pub enum ChainMode {
#[default]
Callers,
Callees,
TypeUsers,
TypeDeps,
}
impl std::fmt::Display for ChainMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ChainMode::Callers => write!(f, "callers"),
ChainMode::Callees => write!(f, "callees"),
ChainMode::TypeUsers => write!(f, "type_users"),
ChainMode::TypeDeps => write!(f, "type_deps"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChainAnalysisRequest {
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uuid: Option<String>,
#[serde(default)]
pub mode: ChainMode,
#[serde(default)]
pub depth: Option<usize>,
}
impl ChainAnalysisRequest {
pub fn new(id: impl Into<String>) -> Self {
Self {
id: id.into(),
uuid: None,
mode: ChainMode::default(),
depth: None,
}
}
pub fn with_uuid(uuid: impl Into<String>) -> Self {
Self {
id: String::new(),
uuid: Some(uuid.into()),
mode: ChainMode::default(),
depth: None,
}
}
pub fn mode(mut self, mode: ChainMode) -> Self {
self.mode = mode;
self
}
pub fn depth(mut self, depth: usize) -> Self {
self.depth = Some(depth);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChainNodeInfo {
pub id: String,
pub path: String,
pub kind: Option<String>,
pub depth: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ChainAnalysisResponse {
pub display_name: String,
pub direction: String,
pub total_count: usize,
pub max_actual_depth: usize,
pub by_depth: std::collections::BTreeMap<usize, Vec<ChainNodeInfo>>,
}