From 6722b25632866d740c1297277523acb86f2f05a7 Mon Sep 17 00:00:00 2001 From: Kadir Mert Okumus Date: Sat, 24 Oct 2026 03:05:53 +0300 Subject: [PATCH] Fold the traverse::search arguments into a TraverseRequest traverse::search took eight arguments under #[allow(clippy::too_many_arguments)]. The per-call ones (workspace path, query, top_k, budget, steer, handle, profile) now travel in a borrowed TraverseRequest; app stays separate. The function destructures it at the top, so the body is unchanged, and the allow is gone. The two callers (the MCP search_code handler and a navigation-barrier test) build plain struct literals. Error messages, output and the MCP schema are untouched. Evidence: traverse_matrix 18/18 (goldens untouched), mcp:: 35/35, navigation_barrier:: 7/7; clippy --workspace --all-targets -D warnings clean; fmt clean. Co-Authored-By: Claude Opus 5.5 --- src/app/traverse/mod.rs | 44 +++++++++++++++++++++++-------- src/server.rs | 16 ++++++----- tests/cases/navigation_barrier.rs | 19 +++++++------ 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/src/app/traverse/mod.rs b/src/app/traverse/mod.rs index d296c367..319d0721 100644 --- a/src/app/traverse/mod.rs +++ b/src/app/traverse/mod.rs @@ -1516,23 +1516,45 @@ async fn finish( }) } +/// The per-call arguments of [`search`] (`search_code` with +/// `mode = "traverse"`): what the caller of the tool supplies, and the +/// endpoint's retriever profile. +#[derive(Debug, Clone, Copy)] +pub struct TraverseRequest<'a> { + /// The workspace to walk, as the caller wrote it; it must be a directory. + pub workspace_path: &'a str, + /// The question: the start nodes come from the hybrid search for it (or + /// the name-matching stand-in when that search finds nothing). + pub query: &'a str, + /// How many results to return, 1 through 40; `None` takes `default_top_k`. + pub top_k: Option, + /// Limits of this walk; `None` takes the defaults. + pub budget: Option<&'a BudgetArgs>, + /// Rules and actions for this walk; `None` takes none. + pub steer: Option<&'a SteerArgs>, + /// The handle of an earlier walk to continue; `None` starts a new one. + pub handle: Option<&'a str>, + /// The endpoint's `[search_profiles]` entry whose retrievers find the + /// start nodes; `None` takes the default retrievers. + pub profile: Option<&'a str>, +} + /// `search_code` with `mode = "traverse"`: the workspace's SCIP index /// (`traverse.scip_index`, relative to the workspace), the data directory /// for traces and handles, the limits of `[traverse]` and, for the start /// nodes, the hybrid search of `app` over the workspace with the retrievers /// of `profile` (the endpoint's `[search_profiles]` entry, if any). An error /// while the mode is off. -#[allow(clippy::too_many_arguments)] -pub async fn search( - app: &App, - workspace_path: &str, - query: &str, - top_k: Option, - budget: Option<&BudgetArgs>, - steer: Option<&SteerArgs>, - handle: Option<&str>, - profile: Option<&str>, -) -> Result { +pub async fn search(app: &App, request: TraverseRequest<'_>) -> Result { + let TraverseRequest { + workspace_path, + query, + top_k, + budget, + steer, + handle, + profile, + } = request; let config = &app.config; let limits = &config.traverse; if !limits.enabled { diff --git a/src/server.rs b/src/server.rs index dcc4dd6d..7b576464 100644 --- a/src/server.rs +++ b/src/server.rs @@ -417,13 +417,15 @@ impl McpServer { return self.answer( traverse::search( &self.app, - &args.workspace_path, - &args.query, - args.top_k, - budget.as_ref(), - steer.as_ref(), - handle.as_deref(), - self.search_profile.as_deref(), + traverse::TraverseRequest { + workspace_path: &args.workspace_path, + query: &args.query, + top_k: args.top_k, + budget: budget.as_ref(), + steer: steer.as_ref(), + handle: handle.as_deref(), + profile: self.search_profile.as_deref(), + }, ) .await, ); diff --git a/tests/cases/navigation_barrier.rs b/tests/cases/navigation_barrier.rs index c0b47fea..b31daa6e 100644 --- a/tests/cases/navigation_barrier.rs +++ b/tests/cases/navigation_barrier.rs @@ -417,15 +417,18 @@ const RUST_WALK_RESTARTED: &str = /// One default traverse walk (`mode = "traverse"` of the service) of `query`: /// no maps are named, so `lsp.live` runs through `[run_profile.lsp] live`. async fn default_walk(app: &App, workspace: &Workspace, query: &str) -> Value { - local_code_intelligence::app::traverse::search( + use local_code_intelligence::app::traverse::{TraverseRequest, search}; + search( app, - &workspace.path.to_string_lossy(), - query, - Some(8), - None, - None, - None, - None, + TraverseRequest { + workspace_path: &workspace.path.to_string_lossy(), + query, + top_k: Some(8), + budget: None, + steer: None, + handle: None, + profile: None, + }, ) .await .unwrap()