@@ -27,7 +27,7 @@ use lsp_types::{
2727 SemanticTokensResult , SymbolInformation , SymbolTag , TextDocumentIdentifier , Url , WorkspaceEdit ,
2828} ;
2929use paths:: Utf8PathBuf ;
30- use project_model:: { ManifestPath , ProjectWorkspaceKind , TargetKind } ;
30+ use project_model:: { CargoWorkspace , ManifestPath , ProjectWorkspaceKind , TargetKind } ;
3131use serde_json:: json;
3232use stdx:: { format_to, never} ;
3333use syntax:: { algo, ast, AstNode , TextRange , TextSize } ;
@@ -199,14 +199,28 @@ pub(crate) fn handle_view_item_tree(
199199 Ok ( res)
200200}
201201
202+ // cargo test requires the real package name which might contain hyphens but
203+ // the test identifier passed to this function is the namespace form where hyphens
204+ // are replaced with underscores so we have to reverse this and find the real package name
205+ fn find_package_name ( namespace_root : & str , cargo : & CargoWorkspace ) -> Option < String > {
206+ cargo. packages ( ) . find_map ( |p| {
207+ let package_name = & cargo[ p] . name ;
208+ if package_name. replace ( '-' , "_" ) == namespace_root {
209+ Some ( package_name. clone ( ) )
210+ } else {
211+ None
212+ }
213+ } )
214+ }
215+
202216pub ( crate ) fn handle_run_test (
203217 state : & mut GlobalState ,
204218 params : lsp_ext:: RunTestParams ,
205219) -> anyhow:: Result < ( ) > {
206220 if let Some ( _session) = state. test_run_session . take ( ) {
207221 state. send_notification :: < lsp_ext:: EndRunTest > ( ( ) ) ;
208222 }
209- // We detect the lowest common ansector of all included tests, and
223+ // We detect the lowest common ancestor of all included tests, and
210224 // run it. We ignore excluded tests for now, the client will handle
211225 // it for us.
212226 let lca = match params. include {
@@ -225,20 +239,31 @@ pub(crate) fn handle_run_test(
225239 . unwrap_or_default ( ) ,
226240 None => "" . to_owned ( ) ,
227241 } ;
228- let test_path = if lca. is_empty ( ) {
229- None
230- } else if let Some ( ( _ , path) ) = lca. split_once ( "::" ) {
231- Some ( path)
242+ let ( namespace_root , test_path) = if lca. is_empty ( ) {
243+ ( None , None )
244+ } else if let Some ( ( namespace_root , path) ) = lca. split_once ( "::" ) {
245+ ( Some ( namespace_root ) , Some ( path) )
232246 } else {
233- None
247+ ( Some ( lca . as_str ( ) ) , None )
234248 } ;
235249 let mut handles = vec ! [ ] ;
236250 for ws in & * state. workspaces {
237251 if let ProjectWorkspaceKind :: Cargo { cargo, .. } = & ws. kind {
252+ let test_target = if let Some ( namespace_root) = namespace_root {
253+ if let Some ( package_name) = find_package_name ( namespace_root, cargo) {
254+ flycheck:: TestTarget :: Package ( package_name)
255+ } else {
256+ flycheck:: TestTarget :: Workspace
257+ }
258+ } else {
259+ flycheck:: TestTarget :: Workspace
260+ } ;
261+
238262 let handle = flycheck:: CargoTestHandle :: new (
239263 test_path,
240264 state. config . cargo_test_options ( ) ,
241265 cargo. workspace_root ( ) ,
266+ test_target,
242267 state. test_run_sender . clone ( ) ,
243268 ) ?;
244269 handles. push ( handle) ;
0 commit comments