@@ -27,7 +27,7 @@ use lsp_types::{
27
27
SemanticTokensResult , SymbolInformation , SymbolTag , TextDocumentIdentifier , Url , WorkspaceEdit ,
28
28
} ;
29
29
use paths:: Utf8PathBuf ;
30
- use project_model:: { ManifestPath , ProjectWorkspaceKind , TargetKind } ;
30
+ use project_model:: { CargoWorkspace , ManifestPath , ProjectWorkspaceKind , TargetKind } ;
31
31
use serde_json:: json;
32
32
use stdx:: { format_to, never} ;
33
33
use syntax:: { algo, ast, AstNode , TextRange , TextSize } ;
@@ -199,14 +199,28 @@ pub(crate) fn handle_view_item_tree(
199
199
Ok ( res)
200
200
}
201
201
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
+
202
216
pub ( crate ) fn handle_run_test (
203
217
state : & mut GlobalState ,
204
218
params : lsp_ext:: RunTestParams ,
205
219
) -> anyhow:: Result < ( ) > {
206
220
if let Some ( _session) = state. test_run_session . take ( ) {
207
221
state. send_notification :: < lsp_ext:: EndRunTest > ( ( ) ) ;
208
222
}
209
- // We detect the lowest common ansector of all included tests, and
223
+ // We detect the lowest common ancestor of all included tests, and
210
224
// run it. We ignore excluded tests for now, the client will handle
211
225
// it for us.
212
226
let lca = match params. include {
@@ -225,20 +239,31 @@ pub(crate) fn handle_run_test(
225
239
. unwrap_or_default ( ) ,
226
240
None => "" . to_owned ( ) ,
227
241
} ;
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) )
232
246
} else {
233
- None
247
+ ( Some ( lca . as_str ( ) ) , None )
234
248
} ;
235
249
let mut handles = vec ! [ ] ;
236
250
for ws in & * state. workspaces {
237
251
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
+
238
262
let handle = flycheck:: CargoTestHandle :: new (
239
263
test_path,
240
264
state. config . cargo_test_options ( ) ,
241
265
cargo. workspace_root ( ) ,
266
+ test_target,
242
267
state. test_run_sender . clone ( ) ,
243
268
) ?;
244
269
handles. push ( handle) ;
0 commit comments