Skip to content

Commit 6ee2ebe

Browse files
committed
reimplement the world
1 parent a646439 commit 6ee2ebe

27 files changed

+2038
-38
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ide-db/src/search.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl SearchScope {
9292
}
9393

9494
/// Build a search scope spanning the entire crate graph of files.
95-
fn crate_graph(db: &RootDatabase) -> SearchScope {
95+
pub fn crate_graph(db: &RootDatabase) -> SearchScope {
9696
let mut entries = NoHashHashMap::default();
9797

9898
let graph = db.crate_graph();

crates/ide/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ mod parent_module;
4747
mod references;
4848
mod rename;
4949
mod runnables;
50+
mod test_items;
5051
mod ssr;
5152
mod static_index;
5253
mod status;
@@ -522,6 +523,10 @@ impl Analysis {
522523
self.with_db(|db| runnables::runnables(db, file_id))
523524
}
524525

526+
pub fn test_runnables_in_file(&self, file_id: FileId) -> Cancellable<Vec<Runnable>> {
527+
self.with_db(|db| test_items::test_runnables_in_file(db, file_id))
528+
}
529+
525530
/// Returns the set of tests for the given file position.
526531
pub fn related_tests(
527532
&self,

crates/ide/src/runnables.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ fn parent_test_module(sema: &Semantics<'_, RootDatabase>, fn_def: &ast::Fn) -> O
295295
let module = ast::Module::cast(node)?;
296296
let module = sema.to_def(&module)?;
297297

298-
if has_test_function_or_multiple_test_submodules(sema, &module) {
298+
if has_test_function_recursively(sema, &module) {
299299
Some(module)
300300
} else {
301301
None
@@ -346,7 +346,7 @@ pub(crate) fn runnable_mod(
346346
sema: &Semantics<'_, RootDatabase>,
347347
def: hir::Module,
348348
) -> Option<Runnable> {
349-
if !has_test_function_or_multiple_test_submodules(sema, &def) {
349+
if !has_test_function_recursively(sema, &def) {
350350
return None;
351351
}
352352
let path =
@@ -388,7 +388,7 @@ fn runnable_mod_outline_definition(
388388
sema: &Semantics<'_, RootDatabase>,
389389
def: hir::Module,
390390
) -> Option<Runnable> {
391-
if !has_test_function_or_multiple_test_submodules(sema, &def) {
391+
if !has_test_function_recursively(sema, &def) {
392392
return None;
393393
}
394394
let path =
@@ -514,14 +514,16 @@ fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool {
514514
})
515515
}
516516

517+
// Argue:
518+
// Should we return when `number_of_test_submodules > 0` or `number_of_test_submodules > 1`?
519+
// Support `> 1`:
517520
// We could create runnables for modules with number_of_test_submodules > 0,
518521
// but that bloats the runnables for no real benefit, since all tests can be run by the submodule already
519-
fn has_test_function_or_multiple_test_submodules(
520-
sema: &Semantics<'_, RootDatabase>,
521-
module: &hir::Module,
522-
) -> bool {
523-
let mut number_of_test_submodules = 0;
524-
522+
// Support `> 0`:
523+
// This will be helpful to rebuild the test item tree for VSCode, although it might should use another function or API.
524+
// A bit faster
525+
// Tell that there are some tests in the module when there is only declaration "mod SomeModule;"
526+
fn has_test_function_recursively(sema: &Semantics<'_, RootDatabase>, module: &hir::Module) -> bool {
525527
for item in module.declarations(sema.db) {
526528
match item {
527529
hir::ModuleDef::Function(f) => {
@@ -532,15 +534,15 @@ fn has_test_function_or_multiple_test_submodules(
532534
}
533535
}
534536
hir::ModuleDef::Module(submodule) => {
535-
if has_test_function_or_multiple_test_submodules(sema, &submodule) {
536-
number_of_test_submodules += 1;
537+
if has_test_function_recursively(sema, &submodule) {
538+
return true;
537539
}
538540
}
539541
_ => (),
540542
}
541543
}
542544

543-
number_of_test_submodules > 1
545+
return false;
544546
}
545547

546548
#[cfg(test)]

crates/ide/src/test_items.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/// This mod is mainly to support vscode native test extension
2+
/// please reference: https://code.visualstudio.com/api/extension-guides/testing
3+
// It's a pretty rough implementation for now, reuse a lot of logic from runnable.
4+
use ide_db::{
5+
base_db::{FileId},
6+
RootDatabase,
7+
};
8+
9+
use crate::{runnables::runnables, Runnable, RunnableKind};
10+
11+
pub(crate) fn test_runnables_in_file(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
12+
return test_runnables_in_file_iter(db, file_id).collect();
13+
}
14+
15+
fn test_runnables_in_file_iter(
16+
db: &RootDatabase,
17+
file_id: FileId,
18+
) -> impl Iterator<Item = Runnable> {
19+
// TODO: Maybe should extract another function with another optional RunnableKind,
20+
// so that we could collect specfic Runnables on the fly, rather than fileter all agagin.
21+
let all_runnables = runnables(db, file_id);
22+
let tests = all_runnables.into_iter().filter(is_test_runnable);
23+
return tests;
24+
25+
fn is_test_runnable(runnable: &Runnable) -> bool {
26+
match runnable.kind {
27+
RunnableKind::Test { .. } => true,
28+
RunnableKind::TestMod { .. } => true,
29+
_ => false,
30+
}
31+
}
32+
}

crates/project-model/src/cargo_workspace.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,31 @@ use crate::{CfgOverrides, InvocationStrategy};
2727
///
2828
/// We use absolute paths here, `cargo metadata` guarantees to always produce
2929
/// abs paths.
30-
#[derive(Debug, Clone, Eq, PartialEq)]
30+
#[derive(Debug, Clone)]
3131
pub struct CargoWorkspace {
3232
packages: Arena<PackageData>,
3333
targets: Arena<TargetData>,
3434
workspace_root: AbsPathBuf,
35+
// Hack, this should be an implmentation detail, however,
36+
// sometimes it's useful to let the client know the project
37+
// structure.
38+
// This property should only be used as JSON
39+
pub origin_metadata: cargo_metadata::Metadata,
40+
}
41+
42+
impl PartialEq for CargoWorkspace {
43+
fn eq(&self, other: &Self) -> bool {
44+
self.packages == other.packages
45+
&& self.targets == other.targets
46+
&& self.workspace_root == other.workspace_root
47+
// Do not compare the origin data
48+
// It's only used to be transfer as JSON
49+
// && self.origin_metadata == other.origin_metadata
50+
}
3551
}
3652

53+
impl Eq for CargoWorkspace {}
54+
3755
impl ops::Index<Package> for CargoWorkspace {
3856
type Output = PackageData;
3957
fn index(&self, index: Package) -> &PackageData {
@@ -328,9 +346,11 @@ impl CargoWorkspace {
328346
let mut pkg_by_id = FxHashMap::default();
329347
let mut packages = Arena::default();
330348
let mut targets = Arena::default();
331-
349+
// let tmp = Box::new(meta);
332350
let ws_members = &meta.workspace_members;
333351

352+
let origin_metadata = meta.clone();
353+
334354
meta.packages.sort_by(|a, b| a.id.cmp(&b.id));
335355
for meta_pkg in meta.packages {
336356
let cargo_metadata::Package {
@@ -411,7 +431,7 @@ impl CargoWorkspace {
411431
let workspace_root =
412432
AbsPathBuf::assert(PathBuf::from(meta.workspace_root.into_os_string()));
413433

414-
CargoWorkspace { packages, targets, workspace_root }
434+
CargoWorkspace { packages, targets, workspace_root, origin_metadata }
415435
}
416436

417437
pub fn packages(&self) -> impl Iterator<Item = Package> + ExactSizeIterator + '_ {

crates/rust-analyzer/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ path = "src/bin/main.rs"
2020

2121
[dependencies]
2222
anyhow = "1.0.62"
23+
cargo_metadata = "0.15.0"
2324
crossbeam-channel = "0.5.5"
2425
dissimilar = "1.0.4"
2526
itertools = "0.10.5"

crates/rust-analyzer/src/handlers.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use ide::{
1515
RunnableKind, SingleResolve, SourceChange, TextEdit,
1616
};
1717
use ide_db::SymbolKind;
18+
use itertools::Itertools;
1819
use lsp_server::ErrorCode;
1920
use lsp_types::{
2021
CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
@@ -804,6 +805,43 @@ pub(crate) fn handle_runnables(
804805
Ok(res)
805806
}
806807

808+
pub(crate) fn handle_cargo_workspaces(
809+
snap: GlobalStateSnapshot,
810+
_: (),
811+
) -> Result<Vec<cargo_metadata::Metadata>> {
812+
let _p = profile::span("cargo_workspaces");
813+
let res = snap
814+
.workspaces
815+
.iter()
816+
.filter_map(|workspace| {
817+
if let ProjectWorkspace::Cargo { cargo, .. } = workspace {
818+
Some(cargo.origin_metadata.clone())
819+
} else {
820+
None
821+
}
822+
})
823+
.collect_vec();
824+
Ok(res)
825+
}
826+
827+
pub(crate) fn handle_test_runnables_in_file(
828+
snap: GlobalStateSnapshot,
829+
params: lsp_ext::TestRunnablesInFileParams,
830+
) -> Result<Vec<lsp_ext::Runnable>> {
831+
let _p = profile::span("handle_test_runnables_in_file");
832+
833+
let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
834+
let test_runnables = snap.analysis.test_runnables_in_file(file_id)?;
835+
836+
let mut res = Vec::new();
837+
for runnable in test_runnables {
838+
let runnable = to_proto::runnable(&snap, runnable)?;
839+
res.push(runnable);
840+
}
841+
842+
Ok(res)
843+
}
844+
807845
fn should_skip_for_offset(runnable: &Runnable, offset: Option<TextSize>) -> bool {
808846
match offset {
809847
None => false,

crates/rust-analyzer/src/lsp_ext.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ pub struct RunnablesParams {
244244
pub position: Option<Position>,
245245
}
246246

247+
#[derive(Serialize, Deserialize, Debug)]
248+
#[serde(rename_all = "camelCase")]
249+
pub struct TestRunnablesInFileParams {
250+
pub text_document: TextDocumentIdentifier,
251+
}
252+
247253
#[derive(Deserialize, Serialize, Debug)]
248254
#[serde(rename_all = "camelCase")]
249255
pub struct Runnable {
@@ -290,6 +296,22 @@ pub struct TestInfo {
290296
pub runnable: Runnable,
291297
}
292298

299+
pub enum CargoWorkspaces{}
300+
301+
impl Request for CargoWorkspaces{
302+
type Params = ();
303+
type Result = Vec<cargo_metadata::Metadata>;
304+
const METHOD: &'static str = "rust-analyzer/cargoWorkspaces";
305+
}
306+
307+
pub enum TestRunnablesInFile {}
308+
309+
impl Request for TestRunnablesInFile {
310+
type Params = TestRunnablesInFileParams;
311+
type Result = Vec<Runnable>;
312+
const METHOD: &'static str = "rust-analyzer/testRunnablesInFile";
313+
}
314+
293315
#[derive(Serialize, Deserialize, Debug)]
294316
#[serde(rename_all = "camelCase")]
295317
pub struct InlayHintsParams {

crates/rust-analyzer/src/main_loop.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,8 @@ impl GlobalState {
671671
.on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro)
672672
.on::<lsp_ext::ParentModule>(handlers::handle_parent_module)
673673
.on::<lsp_ext::Runnables>(handlers::handle_runnables)
674+
.on::<lsp_ext::CargoWorkspaces>(handlers:: handle_cargo_workspaces)
675+
.on::<lsp_ext::TestRunnablesInFile>(handlers::handle_test_runnables_in_file)
674676
.on::<lsp_ext::RelatedTests>(handlers::handle_related_tests)
675677
.on::<lsp_ext::CodeActionRequest>(handlers::handle_code_action)
676678
.on::<lsp_ext::CodeActionResolveRequest>(handlers::handle_code_action_resolve)

editors/code/package-lock.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

editors/code/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"ovsx": "^0.5.2",
6060
"prettier": "^2.7.1",
6161
"tslib": "^2.4.0",
62-
"typescript": "^4.7.4",
62+
"typescript": "^5.0.0",
6363
"vsce": "^2.9.2"
6464
},
6565
"activationEvents": [

editors/code/src/debug.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ async function getDebugConfiguration(
6969
ctx: Ctx,
7070
runnable: ra.Runnable
7171
): Promise<vscode.DebugConfiguration | undefined> {
72-
const editor = ctx.activeRustEditor;
73-
if (!editor) return;
7472

7573
const knownEngines: Record<string, DebugConfigProvider> = {
7674
"vadimcn.vscode-lldb": getLldbDebugConfig,
@@ -91,7 +89,7 @@ async function getDebugConfiguration(
9189
if (!debugEngine) {
9290
await vscode.window.showErrorMessage(
9391
`Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)` +
94-
` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`
92+
` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`
9593
);
9694
return;
9795
}
@@ -109,7 +107,7 @@ async function getDebugConfiguration(
109107
!isMultiFolderWorkspace || !runnable.args.workspaceRoot
110108
? firstWorkspace
111109
: workspaceFolders.find((w) => runnable.args.workspaceRoot?.includes(w.uri.fsPath)) ||
112-
firstWorkspace;
110+
firstWorkspace;
113111

114112
const wsFolder = path.normalize(workspace.uri.fsPath);
115113
const workspaceQualifier = isMultiFolderWorkspace ? `:${workspace.name}` : "";
@@ -201,5 +199,6 @@ function getCppvsDebugConfig(
201199
cwd: runnable.args.workspaceRoot,
202200
sourceFileMap,
203201
env,
202+
204203
};
205204
}

0 commit comments

Comments
 (0)