diff --git a/crates/ide-lsp/src/lib.rs b/crates/ide-lsp/src/lib.rs index 4b55372e7..d9d6e4b60 100644 --- a/crates/ide-lsp/src/lib.rs +++ b/crates/ide-lsp/src/lib.rs @@ -1385,14 +1385,8 @@ impl LspManager { let mut first = Vec::new(); if method == "textDocument/implementation" { let (locs, complete) = self.java_source_implementations(snap, t, pos, cancel).await; - // A type declared in the sources has no implementations in the dependencies: - // none found there is the whole answer, without a type hierarchy over every jar. - if complete { - if !locs.is_empty() { - return Ok(locs); - } - out.value = Some(Vec::new()); - continue; + if complete && !locs.is_empty() { + return Ok(locs); } if let Some(partial) = partial && !locs.is_empty() @@ -1450,9 +1444,9 @@ impl LspManager { self.references_streaming(doc, pos, include_declaration, project_wide, true, cancel, None).await } - /// [`Self::references`]. Java: without `libraries`, only the workspace's sources are - /// searched (`libraries_skipped` when `project_wide`); with it and `project_wide`, those - /// found there arrive on `partial` before the dependencies and the JDK are searched. + /// [`Self::references`]. Java, `project_wide`: without `libraries`, only the + /// workspace's sources are searched (`libraries_skipped`); with it, those found + /// there arrive on `partial` before the dependencies and the JDK are searched. #[allow(clippy::too_many_arguments)] pub async fn references_streaming( &self, @@ -1605,10 +1599,7 @@ impl LspManager { }; scope::Widened { first: all, second: Some(found), incomplete: sources.incomplete } } else { - // Bulk probes (usage counts, Safe Delete) ask about the sources' own symbols, - // which no dependency uses: searching every jar and the JDK only adds seconds - // per symbol and delays the searches the user asks for. - let first = query(!libraries).await?; + let first = query(false).await?; let empty = first.is_empty(); scope::Widened::only(first, empty, &t.server) }; diff --git a/crates/ide-lsp/tests/mock_server.rs b/crates/ide-lsp/tests/mock_server.rs index e47ab84ba..111348dd5 100644 --- a/crates/ide-lsp/tests/mock_server.rs +++ b/crates/ide-lsp/tests/mock_server.rs @@ -1891,11 +1891,10 @@ async fn java_implementations_come_from_sources_first() { .collect::() }; *s.responder.lock() = Some(Arc::new(move |_, method, params| match method { - // Lines 0 and 1 are declared in the sources; 2 and 3 in a dependency, which implements 2 on line 3. + // Line 0 is declared in the sources; line 2 in a dependency, which implements it on line 3. "workspace/executeCommand" => Some(match params["arguments"][1].as_u64() { Some(0) => json!({ "locations": at(&[1]), "complete": true }), Some(2) => json!({ "locations": at(&[1]), "complete": false }), - Some(3) => json!({ "locations": [], "complete": false }), _ => json!({ "locations": [], "complete": true }), }), "textDocument/implementation" => Some(at(&[3, 1])), @@ -1926,14 +1925,7 @@ async fn java_implementations_come_from_sources_first() { assert_eq!(lines(&found), vec![3, 1]); assert_eq!(s.requested("textDocument/implementation").len(), 2); - // Declared in the sources and implemented nowhere there: no search through the dependencies. - let found = h.mgr.goto(doc, Pos::new(1, 6), GotoKind::Implementation).await.unwrap(); - assert!(found.is_empty()); - let markers = h.mgr.implementations(doc, &[Pos::new(1, 6)], Default::default()).await.unwrap(); - assert!(markers[0].is_empty()); - assert_eq!(s.requested("textDocument/implementation").len(), 2); - - // None in the sources of a dependency's type: the standard request, with the dependencies. + // None in the sources: the standard request, with the dependencies. let partial = Mutex::new(Vec::new()); let found = h .mgr @@ -3322,17 +3314,9 @@ async fn java_usages_in_the_sources_arrive_before_the_dependencies() { let scopes: Vec<_> = s.requested("workspace/executeCommand")[3..].iter().map(|p| p["arguments"].get(4).cloned()).collect(); assert_eq!(scopes, [Some(json!("sources")), Some(json!("sources"))]); - // Scoped probes with the libraries search everything at once. + // Scoped probes (code lenses) search everything at once. let scoped = h.mgr.references(doc, Pos::new(0, 5), true, false, Default::default()).await.unwrap(); assert_eq!(scoped.locations.len(), 2); - // Usage counts and Safe Delete (no libraries): the sources alone, not widened. - let scoped = - h.mgr.references_streaming(doc, Pos::new(0, 5), true, false, false, Default::default(), None).await.unwrap(); - assert_eq!(scoped.locations.len(), 1); - assert!(scoped.locations.iter().all(|l| l.uri.is_none())); - let scopes: Vec<_> = - s.requested("workspace/executeCommand")[5..].iter().map(|p| p["arguments"].get(4).cloned()).collect(); - assert_eq!(scopes, [None, Some(json!("sources"))]); } #[tokio::test(flavor = "multi_thread")]