mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-30 15:03:42 +00:00
1834bae5b8
This wasn't a right decision in the first place, the feature flag was broken in the last rustfmt release, and syntax highlighting of imports is more important anyway
409 lines
10 KiB
Rust
409 lines
10 KiB
Rust
mod support;
|
|
|
|
use std::{collections::HashMap, time::Instant};
|
|
|
|
use lsp_types::{
|
|
CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions,
|
|
Position, Range, TextDocumentItem, TextDocumentPositionParams,
|
|
};
|
|
use ra_lsp_server::req::{
|
|
CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument,
|
|
Formatting, OnEnter, Runnables, RunnablesParams,
|
|
};
|
|
use serde_json::json;
|
|
use tempfile::TempDir;
|
|
|
|
use crate::support::{project, Project};
|
|
|
|
const LOG: &'static str = "";
|
|
const PROFILE: &'static str = "";
|
|
// const PROFILE: &'static str = "*@3>100";
|
|
|
|
#[test]
|
|
fn completes_items_from_standard_library() {
|
|
let project_start = Instant::now();
|
|
let server = project(
|
|
r#"
|
|
//- Cargo.toml
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
|
|
//- src/lib.rs
|
|
use std::collections::Spam;
|
|
"#,
|
|
);
|
|
server.wait_until_workspace_is_loaded();
|
|
eprintln!("loading took {:?}", project_start.elapsed());
|
|
let completion_start = Instant::now();
|
|
let res = server.send_request::<Completion>(CompletionParams {
|
|
text_document: server.doc_id("src/lib.rs"),
|
|
context: None,
|
|
position: Position::new(0, 23),
|
|
});
|
|
assert!(format!("{}", res).contains("HashMap"));
|
|
eprintln!("completion took {:?}", completion_start.elapsed());
|
|
}
|
|
|
|
#[test]
|
|
fn test_runnables_no_project() {
|
|
let server = project(
|
|
r"
|
|
//- lib.rs
|
|
#[test]
|
|
fn foo() {
|
|
}
|
|
",
|
|
);
|
|
server.wait_until_workspace_is_loaded();
|
|
server.request::<Runnables>(
|
|
RunnablesParams { text_document: server.doc_id("lib.rs"), position: None },
|
|
json!([
|
|
{
|
|
"args": [ "test", "--", "foo", "--nocapture" ],
|
|
"bin": "cargo",
|
|
"env": { "RUST_BACKTRACE": "short" },
|
|
"cwd": null,
|
|
"label": "test foo",
|
|
"range": {
|
|
"end": { "character": 1, "line": 2 },
|
|
"start": { "character": 0, "line": 0 }
|
|
}
|
|
},
|
|
{
|
|
"args": [
|
|
"check",
|
|
"--all"
|
|
],
|
|
"bin": "cargo",
|
|
"env": {},
|
|
"cwd": null,
|
|
"label": "cargo check --all",
|
|
"range": {
|
|
"end": {
|
|
"character": 0,
|
|
"line": 0
|
|
},
|
|
"start": {
|
|
"character": 0,
|
|
"line": 0
|
|
}
|
|
}
|
|
}
|
|
]),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_runnables_project() {
|
|
let code = r#"
|
|
//- foo/Cargo.toml
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
|
|
//- foo/src/lib.rs
|
|
pub fn foo() {}
|
|
|
|
//- foo/tests/spam.rs
|
|
#[test]
|
|
fn test_eggs() {}
|
|
|
|
//- bar/Cargo.toml
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.0"
|
|
|
|
//- bar/src/main.rs
|
|
fn main() {}
|
|
"#;
|
|
|
|
let server = Project::with_fixture(code).root("foo").root("bar").server();
|
|
|
|
server.wait_until_workspace_is_loaded();
|
|
server.request::<Runnables>(
|
|
RunnablesParams {
|
|
text_document: server.doc_id("foo/tests/spam.rs"),
|
|
position: None,
|
|
},
|
|
json!([
|
|
{
|
|
"args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--nocapture" ],
|
|
"bin": "cargo",
|
|
"env": { "RUST_BACKTRACE": "short" },
|
|
"label": "test test_eggs",
|
|
"range": {
|
|
"end": { "character": 17, "line": 1 },
|
|
"start": { "character": 0, "line": 0 }
|
|
},
|
|
"cwd": server.path().join("foo")
|
|
},
|
|
{
|
|
"args": [
|
|
"check",
|
|
"--package",
|
|
"foo",
|
|
"--test",
|
|
"spam"
|
|
],
|
|
"bin": "cargo",
|
|
"env": {},
|
|
"cwd": server.path().join("foo"),
|
|
"label": "cargo check -p foo",
|
|
"range": {
|
|
"end": {
|
|
"character": 0,
|
|
"line": 0
|
|
},
|
|
"start": {
|
|
"character": 0,
|
|
"line": 0
|
|
}
|
|
}
|
|
}
|
|
])
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_document() {
|
|
let server = project(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
|
|
//- src/lib.rs
|
|
mod bar;
|
|
|
|
fn main() {
|
|
}
|
|
|
|
pub use std::collections::HashMap;
|
|
"#,
|
|
);
|
|
server.wait_until_workspace_is_loaded();
|
|
|
|
server.request::<Formatting>(
|
|
DocumentFormattingParams {
|
|
text_document: server.doc_id("src/lib.rs"),
|
|
options: FormattingOptions {
|
|
tab_size: 4,
|
|
insert_spaces: false,
|
|
properties: HashMap::new(),
|
|
},
|
|
},
|
|
json!([
|
|
{
|
|
"newText": r#"mod bar;
|
|
|
|
fn main() {}
|
|
|
|
pub use std::collections::HashMap;
|
|
"#,
|
|
"range": {
|
|
"end": {
|
|
"character": 0,
|
|
"line": 6
|
|
},
|
|
"start": {
|
|
"character": 0,
|
|
"line": 0
|
|
}
|
|
}
|
|
}
|
|
]),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_missing_module_code_action() {
|
|
let server = project(
|
|
r#"
|
|
//- Cargo.toml
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
|
|
//- src/lib.rs
|
|
mod bar;
|
|
|
|
fn main() {}
|
|
"#,
|
|
);
|
|
server.wait_until_workspace_is_loaded();
|
|
let empty_context = || CodeActionContext { diagnostics: Vec::new(), only: None };
|
|
server.request::<CodeActionRequest>(
|
|
CodeActionParams {
|
|
text_document: server.doc_id("src/lib.rs"),
|
|
range: Range::new(Position::new(0, 4), Position::new(0, 7)),
|
|
context: empty_context(),
|
|
},
|
|
json!([
|
|
{
|
|
"command": {
|
|
"arguments": [
|
|
{
|
|
"cursorPosition": null,
|
|
"label": "create module",
|
|
"workspaceEdit": {
|
|
"documentChanges": [
|
|
{
|
|
"kind": "create",
|
|
"uri": "file:///[..]/src/bar.rs"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
],
|
|
"command": "rust-analyzer.applySourceChange",
|
|
"title": "create module"
|
|
},
|
|
"title": "create module"
|
|
}
|
|
]),
|
|
);
|
|
|
|
server.request::<CodeActionRequest>(
|
|
CodeActionParams {
|
|
text_document: server.doc_id("src/lib.rs"),
|
|
range: Range::new(Position::new(2, 4), Position::new(2, 7)),
|
|
context: empty_context(),
|
|
},
|
|
json!([]),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_missing_module_code_action_in_json_project() {
|
|
let tmp_dir = TempDir::new().unwrap();
|
|
|
|
let path = tmp_dir.path();
|
|
|
|
let project = json!({
|
|
"roots": [path],
|
|
"crates": [ { "root_module": path.join("src/lib.rs"), "deps": [], "edition": "2015" } ]
|
|
});
|
|
|
|
let code = format!(
|
|
r#"
|
|
//- rust-project.json
|
|
{PROJECT}
|
|
|
|
//- src/lib.rs
|
|
mod bar;
|
|
|
|
fn main() {{}}
|
|
"#,
|
|
PROJECT = project.to_string(),
|
|
);
|
|
|
|
let server = Project::with_fixture(&code).tmp_dir(tmp_dir).server();
|
|
|
|
server.wait_until_workspace_is_loaded();
|
|
let empty_context = || CodeActionContext { diagnostics: Vec::new(), only: None };
|
|
server.request::<CodeActionRequest>(
|
|
CodeActionParams {
|
|
text_document: server.doc_id("src/lib.rs"),
|
|
range: Range::new(Position::new(0, 4), Position::new(0, 7)),
|
|
context: empty_context(),
|
|
},
|
|
json!([
|
|
{
|
|
"command": {
|
|
"arguments": [
|
|
{
|
|
"cursorPosition": null,
|
|
"label": "create module",
|
|
"workspaceEdit": {
|
|
"documentChanges": [
|
|
{
|
|
"kind": "create",
|
|
"uri": "file:///[..]/src/bar.rs"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
],
|
|
"command": "rust-analyzer.applySourceChange",
|
|
"title": "create module"
|
|
},
|
|
"title": "create module"
|
|
}
|
|
]),
|
|
);
|
|
|
|
server.request::<CodeActionRequest>(
|
|
CodeActionParams {
|
|
text_document: server.doc_id("src/lib.rs"),
|
|
range: Range::new(Position::new(2, 4), Position::new(2, 7)),
|
|
context: empty_context(),
|
|
},
|
|
json!([]),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn diagnostics_dont_block_typing() {
|
|
let librs: String = (0..10).map(|i| format!("mod m{};", i)).collect();
|
|
let libs: String = (0..10).map(|i| format!("//- src/m{}.rs\nfn foo() {{}}\n\n", i)).collect();
|
|
let server = project(&format!(
|
|
r#"
|
|
//- Cargo.toml
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
|
|
//- src/lib.rs
|
|
{}
|
|
|
|
{}
|
|
|
|
fn main() {{}}
|
|
"#,
|
|
librs, libs
|
|
));
|
|
server.wait_until_workspace_is_loaded();
|
|
for i in 0..10 {
|
|
server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams {
|
|
text_document: TextDocumentItem {
|
|
uri: server.doc_id(&format!("src/m{}.rs", i)).uri,
|
|
language_id: "rust".to_string(),
|
|
version: 0,
|
|
text: "/// Docs\nfn foo() {}".to_string(),
|
|
},
|
|
});
|
|
}
|
|
let start = std::time::Instant::now();
|
|
server.request::<OnEnter>(
|
|
TextDocumentPositionParams {
|
|
text_document: server.doc_id("src/m0.rs"),
|
|
position: Position { line: 0, character: 5 },
|
|
},
|
|
json!({
|
|
"cursorPosition": {
|
|
"position": { "character": 4, "line": 1 },
|
|
"textDocument": { "uri": "file:///[..]src/m0.rs" }
|
|
},
|
|
"label": "on enter",
|
|
"workspaceEdit": {
|
|
"documentChanges": [
|
|
{
|
|
"edits": [
|
|
{
|
|
"newText": "\n/// ",
|
|
"range": {
|
|
"end": { "character": 5, "line": 0 },
|
|
"start": { "character": 5, "line": 0 }
|
|
}
|
|
}
|
|
],
|
|
"textDocument": { "uri": "file:///[..]src/m0.rs", "version": null }
|
|
}
|
|
]
|
|
}
|
|
}),
|
|
);
|
|
let elapsed = start.elapsed();
|
|
assert!(elapsed.as_millis() < 2000, "typing enter took {:?}", elapsed);
|
|
}
|