summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/bench/lsp.rs266
-rw-r--r--cli/lsp/language_server.rs2395
-rw-r--r--cli/tests/integration_tests_lsp.rs1661
-rw-r--r--cli/tests/lsp/code_action_params.json (renamed from cli/tests/lsp/code_action_resolve_request.json)27
-rw-r--r--cli/tests/lsp/code_action_params_cache.json41
-rw-r--r--cli/tests/lsp/code_action_request.json44
-rw-r--r--cli/tests/lsp/code_action_request_cache.json46
-rw-r--r--cli/tests/lsp/code_action_resolve_params.json27
-rw-r--r--cli/tests/lsp/code_action_resolve_response.json (renamed from cli/tests/lsp/code_action_resolve_request_response.json)0
-rw-r--r--cli/tests/lsp/code_lens_request.json10
-rw-r--r--cli/tests/lsp/code_lens_request_asset.json10
-rw-r--r--cli/tests/lsp/code_lens_resolve_request.json21
-rw-r--r--cli/tests/lsp/code_lens_resolve_request_asset.json21
-rw-r--r--cli/tests/lsp/code_lens_resolve_request_impl.json21
-rw-r--r--cli/tests/lsp/code_lens_resolve_response.json38
-rw-r--r--cli/tests/lsp/code_lens_resolve_response_impl.json38
-rw-r--r--cli/tests/lsp/code_lens_response.json34
-rw-r--r--cli/tests/lsp/code_lens_response_impl.json50
-rw-r--r--cli/tests/lsp/completion_request.json18
-rw-r--r--cli/tests/lsp/completion_request_optional.json18
-rw-r--r--cli/tests/lsp/completion_request_params_optional.json13
-rw-r--r--cli/tests/lsp/completion_request_registry.json18
-rw-r--r--cli/tests/lsp/completion_request_registry_02.json18
-rw-r--r--cli/tests/lsp/completion_request_response_empty.json38
-rw-r--r--cli/tests/lsp/completion_resolve_params.json14
-rw-r--r--cli/tests/lsp/completion_resolve_params_optional.json15
-rw-r--r--cli/tests/lsp/completion_resolve_params_registry.json20
-rw-r--r--cli/tests/lsp/completion_resolve_request.json19
-rw-r--r--cli/tests/lsp/completion_resolve_request_optional.json20
-rw-r--r--cli/tests/lsp/completion_resolve_request_registry.json25
-rw-r--r--cli/tests/lsp/completion_resolve_response.json11
-rw-r--r--cli/tests/lsp/completion_resolve_response_registry.json20
-rw-r--r--cli/tests/lsp/definition_request_asset.json14
-rw-r--r--cli/tests/lsp/did_change_notification_large.json25
-rw-r--r--cli/tests/lsp/did_change_notification_large_02.json25
-rw-r--r--cli/tests/lsp/did_change_notification_large_03.json25
-rw-r--r--cli/tests/lsp/did_change_notification_mbc.json25
-rw-r--r--cli/tests/lsp/did_open_notification.json12
-rw-r--r--cli/tests/lsp/did_open_notification_asset.json12
-rw-r--r--cli/tests/lsp/did_open_notification_cache.json12
-rw-r--r--cli/tests/lsp/did_open_notification_cl_impl.json12
-rw-r--r--cli/tests/lsp/did_open_notification_cl_references.json12
-rw-r--r--cli/tests/lsp/did_open_notification_code_action.json12
-rw-r--r--cli/tests/lsp/did_open_notification_completion_optional.json12
-rw-r--r--cli/tests/lsp/did_open_notification_completion_registry.json12
-rw-r--r--cli/tests/lsp/did_open_notification_completion_registry_02.json12
-rw-r--r--cli/tests/lsp/did_open_notification_completions.json12
-rw-r--r--cli/tests/lsp/did_open_notification_large.json12
-rw-r--r--cli/tests/lsp/did_open_notification_mbc.json12
-rw-r--r--cli/tests/lsp/did_open_notification_mbc_fmt.json12
-rw-r--r--cli/tests/lsp/did_open_notification_unstable.json12
-rw-r--r--cli/tests/lsp/did_open_params_doc_symbol.json8
-rw-r--r--cli/tests/lsp/did_open_params_large.json8
-rw-r--r--cli/tests/lsp/did_open_params_semantic_tokens.json8
-rw-r--r--cli/tests/lsp/document_symbol_did_open_notification.json12
-rw-r--r--cli/tests/lsp/document_symbol_request.json10
-rw-r--r--cli/tests/lsp/document_symbol_response.json371
-rw-r--r--cli/tests/lsp/exit_notification.json5
-rw-r--r--cli/tests/lsp/folding_range_did_open_notification.json12
-rw-r--r--cli/tests/lsp/folding_range_request.json10
-rw-r--r--cli/tests/lsp/formatting_mbc_response.json54
-rw-r--r--cli/tests/lsp/formatting_request_mbc_fmt.json14
-rw-r--r--cli/tests/lsp/hover_request.json14
-rw-r--r--cli/tests/lsp/hover_request_asset.json14
-rw-r--r--cli/tests/lsp/hover_request_large_01.json14
-rw-r--r--cli/tests/lsp/hover_request_large_02.json14
-rw-r--r--cli/tests/lsp/hover_request_large_03.json14
-rw-r--r--cli/tests/lsp/hover_request_mbc.json14
-rw-r--r--cli/tests/lsp/incoming_calls_params.json28
-rw-r--r--cli/tests/lsp/incoming_calls_request.json33
-rw-r--r--cli/tests/lsp/incoming_calls_response.json42
-rw-r--r--cli/tests/lsp/initialize_params.json56
-rw-r--r--cli/tests/lsp/initialize_params_disabled.json56
-rw-r--r--cli/tests/lsp/initialize_params_registry.json58
-rw-r--r--cli/tests/lsp/initialize_params_unstable.json56
-rw-r--r--cli/tests/lsp/initialize_request.json61
-rw-r--r--cli/tests/lsp/initialize_request_disabled.json29
-rw-r--r--cli/tests/lsp/initialize_request_registry.json63
-rw-r--r--cli/tests/lsp/initialize_request_unstable.json30
-rw-r--r--cli/tests/lsp/initialized_notification.json5
-rw-r--r--cli/tests/lsp/outgoing_calls_params.json28
-rw-r--r--cli/tests/lsp/outgoing_calls_request.json33
-rw-r--r--cli/tests/lsp/outgoing_calls_response.json42
-rw-r--r--cli/tests/lsp/performance_request.json6
-rw-r--r--cli/tests/lsp/prepare_call_hierarchy_did_open_notification.json12
-rw-r--r--cli/tests/lsp/prepare_call_hierarchy_request.json14
-rw-r--r--cli/tests/lsp/prepare_call_hierarchy_response.json28
-rw-r--r--cli/tests/lsp/references_request_asset.json17
-rw-r--r--cli/tests/lsp/rename_did_open_notification.json12
-rw-r--r--cli/tests/lsp/rename_request.json15
-rw-r--r--cli/tests/lsp/rename_response.json38
-rw-r--r--cli/tests/lsp/selection_range_did_open_notification.json12
-rw-r--r--cli/tests/lsp/selection_range_request.json16
-rw-r--r--cli/tests/lsp/selection_range_response.json86
-rw-r--r--cli/tests/lsp/semantic_tokens_did_open_notification.json12
-rw-r--r--cli/tests/lsp/semantic_tokens_full_request.json10
-rw-r--r--cli/tests/lsp/semantic_tokens_range_request.json20
-rw-r--r--cli/tests/lsp/shutdown_request.json6
-rw-r--r--cli/tests/lsp/signature_help_did_change_notification.json25
-rw-r--r--cli/tests/lsp/signature_help_did_open_notification.json12
-rw-r--r--cli/tests/lsp/signature_help_request_01.json19
-rw-r--r--cli/tests/lsp/signature_help_request_02.json14
-rw-r--r--cli/tests/lsp/virtual_text_document_request.json10
103 files changed, 3020 insertions, 3879 deletions
diff --git a/cli/bench/lsp.rs b/cli/bench/lsp.rs
index ed474b9ea..cabcef1db 100644
--- a/cli/bench/lsp.rs
+++ b/cli/bench/lsp.rs
@@ -1,37 +1,21 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-use deno_core::error::generic_error;
use deno_core::error::AnyError;
-use deno_core::serde::de;
use deno_core::serde::Deserialize;
-use deno_core::serde::Serialize;
use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
-use lazy_static::lazy_static;
-use regex::Regex;
use std::collections::HashMap;
-use std::io::BufRead;
-use std::io::Read;
-use std::io::Write;
use std::path::Path;
-use std::process::ChildStdin;
-use std::process::ChildStdout;
-use std::process::Command;
-use std::process::Stdio;
use std::time::Duration;
-use std::time::Instant;
+use test_util::lsp::LspClient;
+use test_util::lsp::LspResponseError;
static FIXTURE_DB_TS: &str = include_str!("fixtures/db.ts");
static FIXTURE_DB_MESSAGES: &[u8] = include_bytes!("fixtures/db_messages.json");
static FIXTURE_INIT_JSON: &[u8] =
include_bytes!("fixtures/initialize_params.json");
-lazy_static! {
- static ref CONTENT_TYPE_REG: Regex =
- Regex::new(r"(?i)^content-length:\s+(\d+)").unwrap();
-}
-
#[derive(Debug, Deserialize)]
enum FixtureType {
#[serde(rename = "action")]
@@ -53,224 +37,6 @@ struct FixtureMessage {
params: Value,
}
-#[derive(Debug, Deserialize, Serialize)]
-struct LspResponseError {
- code: i32,
- message: String,
- data: Option<Value>,
-}
-
-#[derive(Debug)]
-enum LspMessage {
- Notification(String, Option<Value>),
- Request(u64, String, Option<Value>),
- Response(u64, Option<Value>, Option<LspResponseError>),
-}
-
-impl<'a> From<&'a [u8]> for LspMessage {
- fn from(s: &'a [u8]) -> Self {
- let value: Value = serde_json::from_slice(s).unwrap();
- let obj = value.as_object().unwrap();
- if obj.contains_key("id") && obj.contains_key("method") {
- let id = obj.get("id").unwrap().as_u64().unwrap();
- let method = obj.get("method").unwrap().as_str().unwrap().to_string();
- Self::Request(id, method, obj.get("params").cloned())
- } else if obj.contains_key("id") {
- let id = obj.get("id").unwrap().as_u64().unwrap();
- let maybe_error: Option<LspResponseError> = obj
- .get("error")
- .map(|v| serde_json::from_value(v.clone()).unwrap());
- Self::Response(id, obj.get("result").cloned(), maybe_error)
- } else {
- assert!(obj.contains_key("method"));
- let method = obj.get("method").unwrap().as_str().unwrap().to_string();
- Self::Notification(method, obj.get("params").cloned())
- }
- }
-}
-
-struct LspClient {
- reader: std::io::BufReader<ChildStdout>,
- child: std::process::Child,
- request_id: u64,
- start: Instant,
- writer: std::io::BufWriter<ChildStdin>,
-}
-
-fn read_message<R>(reader: &mut R) -> Result<Vec<u8>, AnyError>
-where
- R: Read + BufRead,
-{
- let mut content_length = 0_usize;
- loop {
- let mut buf = String::new();
- reader.read_line(&mut buf)?;
- if let Some(captures) = CONTENT_TYPE_REG.captures(&buf) {
- let content_length_match = captures
- .get(1)
- .ok_or_else(|| generic_error("missing capture"))?;
- content_length = content_length_match.as_str().parse::<usize>()?;
- }
- if &buf == "\r\n" {
- break;
- }
- }
-
- let mut msg_buf = vec![0_u8; content_length];
- reader.read_exact(&mut msg_buf)?;
- Ok(msg_buf)
-}
-
-impl Drop for LspClient {
- fn drop(&mut self) {
- match self.child.try_wait() {
- Ok(None) => {
- self.child.kill().unwrap();
- let _ = self.child.wait();
- }
- Ok(Some(status)) => panic!("deno lsp exited unexpectedly {}", status),
- Err(e) => panic!("pebble error: {}", e),
- }
- }
-}
-
-impl LspClient {
- fn new(deno_exe: &Path) -> Result<Self, AnyError> {
- let mut child = Command::new(deno_exe)
- .arg("lsp")
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .stderr(Stdio::null())
- .spawn()?;
-
- let stdout = child.stdout.take().unwrap();
- let reader = std::io::BufReader::new(stdout);
-
- let stdin = child.stdin.take().unwrap();
- let writer = std::io::BufWriter::new(stdin);
-
- Ok(Self {
- child,
- reader,
- request_id: 1,
- start: Instant::now(),
- writer,
- })
- }
-
- fn duration(&self) -> Duration {
- self.start.elapsed()
- }
-
- fn read(&mut self) -> Result<LspMessage, AnyError> {
- let msg_buf = read_message(&mut self.reader)?;
- let msg = LspMessage::from(msg_buf.as_slice());
- Ok(msg)
- }
-
- fn read_notification<R>(&mut self) -> Result<(String, Option<R>), AnyError>
- where
- R: de::DeserializeOwned,
- {
- loop {
- if let LspMessage::Notification(method, maybe_params) = self.read()? {
- if let Some(p) = maybe_params {
- let params = serde_json::from_value(p)?;
- return Ok((method, Some(params)));
- } else {
- return Ok((method, None));
- }
- }
- }
- }
-
- #[allow(unused)]
- fn read_request<R>(&mut self) -> Result<(u64, String, Option<R>), AnyError>
- where
- R: de::DeserializeOwned,
- {
- loop {
- if let LspMessage::Request(id, method, maybe_params) = self.read()? {
- if let Some(p) = maybe_params {
- let params = serde_json::from_value(p)?;
- return Ok((id, method, Some(params)));
- } else {
- return Ok((id, method, None));
- }
- }
- }
- }
-
- fn write(&mut self, value: Value) -> Result<(), AnyError> {
- let value_str = value.to_string();
- let msg = format!(
- "Content-Length: {}\r\n\r\n{}",
- value_str.as_bytes().len(),
- value_str
- );
- self.writer.write_all(msg.as_bytes())?;
- self.writer.flush()?;
- Ok(())
- }
-
- fn write_request<S, V>(
- &mut self,
- method: S,
- params: V,
- ) -> Result<(Option<Value>, Option<LspResponseError>), AnyError>
- where
- S: AsRef<str>,
- V: Serialize,
- {
- let value = json!({
- "jsonrpc": "2.0",
- "id": self.request_id,
- "method": method.as_ref(),
- "params": params,
- });
- self.write(value)?;
-
- loop {
- if let LspMessage::Response(id, result, error) = self.read()? {
- assert_eq!(id, self.request_id);
- self.request_id += 1;
- return Ok((result, error));
- }
- }
- }
-
- #[allow(unused)]
- fn write_response<V>(&mut self, id: u64, result: V) -> Result<(), AnyError>
- where
- V: Serialize,
- {
- let value = json!({
- "jsonrpc": "2.0",
- "id": id,
- "result": result
- });
- self.write(value)
- }
-
- fn write_notification<S, V>(
- &mut self,
- method: S,
- params: V,
- ) -> Result<(), AnyError>
- where
- S: AsRef<str>,
- V: Serialize,
- {
- let value = json!({
- "jsonrpc": "2.0",
- "method": method.as_ref(),
- "params": params,
- });
- self.write(value)?;
- Ok(())
- }
-}
-
/// A benchmark that opens a 8000+ line TypeScript document, adds a function to
/// the end of the document and does a level of hovering and gets quick fix
/// code actions.
@@ -320,19 +86,29 @@ fn bench_big_file_edits(deno_exe: &Path) -> Result<Duration, AnyError> {
for msg in messages {
match msg.fixture_type {
FixtureType::Action => {
- client.write_request("textDocument/codeAction", msg.params)?;
+ client.write_request::<_, _, Value>(
+ "textDocument/codeAction",
+ msg.params,
+ )?;
}
FixtureType::Change => {
client.write_notification("textDocument/didChange", msg.params)?;
}
FixtureType::Completion => {
- client.write_request("textDocument/completion", msg.params)?;
+ client.write_request::<_, _, Value>(
+ "textDocument/completion",
+ msg.params,
+ )?;
}
FixtureType::Highlight => {
- client.write_request("textDocument/documentHighlight", msg.params)?;
+ client.write_request::<_, _, Value>(
+ "textDocument/documentHighlight",
+ msg.params,
+ )?;
}
FixtureType::Hover => {
- client.write_request("textDocument/hover", msg.params)?;
+ client
+ .write_request::<_, _, Value>("textDocument/hover", msg.params)?;
}
}
}
@@ -427,13 +203,3 @@ pub(crate) fn benchmarks(
Ok(exec_times)
}
-
-#[cfg(test)]
-mod tests {
- #[test]
- fn test_read_message() {
- let msg = b"content-length: 11\r\n\r\nhello world";
- let reader = std::io::Cursor::new(msg);
- assert_eq!(read_message(reader).unwrap(), b"hello world");
- }
-}
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 1be65d0fe..9f5a7c84a 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -2608,2398 +2608,3 @@ impl Inner {
Ok(contents)
}
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::lsp::performance::PerformanceAverage;
- use lspower::jsonrpc;
- use lspower::ExitedError;
- use lspower::LspService;
- use std::fs;
- use std::task::Poll;
- use std::time::Instant;
- use tempfile::TempDir;
- use tower_test::mock::Spawn;
-
- enum LspResponse<V>
- where
- V: FnOnce(Value),
- {
- None,
- Delay(u64),
- RequestAny,
- Request(u64, Value),
- RequestAssert(V),
- RequestFixture(u64, String),
- }
-
- enum LspFixture {
- None,
- Path(&'static str),
- Value(Value),
- }
-
- type LspTestHarnessRequest = (LspFixture, LspResponse<fn(Value)>);
-
- struct LspTestHarness {
- requests: Vec<LspTestHarnessRequest>,
- service: Spawn<LspService>,
- }
-
- impl LspTestHarness {
- pub fn new(requests: Vec<LspTestHarnessRequest>) -> Self {
- let (service, _) = LspService::new(LanguageServer::new);
- let service = Spawn::new(service);
- Self { requests, service }
- }
-
- async fn run(&mut self) {
- for (value_or_str, expected) in self.requests.iter() {
- assert_eq!(self.service.poll_ready(), Poll::Ready(Ok(())));
- let fixtures_path = test_util::root_path().join("cli/tests/lsp");
- assert!(fixtures_path.is_dir());
- let response: Result<Option<jsonrpc::Outgoing>, ExitedError> =
- match value_or_str {
- LspFixture::None => Ok(None),
- LspFixture::Path(req_path_str) => {
- let req_path = fixtures_path.join(req_path_str);
- let req_str = fs::read_to_string(req_path).unwrap();
- let req: jsonrpc::Incoming =
- serde_json::from_str(&req_str).unwrap();
- self.service.call(req).await
- }
- LspFixture::Value(value) => {
- let req: jsonrpc::Incoming =
- serde_json::from_value(value.clone()).unwrap();
- self.service.call(req).await
- }
- };
- match response {
- Ok(result) => match expected {
- LspResponse::None => assert_eq!(result, None),
- LspResponse::Delay(millis) => {
- tokio::time::sleep(tokio::time::Duration::from_millis(*millis))
- .await
- }
- LspResponse::RequestAny => match result {
- Some(jsonrpc::Outgoing::Response(_)) => (),
- _ => panic!("unexpected result: {:?}", result),
- },
- LspResponse::Request(id, value) => match result {
- Some(jsonrpc::Outgoing::Response(resp)) => assert_eq!(
- resp,
- jsonrpc::Response::ok(jsonrpc::Id::Number(*id), value.clone())
- ),
- _ => panic!("unexpected result: {:?}", result),
- },
- LspResponse::RequestAssert(assert) => match result {
- Some(jsonrpc::Outgoing::Response(resp)) => assert(json!(resp)),
- _ => panic!("unexpected result: {:?}", result),
- },
- LspResponse::RequestFixture(id, res_path_str) => {
- let res_path = fixtures_path.join(res_path_str);
- let res_str = fs::read_to_string(res_path).unwrap();
- match result {
- Some(jsonrpc::Outgoing::Response(resp)) => assert_eq!(
- resp,
- jsonrpc::Response::ok(
- jsonrpc::Id::Number(*id),
- serde_json::from_str(&res_str).unwrap()
- )
- ),
- _ => panic!("unexpected result: {:?}", result),
- }
- }
- },
- Err(err) => panic!("Error result: {}", err),
- }
- }
- }
- }
-
- #[tokio::test]
- async fn test_startup_shutdown() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_hover() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("hover_request.json"),
- LspResponse::Request(
- 2,
- json!({
- "contents": [
- {
- "language": "typescript",
- "value": "const Deno.args: string[]"
- },
- "Returns the script arguments to the program. If for example we run a\nprogram:\n\ndeno run --allow-read https://deno.land/std/examples/cat.ts /etc/passwd\n\nThen `Deno.args` will contain:\n\n[ \"/etc/passwd\" ]"
- ],
- "range": {
- "start": {
- "line": 0,
- "character": 17
- },
- "end": {
- "line": 0,
- "character": 21
- }
- }
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_hover_asset() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_asset.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("definition_request_asset.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("virtual_text_document_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("hover_request_asset.json"),
- LspResponse::Request(
- 5,
- json!({
- "contents": [
- {
- "language": "typescript",
- "value": "interface Date",
- },
- "Enables basic storage and retrieval of dates and times."
- ],
- "range": {
- "start": {
- "line": 109,
- "character": 10,
- },
- "end": {
- "line": 109,
- "character": 14,
- }
- }
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_hover_disabled() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request_disabled.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("hover_request.json"),
- LspResponse::Request(2, json!(null)),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_hover_unstable_disabled() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_unstable.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("hover_request.json"),
- LspResponse::Request(
- 2,
- json!({
- "contents": [
- {
- "language": "typescript",
- "value": "any"
- }
- ],
- "range": {
- "start": {
- "line": 0,
- "character": 17
- },
- "end": {
- "line": 0,
- "character": 27
- }
- }
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_hover_unstable_enabled() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request_unstable.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_unstable.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("hover_request.json"),
- LspResponse::Request(
- 2,
- json!({
- "contents": [
- {
- "language": "typescript",
- "value": "function Deno.openPlugin(filename: string): number"
- },
- "**UNSTABLE**: new API, yet to be vetted.\n\nOpen and initialize a plugin.\n\n```ts\nconst rid = Deno.openPlugin(\"./path/to/some/plugin.so\");\nconst opId = Deno.core.ops()[\"some_op\"];\nconst response = Deno.core.dispatch(opId, new Uint8Array([1,2,3,4]));\nconsole.log(`Response from plugin ${response}`);\n```\n\nRequires `allow-plugin` permission.\n\nThe plugin system is not stable and will change in the future, hence the\nlack of docs. For now take a look at the example\nhttps://github.com/denoland/deno/tree/main/test_plugin"
- ],
- "range": {
- "start": {
- "line": 0,
- "character": 17
- },
- "end": {
- "line": 0,
- "character": 27
- }
- }
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_hover_change_mbc() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_mbc.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_change_notification_mbc.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("hover_request_mbc.json"),
- LspResponse::Request(
- 2,
- json!({
- "contents": [
- {
- "language": "typescript",
- "value": "const b: \"🦕😃\"",
- },
- "",
- ],
- "range": {
- "start": {
- "line": 2,
- "character": 15,
- },
- "end": {
- "line": 2,
- "character": 16,
- },
- }
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[derive(Deserialize)]
- struct HoverResponse {
- pub result: Option<Hover>,
- }
-
- #[tokio::test]
- async fn test_hover_closed_document() {
- let temp_dir = TempDir::new()
- .expect("could not create temp dir")
- .into_path();
- let a_path = temp_dir.join("a.ts");
- fs::write(a_path, r#"export const a = "a";"#)
- .expect("could not write file");
- let b_path = temp_dir.join("b.ts");
- fs::write(&b_path, r#"export * from "./a.ts";"#)
- .expect("could not write file");
- let b_specifier =
- Url::from_file_path(b_path).expect("could not convert path");
- let c_path = temp_dir.join("c.ts");
- fs::write(&c_path, "import { a } from \"./b.ts\";\nconsole.log(a);\n")
- .expect("could not write file");
- let c_specifier =
- Url::from_file_path(c_path).expect("could not convert path");
-
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Value(json!({
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": b_specifier,
- "languageId": "typescript",
- "version": 1,
- "text": r#"export * from "./a.ts";"#
- }
- }
- })),
- LspResponse::None,
- ),
- (
- LspFixture::Value(json!({
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": c_specifier,
- "languageId": "typescript",
- "version": 1,
- "text": "import { a } from \"./b.ts\";\nconsole.log(a);\n",
- }
- }
- })),
- LspResponse::None,
- ),
- (
- LspFixture::Value(json!({
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/hover",
- "params": {
- "textDocument": {
- "uri": c_specifier,
- },
- "position": {
- "line": 0,
- "character": 10
- }
- }
- })),
- LspResponse::RequestAssert(|value| {
- let resp: HoverResponse = serde_json::from_value(value).unwrap();
- if let Some(hover) = resp.result {
- assert_eq!(
- hover,
- Hover {
- contents: HoverContents::Array(vec![
- MarkedString::LanguageString(LanguageString {
- language: "typescript".to_string(),
- value: "(alias) const a: \"a\"\nimport a".to_string()
- }),
- MarkedString::String("".to_string()),
- ]),
- range: Some(Range {
- start: Position {
- line: 0,
- character: 9,
- },
- end: Position {
- line: 0,
- character: 10,
- }
- }),
- }
- );
- } else {
- panic!("no response");
- }
- }),
- ),
- (
- LspFixture::Value(json!({
- "jsonrpc": "2.0",
- "method": "textDocument/didClose",
- "params": {
- "textDocument": {
- "uri": b_specifier,
- }
- }
- })),
- LspResponse::None,
- ),
- (
- LspFixture::Value(json!({
- "jsonrpc": "2.0",
- "id": 4,
- "method": "textDocument/hover",
- "params": {
- "textDocument": {
- "uri": c_specifier,
- },
- "position": {
- "line": 0,
- "character": 10
- }
- }
- })),
- LspResponse::RequestAssert(|value| {
- let resp: HoverResponse = serde_json::from_value(value).unwrap();
- if let Some(hover) = resp.result {
- assert_eq!(
- hover,
- Hover {
- contents: HoverContents::Array(vec![
- MarkedString::LanguageString(LanguageString {
- language: "typescript".to_string(),
- value: "(alias) const a: \"a\"\nimport a".to_string()
- }),
- MarkedString::String("".to_string()),
- ]),
- range: Some(Range {
- start: Position {
- line: 0,
- character: 9,
- },
- end: Position {
- line: 0,
- character: 10,
- }
- }),
- }
- );
- } else {
- panic!("no response");
- }
- }),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_call_hierarchy() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("prepare_call_hierarchy_did_open_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("prepare_call_hierarchy_request.json"),
- LspResponse::Request(
- 2,
- json!([
- {
- "name": "baz",
- "kind": 6,
- "detail": "Bar",
- "uri": "file:///a/file.ts",
- "range": {
- "start": {
- "line": 5,
- "character": 2
- },
- "end": {
- "line": 7,
- "character": 3
- }
- },
- "selectionRange": {
- "start": {
- "line": 5,
- "character": 2
- },
- "end": {
- "line": 5,
- "character": 5
- }
- }
- }
- ]),
- ),
- ),
- (
- LspFixture::Path("incoming_calls_request.json"),
- LspResponse::Request(
- 4,
- json!([
- {
- "from": {
- "name": "main",
- "kind": 12,
- "detail": "",
- "uri": "file:///a/file.ts",
- "range": {
- "start": {
- "line": 10,
- "character": 0
- },
- "end": {
- "line": 13,
- "character": 1
- }
- },
- "selectionRange": {
- "start": {
- "line": 10,
- "character": 9
- },
- "end": {
- "line": 10,
- "character": 13
- }
- }
- },
- "fromRanges": [
- {
- "start": {
- "line": 12,
- "character": 6
- },
- "end": {
- "line": 12,
- "character": 9
- }
- }
- ]
- }
- ]),
- ),
- ),
- (
- LspFixture::Path("outgoing_calls_request.json"),
- LspResponse::Request(
- 5,
- json!([
- {
- "to": {
- "name": "foo",
- "kind": 12,
- "detail": "",
- "uri": "file:///a/file.ts",
- "range": {
- "start": {
- "line": 0,
- "character": 0
- },
- "end": {
- "line": 2,
- "character": 1
- }
- },
- "selectionRange": {
- "start": {
- "line": 0,
- "character": 9
- },
- "end": {
- "line": 0,
- "character": 12
- }
- }
- },
- "fromRanges": [
- {
- "start": {
- "line": 6,
- "character": 11
- },
- "end": {
- "line": 6,
- "character": 14
- }
- }
- ]
- }
- ]),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_format_mbc() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_mbc_fmt.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("formatting_request_mbc_fmt.json"),
- LspResponse::Request(
- 2,
- json!([
- {
- "range": {
- "start": {
- "line": 0,
- "character": 12
- },
- "end": {
- "line": 0,
- "character": 13,
- }
- },
- "newText": "\""
- },
- {
- "range": {
- "start": {
- "line": 0,
- "character": 21
- },
- "end": {
- "line": 0,
- "character": 22
- }
- },
- "newText": "\";"
- },
- {
- "range": {
- "start": {
- "line": 1,
- "character": 12,
- },
- "end": {
- "line": 1,
- "character": 13,
- }
- },
- "newText": "\""
- },
- {
- "range": {
- "start": {
- "line": 1,
- "character": 23,
- },
- "end": {
- "line": 1,
- "character": 25,
- }
- },
- "newText": "\");"
- }
- ]),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- #[ignore] // TODO(ry) Re-enable. Flaky on ubuntu-latest-xl.
- async fn test_large_doc_change() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_large.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_change_notification_large.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_change_notification_large_02.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_change_notification_large_03.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("hover_request_large_01.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("hover_request_large_02.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("hover_request_large_03.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- let time = Instant::now();
- harness.run().await;
- assert!(
- time.elapsed().as_millis() <= 10000,
- "the execution time exceeded 10000ms"
- );
- }
-
- #[tokio::test]
- async fn test_document_symbol() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("document_symbol_did_open_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("document_symbol_request.json"),
- LspResponse::Request(
- 2,
- json!([
- {
- "name": "bar",
- "kind": 13,
- "range": {
- "start": {
- "line": 17,
- "character": 4
- },
- "end": {
- "line": 17,
- "character": 26
- }
- },
- "selectionRange": {
- "start": {
- "line": 17,
- "character": 4
- },
- "end": {
- "line": 17,
- "character": 7
- }
- }
- },
- {
- "name": "Bar",
- "kind": 5,
- "range": {
- "start": {
- "line": 4,
- "character": 0
- },
- "end": {
- "line": 13,
- "character": 1
- }
- },
- "selectionRange": {
- "start": {
- "line": 4,
- "character": 6
- },
- "end": {
- "line": 4,
- "character": 9
- }
- },
- "children": [
- {
- "name": "constructor",
- "kind": 9,
- "range": {
- "start": {
- "line": 5,
- "character": 2
- },
- "end": {
- "line": 5,
- "character": 35
- }
- },
- "selectionRange": {
- "start": {
- "line": 5,
- "character": 2
- },
- "end": {
- "line": 5,
- "character": 35
- }
- }
- },
- {
- "name": "baz",
- "kind": 6,
- "tags": [
- 1
- ],
- "range": {
- "start": {
- "line": 8,
- "character": 2
- },
- "end": {
- "line": 8,
- "character": 25
- }
- },
- "selectionRange": {
- "start": {
- "line": 8,
- "character": 2
- },
- "end": {
- "line": 8,
- "character": 5
- }
- }
- },
- {
- "name": "foo",
- "kind": 6,
- "range": {
- "start": {
- "line": 6,
- "character": 2
- },
- "end": {
- "line": 6,
- "character": 24
- }
- },
- "selectionRange": {
- "start": {
- "line": 6,
- "character": 2
- },
- "end": {
- "line": 6,
- "character": 5
- }
- }
- },
- {
- "name": "getStaticBar",
- "kind": 6,
- "range": {
- "start": {
- "line": 12,
- "character": 2
- },
- "end": {
- "line": 12,
- "character": 57
- }
- },
- "selectionRange": {
- "start": {
- "line": 12,
- "character": 17
- },
- "end": {
- "line": 12,
- "character": 29
- }
- }
- },
- {
- "name": "staticBar",
- "kind": 7,
- "range": {
- "start": {
- "line": 11,
- "character": 2
- },
- "end": {
- "line": 11,
- "character": 32
- }
- },
- "selectionRange": {
- "start": {
- "line": 11,
- "character": 9
- },
- "end": {
- "line": 11,
- "character": 18
- }
- }
- },
- {
- "name": "value",
- "kind": 7,
- "range": {
- "start": {
- "line": 9,
- "character": 2
- },
- "end": {
- "line": 9,
- "character": 35
- }
- },
- "selectionRange": {
- "start": {
- "line": 9,
- "character": 6
- },
- "end": {
- "line": 9,
- "character": 11
- }
- }
- },
- {
- "name": "value",
- "kind": 7,
- "range": {
- "start": {
- "line": 10,
- "character": 2
- },
- "end": {
- "line": 10,
- "character": 42
- }
- },
- "selectionRange": {
- "start": {
- "line": 10,
- "character": 6
- },
- "end": {
- "line": 10,
- "character": 11
- }
- }
- },
- {
- "name": "x",
- "kind": 7,
- "range": {
- "start": {
- "line": 5,
- "character": 14
- },
- "end": {
- "line": 5,
- "character": 30
- }
- },
- "selectionRange": {
- "start": {
- "line": 5,
- "character": 21
- },
- "end": {
- "line": 5,
- "character": 22
- }
- }
- }
- ]
- },
- {
- "name": "IFoo",
- "kind": 11,
- "range": {
- "start": {
- "line": 0,
- "character": 0
- },
- "end": {
- "line": 2,
- "character": 1
- }
- },
- "selectionRange": {
- "start": {
- "line": 0,
- "character": 10
- },
- "end": {
- "line": 0,
- "character": 14
- }
- },
- "children": [
- {
- "name": "foo",
- "kind": 6,
- "range": {
- "start": {
- "line": 1,
- "character": 2
- },
- "end": {
- "line": 1,
- "character": 17
- }
- },
- "selectionRange": {
- "start": {
- "line": 1,
- "character": 2
- },
- "end": {
- "line": 1,
- "character": 5
- }
- }
- }
- ]
- },
- {
- "name": "Values",
- "kind": 10,
- "range": {
- "start": {
- "line": 15,
- "character": 0
- },
- "end": {
- "line": 15,
- "character": 30
- }
- },
- "selectionRange": {
- "start": {
- "line": 15,
- "character": 5
- },
- "end": {
- "line": 15,
- "character": 11
- }
- },
- "children": [
- {
- "name": "value1",
- "kind": 13,
- "range": {
- "start": {
- "line": 15,
- "character": 14
- },
- "end": {
- "line": 15,
- "character": 20
- }
- },
- "selectionRange": {
- "start": {
- "line": 15,
- "character": 14
- },
- "end": {
- "line": 15,
- "character": 20
- }
- }
- },
- {
- "name": "value2",
- "kind": 13,
- "range": {
- "start": {
- "line": 15,
- "character": 22
- },
- "end": {
- "line": 15,
- "character": 28
- }
- },
- "selectionRange": {
- "start": {
- "line": 15,
- "character": 22
- },
- "end": {
- "line": 15,
- "character": 28
- }
- }
- }
- ]
- }
- ]),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_folding_range() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("folding_range_did_open_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("folding_range_request.json"),
- LspResponse::Request(
- 2,
- json!([
- {
- "startLine": 0,
- "endLine": 12,
- "kind": "region"
- },
- {
- "startLine": 1,
- "endLine": 3,
- "kind": "comment"
- },
- {
- "startLine": 4,
- "endLine": 10
- },
- {
- "startLine": 5,
- "endLine": 9
- },
- {
- "startLine": 6,
- "endLine": 7
- }
- ]),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_rename() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("rename_did_open_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("rename_request.json"),
- LspResponse::Request(
- 2,
- json!({
- "documentChanges": [{
- "textDocument": {
- "uri": "file:///a/file.ts",
- "version": 1,
- },
- "edits": [{
- "range": {
- "start": {
- "line": 0,
- "character": 4
- },
- "end": {
- "line": 0,
- "character": 12
- }
- },
- "newText": "variable_modified"
- }, {
- "range": {
- "start": {
- "line": 1,
- "character": 12
- },
- "end": {
- "line": 1,
- "character": 20
- }
- },
- "newText": "variable_modified"
- }]
- }]
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_selection_range() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("selection_range_did_open_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("selection_range_request.json"),
- LspResponse::Request(
- 2,
- json!([{
- "range": {
- "start": {
- "line": 2,
- "character": 8
- },
- "end": {
- "line": 2,
- "character": 9
- }
- },
- "parent": {
- "range": {
- "start": {
- "line": 2,
- "character": 8
- },
- "end": {
- "line": 2,
- "character": 15
- }
- },
- "parent": {
- "range": {
- "start": {
- "line": 2,
- "character": 4
- },
- "end": {
- "line": 4,
- "character": 5
- }
- },
- "parent": {
- "range": {
- "start": {
- "line": 1,
- "character": 13
- },
- "end": {
- "line": 6,
- "character": 2
- }
- },
- "parent": {
- "range": {
- "start": {
- "line": 1,
- "character": 2
- },
- "end": {
- "line": 6,
- "character": 3
- }
- },
- "parent": {
- "range": {
- "start": {
- "line": 0,
- "character": 11
- },
- "end": {
- "line": 7,
- "character": 0
- }
- },
- "parent": {
- "range": {
- "start": {
- "line": 0,
- "character": 0
- },
- "end": {
- "line": 7,
- "character": 1
- }
- }
- }
- }
- }
- }
- }
- }
- }]),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- #[rustfmt::skip]
- async fn test_semantic_tokens() {
- let mut harness = LspTestHarness::new(vec![
- (LspFixture::Path("initialize_request.json"), LspResponse::RequestAny),
- (LspFixture::Path("initialized_notification.json"), LspResponse::None),
- (
- LspFixture::Path("semantic_tokens_did_open_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("semantic_tokens_full_request.json"),
- LspResponse::Request(
- 2,
- json!({
- "data": [0, 5, 6, 1, 1, 0, 9, 6, 8, 9, 0, 8, 6, 8, 9, 2, 15 ,3, 10 ,5, 0, 4, 1, 6, 1, 0, 12 ,7, 2, 16 ,1, 8, 1, 7, 41 ,0, 4, 1, 6, 0, 0, 2, 5, 11 ,16 ,1, 9, 1, 7, 40 ,3, 10 ,4, 2, 1, 1, 11 ,1, 9, 9, 1, 2, 3, 11 ,1, 3, 6, 3, 0, 1, 0, 15 ,4, 2, 0, 1, 30 ,1, 6, 9, 1, 2, 3, 11 ,1, 1, 9, 9, 9, 3, 0, 16 ,3, 0, 0, 1, 17 ,12 ,11 ,3, 0, 24 ,3, 0, 0, 0, 4, 9, 9, 2]
- }),
- ),
- ),
- (
- LspFixture::Path("semantic_tokens_range_request.json"),
- LspResponse::Request(
- 4,
- json!({
- "data": [0, 5, 6, 1, 1, 0, 9, 6, 8, 9, 0, 8, 6, 8, 9, 2, 15 ,3, 10 ,5, 0, 4, 1, 6, 1, 0, 12 ,7, 2, 16 ,1, 8, 1, 7, 41 ,0, 4, 1, 6, 0, 0, 2, 5, 11 ,16 ,1, 9, 1, 7, 40]
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (LspFixture::Path("exit_notification.json"), LspResponse::None),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_code_lens_request() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_cl_references.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("code_lens_request.json"),
- LspResponse::Request(
- 2,
- json!([
- {
- "range": {
- "start": {
- "line": 0,
- "character": 6,
- },
- "end": {
- "line": 0,
- "character": 7,
- }
- },
- "data": {
- "specifier": "file:///a/file.ts",
- "source": "references",
- },
- },
- {
- "range": {
- "start": {
- "line": 1,
- "character": 2,
- },
- "end": {
- "line": 1,
- "character": 3,
- }
- },
- "data": {
- "specifier": "file:///a/file.ts",
- "source": "references",
- }
- }
- ]),
- ),
- ),
- (
- LspFixture::Path("code_lens_resolve_request.json"),
- LspResponse::Request(
- 4,
- json!({
- "range": {
- "start": {
- "line": 0,
- "character": 6,
- },
- "end": {
- "line": 0,
- "character": 7,
- }
- },
- "command": {
- "title": "1 reference",
- "command": "deno.showReferences",
- "arguments": [
- "file:///a/file.ts",
- {
- "line": 0,
- "character": 6,
- },
- [
- {
- "uri": "file:///a/file.ts",
- "range": {
- "start": {
- "line": 12,
- "character": 14,
- },
- "end": {
- "line": 12,
- "character": 15,
- }
- }
- }
- ],
- ]
- }
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_signature_help() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("signature_help_did_open_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("signature_help_request_01.json"),
- LspResponse::Request(
- 1,
- json!({
- "signatures": [
- {
- "label": "add(a: number, b: number): number",
- "documentation": "Adds two numbers.",
- "parameters": [
- {
- "label": "a: number",
- "documentation": "This is a first number."
- },
- {
- "label": "b: number",
- "documentation": "This is a second number."
- }
- ]
- }
- ],
- "activeSignature": 0,
- "activeParameter": 0
- }),
- ),
- ),
- (
- LspFixture::Path("signature_help_did_change_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("signature_help_request_02.json"),
- LspResponse::Request(
- 2,
- json!({
- "signatures": [
- {
- "label": "add(a: number, b: number): number",
- "documentation": "Adds two numbers.",
- "parameters": [
- {
- "label": "a: number",
- "documentation": "This is a first number."
- },
- {
- "label": "b: number",
- "documentation": "This is a second number."
- }
- ]
- }
- ],
- "activeSignature": 0,
- "activeParameter": 1
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_code_lens_impl_request() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_cl_impl.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("code_lens_request.json"),
- LspResponse::Request(
- 2,
- json!([
- {
- "range": {
- "start": {
- "line": 0,
- "character": 10,
- },
- "end": {
- "line": 0,
- "character": 11,
- }
- },
- "data": {
- "specifier": "file:///a/file.ts",
- "source": "implementations",
- },
- },
- {
- "range": {
- "start": {
- "line": 0,
- "character": 10,
- },
- "end": {
- "line": 0,
- "character": 11,
- }
- },
- "data": {
- "specifier": "file:///a/file.ts",
- "source": "references",
- },
- },
- {
- "range": {
- "start": {
- "line": 4,
- "character": 6,
- },
- "end": {
- "line": 4,
- "character": 7,
- }
- },
- "data": {
- "specifier": "file:///a/file.ts",
- "source": "references",
- },
- },
- ]),
- ),
- ),
- (
- LspFixture::Path("code_lens_resolve_request_impl.json"),
- LspResponse::Request(
- 4,
- json!({
- "range": {
- "start": {
- "line": 0,
- "character": 10,
- },
- "end": {
- "line": 0,
- "character": 11,
- }
- },
- "command": {
- "title": "1 implementation",
- "command": "deno.showReferences",
- "arguments": [
- "file:///a/file.ts",
- {
- "line": 0,
- "character": 10,
- },
- [
- {
- "uri": "file:///a/file.ts",
- "range": {
- "start": {
- "line": 4,
- "character": 6,
- },
- "end": {
- "line": 4,
- "character": 7,
- }
- }
- }
- ],
- ]
- }
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[derive(Deserialize)]
- struct CodeLensResponse {
- pub result: Option<Vec<CodeLens>>,
- }
-
- #[derive(Deserialize)]
- struct CodeLensResolveResponse {
- pub result: CodeLens,
- }
-
- #[tokio::test]
- async fn test_code_lens_non_doc_nav_tree() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_asset.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("references_request_asset.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("virtual_text_document_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("code_lens_request_asset.json"),
- LspResponse::RequestAssert(|value| {
- let resp: CodeLensResponse = serde_json::from_value(value).unwrap();
- let lenses = resp.result.unwrap();
- assert!(lenses.len() > 50);
- }),
- ),
- (
- LspFixture::Path("code_lens_resolve_request_asset.json"),
- LspResponse::RequestAssert(|value| {
- let resp: CodeLensResolveResponse =
- serde_json::from_value(value).unwrap();
- assert!(resp.result.command.is_some());
- }),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_code_actions() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_code_action.json"),
- LspResponse::None,
- ),
- (LspFixture::None, LspResponse::Delay(20000)),
- (
- LspFixture::Path("code_action_request.json"),
- LspResponse::RequestFixture(2, "code_action_response.json".to_string()),
- ),
- (
- LspFixture::Path("code_action_resolve_request.json"),
- LspResponse::RequestFixture(
- 4,
- "code_action_resolve_request_response.json".to_string(),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_code_actions_deno_cache() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_cache.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("code_action_request_cache.json"),
- LspResponse::RequestFixture(
- 2,
- "code_action_response_cache.json".to_string(),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[derive(Deserialize)]
- struct CompletionResult {
- pub result: Option<CompletionResponse>,
- }
-
- #[tokio::test]
- async fn test_completions() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_completions.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("completion_request.json"),
- LspResponse::RequestAssert(|value| {
- let response: CompletionResult =
- serde_json::from_value(value).unwrap();
- let result = response.result.unwrap();
- match result {
- CompletionResponse::List(list) => {
- // there should be at least 90 completions for `Deno.`
- assert!(list.items.len() > 90);
- }
- _ => panic!("unexpected result"),
- }
- }),
- ),
- (
- LspFixture::Path("completion_resolve_request.json"),
- LspResponse::Request(
- 4,
- json!({
- "label": "build",
- "kind": 6,
- "detail": "const Deno.build: {\n target: string;\n arch: \"x86_64\" | \"aarch64\";\n os: \"darwin\" | \"linux\" | \"windows\";\n vendor: string;\n env?: string | undefined;\n}",
- "documentation": {
- "kind": "markdown",
- "value": "Build related information."
- },
- "sortText": "1",
- "insertTextFormat": 1,
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_completions_optional() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_completion_optional.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("completion_request_optional.json"),
- LspResponse::Request(
- 2,
- json!({
- "isIncomplete": false,
- "items": [
- {
- "label": "b?",
- "kind": 5,
- "sortText": "1",
- "filterText": "b",
- "insertText": "b",
- "data": {
- "tsc": {
- "specifier": "file:///a/file.ts",
- "position": 79,
- "name": "b",
- "useCodeSnippet": false
- }
- }
- }
- ]
- }),
- ),
- ),
- (
- LspFixture::Path("completion_resolve_request_optional.json"),
- LspResponse::Request(
- 4,
- json!({
- "label": "b?",
- "kind": 5,
- "detail": "(property) A.b?: string | undefined",
- "documentation": {
- "kind": "markdown",
- "value": ""
- },
- "sortText": "1",
- "filterText": "b",
- "insertText": "b"
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_completions_registry() {
- let _g = test_util::http_server();
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request_registry.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_completion_registry.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("completion_request_registry.json"),
- LspResponse::RequestAssert(|value| {
- let response: CompletionResult =
- serde_json::from_value(value).unwrap();
- let result = response.result.unwrap();
- if let CompletionResponse::List(list) = result {
- assert_eq!(list.items.len(), 3);
- } else {
- panic!("unexpected result");
- }
- }),
- ),
- (
- LspFixture::Path("completion_resolve_request_registry.json"),
- LspResponse::Request(
- 4,
- json!({
- "label": "v2.0.0",
- "kind": 19,
- "detail": "(version)",
- "sortText": "0000000003",
- "filterText": "http://localhost:4545/x/a@v2.0.0",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 20
- },
- "end": {
- "line": 0,
- "character": 46
- }
- },
- "newText": "http://localhost:4545/x/a@v2.0.0"
- }
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[tokio::test]
- async fn test_completion_registry_empty_specifier() {
- let _g = test_util::http_server();
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request_registry.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification_completion_registry_02.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("completion_request_registry_02.json"),
- LspResponse::Request(
- 2,
- json!({
- "isIncomplete": false,
- "items": [
- {
- "label": ".",
- "kind": 19,
- "detail": "(local)",
- "sortText": "1",
- "insertText": "."
- },
- {
- "label": "..",
- "kind": 19,
- "detail": "(local)",
- "sortText": "1",
- "insertText": ".."
- },
- {
- "label": "http://localhost:4545",
- "kind": 19,
- "detail": "(registry)",
- "sortText": "2",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 20
- },
- "end": {
- "line": 0,
- "character": 20
- }
- },
- "newText": "http://localhost:4545"
- }
- }
- ]
- }),
- ),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-
- #[derive(Deserialize)]
- struct PerformanceAverages {
- averages: Vec<PerformanceAverage>,
- }
- #[derive(Deserialize)]
- struct PerformanceResponse {
- result: PerformanceAverages,
- }
-
- #[tokio::test]
- async fn test_deno_performance_request() {
- let mut harness = LspTestHarness::new(vec![
- (
- LspFixture::Path("initialize_request.json"),
- LspResponse::RequestAny,
- ),
- (
- LspFixture::Path("initialized_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("did_open_notification.json"),
- LspResponse::None,
- ),
- (
- LspFixture::Path("hover_request.json"),
- LspResponse::Request(
- 2,
- json!({
- "contents": [
- {
- "language": "typescript",
- "value": "const Deno.args: string[]"
- },
- "Returns the script arguments to the program. If for example we run a\nprogram:\n\ndeno run --allow-read https://deno.land/std/examples/cat.ts /etc/passwd\n\nThen `Deno.args` will contain:\n\n[ \"/etc/passwd\" ]"
- ],
- "range": {
- "start": {
- "line": 0,
- "character": 17
- },
- "end": {
- "line": 0,
- "character": 21
- }
- }
- }),
- ),
- ),
- (
- LspFixture::Path("performance_request.json"),
- LspResponse::RequestAssert(|value| {
- let resp: PerformanceResponse =
- serde_json::from_value(value).unwrap();
- // the len can be variable since some of the parts of the language
- // server run in separate threads and may not add to performance by
- // the time the results are checked.
- assert!(resp.result.averages.len() >= 6);
- }),
- ),
- (
- LspFixture::Path("shutdown_request.json"),
- LspResponse::Request(3, json!(null)),
- ),
- (
- LspFixture::Path("exit_notification.json"),
- LspResponse::None,
- ),
- ]);
- harness.run().await;
- }
-}
diff --git a/cli/tests/integration_tests_lsp.rs b/cli/tests/integration_tests_lsp.rs
new file mode 100644
index 000000000..6b0f6b792
--- /dev/null
+++ b/cli/tests/integration_tests_lsp.rs
@@ -0,0 +1,1661 @@
+// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
+
+use deno_core::serde::Deserialize;
+use deno_core::serde::Serialize;
+use deno_core::serde_json;
+use deno_core::serde_json::json;
+use deno_core::serde_json::Value;
+use deno_core::url::Url;
+use lspower::lsp;
+use std::fs;
+use tempfile::TempDir;
+use test_util::deno_exe_path;
+use test_util::http_server;
+use test_util::lsp::LspClient;
+use test_util::root_path;
+
+fn load_fixture(path: &str) -> Value {
+ let fixtures_path = root_path().join("cli/tests/lsp");
+ let path = fixtures_path.join(path);
+ let fixture_str = fs::read_to_string(path).unwrap();
+ serde_json::from_str(&fixture_str).unwrap()
+}
+
+fn init(init_path: &str) -> LspClient {
+ let deno_exe = deno_exe_path();
+ let mut client = LspClient::new(&deno_exe).unwrap();
+ client
+ .write_request::<_, _, Value>("initialize", load_fixture(init_path))
+ .unwrap();
+ client.write_notification("initialized", json!({})).unwrap();
+ client
+}
+
+fn did_open<V>(client: &mut LspClient, params: V)
+where
+ V: Serialize,
+{
+ client
+ .write_notification("textDocument/didOpen", params)
+ .unwrap();
+ let (method, _) = client.read_notification::<Value>().unwrap();
+ assert_eq!(method, "textDocument/publishDiagnostics");
+ let (method, _) = client.read_notification::<Value>().unwrap();
+ assert_eq!(method, "textDocument/publishDiagnostics");
+ let (method, _) = client.read_notification::<Value>().unwrap();
+ assert_eq!(method, "textDocument/publishDiagnostics");
+}
+
+fn shutdown(client: &mut LspClient) {
+ client
+ .write_request::<_, _, Value>("shutdown", json!(null))
+ .unwrap();
+ client.write_notification("exit", json!(null)).unwrap();
+}
+
+#[test]
+fn lsp_startup_shutdown() {
+ let mut client = init("initialize_params.json");
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_hover() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "console.log(Deno.args);\n"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 19
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "contents": [
+ {
+ "language": "typescript",
+ "value": "const Deno.args: string[]"
+ },
+ "Returns the script arguments to the program. If for example we run a\nprogram:\n\ndeno run --allow-read https://deno.land/std/examples/cat.ts /etc/passwd\n\nThen `Deno.args` will contain:\n\n[ \"/etc/passwd\" ]"
+ ],
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 17
+ },
+ "end": {
+ "line": 0,
+ "character": 21
+ }
+ }
+ }))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_hover_asset() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "console.log(Date.now());\n"
+ }
+ }),
+ );
+ let (_, maybe_error) = client
+ .write_request::<_, _, Value>(
+ "textDocument/definition",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 14
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_error.is_none());
+ let (_, maybe_error) = client
+ .write_request::<_, _, Value>(
+ "deno/virtualTextDocument",
+ json!({
+ "textDocument": {
+ "uri": "deno:/asset//lib.deno.shared_globals.d.ts"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_error.is_none());
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "deno:/asset//lib.es2015.symbol.wellknown.d.ts"
+ },
+ "position": {
+ "line": 109,
+ "character": 13
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "contents": [
+ {
+ "language": "typescript",
+ "value": "interface Date",
+ },
+ "Enables basic storage and retrieval of dates and times."
+ ],
+ "range": {
+ "start": {
+ "line": 109,
+ "character": 10,
+ },
+ "end": {
+ "line": 109,
+ "character": 14,
+ }
+ }
+ }))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_hover_disabled() {
+ let mut client = init("initialize_params_disabled.json");
+ client
+ .write_notification(
+ "textDocument/didOpen",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "console.log(Date.now());\n"
+ }
+ }),
+ )
+ .unwrap();
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 19
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(maybe_res, Some(json!(null)));
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_hover_unstable_disabled() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "console.log(Deno.openPlugin);\n"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 19
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "contents": [
+ {
+ "language": "typescript",
+ "value": "any"
+ }
+ ],
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 17
+ },
+ "end": {
+ "line": 0,
+ "character": 27
+ }
+ }
+ }))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_hover_unstable_enabled() {
+ let mut client = init("initialize_params_unstable.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "console.log(Deno.openPlugin);\n"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 19
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "contents":[
+ {
+ "language":"typescript",
+ "value":"function Deno.openPlugin(filename: string): number"
+ },
+ "**UNSTABLE**: new API, yet to be vetted.\n\nOpen and initialize a plugin.\n\n```ts\nconst rid = Deno.openPlugin(\"./path/to/some/plugin.so\");\nconst opId = Deno.core.ops()[\"some_op\"];\nconst response = Deno.core.dispatch(opId, new Uint8Array([1,2,3,4]));\nconsole.log(`Response from plugin ${response}`);\n```\n\nRequires `allow-plugin` permission.\n\nThe plugin system is not stable and will change in the future, hence the\nlack of docs. For now take a look at the example\nhttps://github.com/denoland/deno/tree/main/test_plugin"
+ ],
+ "range":{
+ "start":{
+ "line":0,
+ "character":17
+ },
+ "end":{
+ "line":0,
+ "character":27
+ }
+ }
+ }))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_hover_change_mbc() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "const a = `编写软件很难`;\nconst b = `👍🦕😃`;\nconsole.log(a, b);\n"
+ }
+ }),
+ );
+ client
+ .write_notification(
+ "textDocument/didChange",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "version": 2
+ },
+ "contentChanges": [
+ {
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 11
+ },
+ "end": {
+ "line": 1,
+ "character": 13
+ }
+ },
+ "text": ""
+ }
+ ]
+ }),
+ )
+ .unwrap();
+ let (method, _) = client.read_notification::<Value>().unwrap();
+ assert_eq!(method, "textDocument/publishDiagnostics");
+ let (method, _) = client.read_notification::<Value>().unwrap();
+ assert_eq!(method, "textDocument/publishDiagnostics");
+ let (method, _) = client.read_notification::<Value>().unwrap();
+ assert_eq!(method, "textDocument/publishDiagnostics");
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 2,
+ "character": 14
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "contents": [
+ {
+ "language": "typescript",
+ "value": "const b: \"😃\"",
+ },
+ "",
+ ],
+ "range": {
+ "start": {
+ "line": 2,
+ "character": 13,
+ },
+ "end": {
+ "line": 2,
+ "character": 14,
+ },
+ }
+ }))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_hover_closed_document() {
+ let temp_dir = TempDir::new()
+ .expect("could not create temp dir")
+ .into_path();
+ let a_path = temp_dir.join("a.ts");
+ fs::write(a_path, r#"export const a = "a";"#).expect("could not write file");
+ let b_path = temp_dir.join("b.ts");
+ fs::write(&b_path, r#"export * from "./a.ts";"#)
+ .expect("could not write file");
+ let b_specifier =
+ Url::from_file_path(b_path).expect("could not convert path");
+ let c_path = temp_dir.join("c.ts");
+ fs::write(&c_path, "import { a } from \"./b.ts\";\nconsole.log(a);\n")
+ .expect("could not write file");
+ let c_specifier =
+ Url::from_file_path(c_path).expect("could not convert path");
+
+ let mut client = init("initialize_params.json");
+ client
+ .write_notification(
+ "textDocument/didOpen",
+ json!({
+ "textDocument": {
+ "uri": b_specifier,
+ "languageId": "typescript",
+ "version": 1,
+ "text": r#"export * from "./a.ts";"#
+ }
+ }),
+ )
+ .unwrap();
+ client
+ .write_notification(
+ "textDocument/didOpen",
+ json!({
+ "textDocument": {
+ "uri": c_specifier,
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import { a } from \"./b.ts\";\nconsole.log(a);\n",
+ }
+ }),
+ )
+ .unwrap();
+ let (method, _) = client.read_notification::<Value>().unwrap();
+ assert_eq!(method, "textDocument/publishDiagnostics");
+ let (method, _) = client.read_notification::<Value>().unwrap();
+ assert_eq!(method, "textDocument/publishDiagnostics");
+ let (method, _) = client.read_notification::<Value>().unwrap();
+ assert_eq!(method, "textDocument/publishDiagnostics");
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": c_specifier,
+ },
+ "position": {
+ "line": 0,
+ "character": 10
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "contents": [
+ {
+ "language": "typescript",
+ "value": "(alias) const a: \"a\"\nimport a"
+ },
+ ""
+ ],
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 9
+ },
+ "end": {
+ "line": 0,
+ "character": 10
+ }
+ }
+ }))
+ );
+ client
+ .write_notification(
+ "textDocument/didClose",
+ json!({
+ "textDocument": {
+ "uri": b_specifier,
+ }
+ }),
+ )
+ .unwrap();
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": c_specifier,
+ },
+ "position": {
+ "line": 0,
+ "character": 10
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "contents": [
+ {
+ "language": "typescript",
+ "value": "(alias) const a: \"a\"\nimport a"
+ },
+ ""
+ ],
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 9
+ },
+ "end": {
+ "line": 0,
+ "character": 10
+ }
+ }
+ }))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_call_hierarchy() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "function foo() {\n return false;\n}\n\nclass Bar {\n baz() {\n return foo();\n }\n}\n\nfunction main() {\n const bar = new Bar();\n bar.baz();\n}\n\nmain();"
+ }
+ }),
+ );
+ let (maybe_res, maybe_error) = client
+ .write_request(
+ "textDocument/prepareCallHierarchy",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 5,
+ "character": 3
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_error.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("prepare_call_hierarchy_response.json"))
+ );
+ let (maybe_res, maybe_error) = client
+ .write_request(
+ "callHierarchy/incomingCalls",
+ load_fixture("incoming_calls_params.json"),
+ )
+ .unwrap();
+ assert!(maybe_error.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("incoming_calls_response.json"))
+ );
+ let (maybe_res, maybe_error) = client
+ .write_request(
+ "callHierarchy/outgoingCalls",
+ load_fixture("outgoing_calls_params.json"),
+ )
+ .unwrap();
+ assert!(maybe_error.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("outgoing_calls_response.json"))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_format_mbc() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "const bar = '👍🇺🇸😃'\nconsole.log('hello deno')\n"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/formatting",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "options": {
+ "tabSize": 2,
+ "insertSpaces": true
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!(load_fixture("formatting_mbc_response.json")))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_large_doc_changes() {
+ let mut client = init("initialize_params.json");
+ did_open(&mut client, load_fixture("did_open_params_large.json"));
+ client
+ .write_notification(
+ "textDocument/didChange",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "version": 2
+ },
+ "contentChanges": [
+ {
+ "range": {
+ "start": {
+ "line": 444,
+ "character": 11
+ },
+ "end": {
+ "line": 444,
+ "character": 14
+ }
+ },
+ "text": "+++"
+ }
+ ]
+ }),
+ )
+ .unwrap();
+ client
+ .write_notification(
+ "textDocument/didChange",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "version": 2
+ },
+ "contentChanges": [
+ {
+ "range": {
+ "start": {
+ "line": 445,
+ "character": 4
+ },
+ "end": {
+ "line": 445,
+ "character": 4
+ }
+ },
+ "text": "// "
+ }
+ ]
+ }),
+ )
+ .unwrap();
+ client
+ .write_notification(
+ "textDocument/didChagne",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "version": 2
+ },
+ "contentChanges": [
+ {
+ "range": {
+ "start": {
+ "line": 477,
+ "character": 4
+ },
+ "end": {
+ "line": 477,
+ "character": 9
+ }
+ },
+ "text": "error"
+ }
+ ]
+ }),
+ )
+ .unwrap();
+ let (maybe_res, maybe_err) = client
+ .write_request::<_, _, Value>(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 421,
+ "character": 30
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_res.is_some());
+ assert!(maybe_err.is_none());
+ let (maybe_res, maybe_err) = client
+ .write_request::<_, _, Value>(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 444,
+ "character": 6
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_res.is_some());
+ assert!(maybe_err.is_none());
+ let (maybe_res, maybe_err) = client
+ .write_request::<_, _, Value>(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 461,
+ "character": 34
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_res.is_some());
+ assert!(maybe_err.is_none());
+ shutdown(&mut client);
+
+ assert!(client.duration().as_millis() <= 15000);
+}
+
+#[test]
+fn lsp_document_symbol() {
+ let mut client = init("initialize_params.json");
+ did_open(&mut client, load_fixture("did_open_params_doc_symbol.json"));
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/documentSymbol",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("document_symbol_response.json"))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_folding_range() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "// #region 1\n/*\n * Some comment\n */\nclass Foo {\n bar(a, b) {\n if (a === b) {\n return true;\n }\n return false;\n }\n}\n// #endregion"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/foldingRange",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!([
+ {
+ "startLine": 0,
+ "endLine": 12,
+ "kind": "region"
+ },
+ {
+ "startLine": 1,
+ "endLine": 3,
+ "kind": "comment"
+ },
+ {
+ "startLine": 4,
+ "endLine": 10
+ },
+ {
+ "startLine": 5,
+ "endLine": 9
+ },
+ {
+ "startLine": 6,
+ "endLine": 7
+ }
+ ]))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_rename() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "let variable = 'a';\nconsole.log(variable);"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/rename",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 4
+ },
+ "newName": "variable_modified"
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(maybe_res, Some(load_fixture("rename_response.json")));
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_selection_range() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "class Foo {\n bar(a, b) {\n if (a === b) {\n return true;\n }\n return false;\n }\n}"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/selectionRange",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "positions": [
+ {
+ "line": 2,
+ "character": 8
+ }
+ ]
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("selection_range_response.json"))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_semantic_tokens() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ load_fixture("did_open_params_semantic_tokens.json"),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/semanticTokens/full",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "data": [
+ 0, 5, 6, 1, 1, 0, 9, 6, 8, 9, 0, 8, 6, 8, 9, 2, 15, 3, 10, 5, 0, 4, 1,
+ 6, 1, 0, 12, 7, 2, 16, 1, 8, 1, 7, 41, 0, 4, 1, 6, 0, 0, 2, 5, 11, 16,
+ 1, 9, 1, 7, 40, 3, 10, 4, 2, 1, 1, 11, 1, 9, 9, 1, 2, 3, 11, 1, 3, 6, 3,
+ 0, 1, 0, 15, 4, 2, 0, 1, 30, 1, 6, 9, 1, 2, 3, 11,1, 1, 9, 9, 9, 3, 0,
+ 16, 3, 0, 0, 1, 17, 12, 11, 3, 0, 24, 3, 0, 0, 0, 4, 9, 9, 2
+ ]
+ }))
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/semanticTokens/range",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 0
+ },
+ "end": {
+ "line": 6,
+ "character": 0
+ }
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "data": [
+ 0, 5, 6, 1, 1, 0, 9, 6, 8, 9, 0, 8, 6, 8, 9, 2, 15, 3, 10, 5, 0, 4, 1,
+ 6, 1, 0, 12, 7, 2, 16, 1, 8, 1, 7, 41, 0, 4, 1, 6, 0, 0, 2, 5, 11, 16,
+ 1, 9, 1, 7, 40
+ ]
+ }))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_code_lens() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "class A {\n a = \"a\";\n\n b() {\n console.log(this.a);\n }\n\n c() {\n this.a = \"c\";\n }\n}\n\nconst a = new A();\na.b();\n"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/codeLens",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(maybe_res, Some(load_fixture("code_lens_response.json")));
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "codeLens/resolve",
+ json!({
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 6
+ },
+ "end": {
+ "line": 0,
+ "character": 7
+ }
+ },
+ "data": {
+ "specifier": "file:///a/file.ts",
+ "source": "references"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("code_lens_resolve_response.json"))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_code_lens_impl() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "interface A {\n b(): void;\n}\n\nclass B implements A {\n b() {\n console.log(\"b\");\n }\n}\n"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/codeLens",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("code_lens_response_impl.json"))
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "codeLens/resolve",
+ json!({
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 10
+ },
+ "end": {
+ "line": 0,
+ "character": 11
+ }
+ },
+ "data": {
+ "specifier": "file:///a/file.ts",
+ "source": "implementations"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("code_lens_resolve_response_impl.json"))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_code_lens_non_doc_nav_tree() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "console.log(Date.now());\n"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request::<_, _, Value>(
+ "textDocument/references",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 3
+ },
+ "context": {
+ "includeDeclaration": true
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert!(maybe_res.is_some());
+ let (maybe_res, maybe_err) = client
+ .write_request::<_, _, Value>(
+ "deno/virtualTextDocument",
+ json!({
+ "textDocument": {
+ "uri": "deno:/asset//lib.deno.shared_globals.d.ts"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert!(maybe_res.is_some());
+ let (maybe_res, maybe_err) = client
+ .write_request::<_, _, Vec<lsp::CodeLens>>(
+ "textDocument/codeLens",
+ json!({
+ "textDocument": {
+ "uri": "deno:/asset//lib.deno.shared_globals.d.ts"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert!(maybe_res.is_some());
+ let res = maybe_res.unwrap();
+ assert!(res.len() > 50);
+ let (maybe_res, maybe_err) = client
+ .write_request::<_, _, lsp::CodeLens>(
+ "codeLens/resolve",
+ json!({
+ "range": {
+ "start": {
+ "line": 416,
+ "character": 12
+ },
+ "end": {
+ "line": 416,
+ "character": 19
+ }
+ },
+ "data": {
+ "specifier": "asset:///lib.deno.shared_globals.d.ts",
+ "source": "references"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert!(maybe_res.is_some());
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_signature_help() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "/**\n * Adds two numbers.\n * @param a This is a first number.\n * @param b This is a second number.\n */\nfunction add(a: number, b: number) {\n return a + b;\n}\n\nadd("
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/signatureHelp",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "character": 4,
+ "line": 9
+ },
+ "context": {
+ "triggerKind": 2,
+ "triggerCharacter": "(",
+ "isRetrigger": false
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "signatures": [
+ {
+ "label": "add(a: number, b: number): number",
+ "documentation": "Adds two numbers.",
+ "parameters": [
+ {
+ "label": "a: number",
+ "documentation": "This is a first number."
+ },
+ {
+ "label": "b: number",
+ "documentation": "This is a second number."
+ }
+ ]
+ }
+ ],
+ "activeSignature": 0,
+ "activeParameter": 0
+ }))
+ );
+ client
+ .write_notification(
+ "textDocument/didChange",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "version": 2
+ },
+ "contentChanges": [
+ {
+ "range": {
+ "start": {
+ "line": 9,
+ "character": 4
+ },
+ "end": {
+ "line": 9,
+ "character": 4
+ }
+ },
+ "text": "123, "
+ }
+ ]
+ }),
+ )
+ .unwrap();
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/signatureHelp",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "character": 8,
+ "line": 9
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "signatures": [
+ {
+ "label": "add(a: number, b: number): number",
+ "documentation": "Adds two numbers.",
+ "parameters": [
+ {
+ "label": "a: number",
+ "documentation": "This is a first number."
+ },
+ {
+ "label": "b: number",
+ "documentation": "This is a second number."
+ }
+ ]
+ }
+ ],
+ "activeSignature": 0,
+ "activeParameter": 1
+ }))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_code_actions() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "export function a(): void {\n await Promise.resolve(\"a\");\n}\n\nexport function b(): void {\n await Promise.resolve(\"b\");\n}\n"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/codeAction",
+ load_fixture("code_action_params.json"),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(maybe_res, Some(load_fixture("code_action_response.json")));
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "codeAction/resolve",
+ load_fixture("code_action_resolve_params.json"),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("code_action_resolve_response.json"))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_code_actions_deno_cache() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import * as a from \"https://deno.land/x/a/mod.ts\";\n\nconsole.log(a);\n"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/codeAction",
+ load_fixture("code_action_params_cache.json"),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("code_action_response_cache.json"))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_completions() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "Deno."
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/completion",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 5
+ },
+ "context": {
+ "triggerKind": 2,
+ "triggerCharacter": "."
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ if let Some(lsp::CompletionResponse::List(list)) = maybe_res {
+ assert!(!list.is_incomplete);
+ assert!(list.items.len() > 90);
+ } else {
+ panic!("unexpected response");
+ }
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "completionItem/resolve",
+ load_fixture("completion_resolve_params.json"),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("completion_resolve_response.json"))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_completions_optional() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "interface A {\n b?: string;\n}\n\nconst o: A = {};\n\nfunction c(s: string) {}\n\nc(o.)"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/completion",
+ load_fixture("completion_request_params_optional.json"),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "isIncomplete": false,
+ "items": [
+ {
+ "label": "b?",
+ "kind": 5,
+ "sortText": "1",
+ "filterText": "b",
+ "insertText": "b",
+ "data": {
+ "tsc": {
+ "specifier": "file:///a/file.ts",
+ "position": 79,
+ "name": "b",
+ "useCodeSnippet": false
+ }
+ }
+ }
+ ]
+ }))
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "completionItem/resolve",
+ load_fixture("completion_resolve_params_optional.json"),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "label": "b?",
+ "kind": 5,
+ "detail": "(property) A.b?: string | undefined",
+ "documentation": {
+ "kind": "markdown",
+ "value": ""
+ },
+ "sortText": "1",
+ "filterText": "b",
+ "insertText": "b"
+ }))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_completions_registry() {
+ let _g = http_server();
+ let mut client = init("initialize_params_registry.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import * as a from \"http://localhost:4545/x/a@\""
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/completion",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 46
+ },
+ "context": {
+ "triggerKind": 2,
+ "triggerCharacter": "@"
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ if let Some(lsp::CompletionResponse::List(list)) = maybe_res {
+ assert!(!list.is_incomplete);
+ assert_eq!(list.items.len(), 3);
+ } else {
+ panic!("unexpected response");
+ }
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "completionItem/resolve",
+ load_fixture("completion_resolve_params_registry.json"),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("completion_resolve_response_registry.json"))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
+fn lsp_completions_registry_empty() {
+ let _g = http_server();
+ let mut client = init("initialize_params_registry.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import * as a from \"\""
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/completion",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 20
+ },
+ "context": {
+ "triggerKind": 2,
+ "triggerCharacter": "\""
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(load_fixture("completion_request_response_empty.json"))
+ );
+ shutdown(&mut client);
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct PerformanceAverage {
+ pub name: String,
+ pub count: u32,
+ pub average_duration: u32,
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+struct PerformanceAverages {
+ averages: Vec<PerformanceAverage>,
+}
+
+#[test]
+fn lsp_performance() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "console.log(Deno.args);\n"
+ }
+ }),
+ );
+ let (maybe_res, maybe_err) = client
+ .write_request::<_, _, Value>(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 0,
+ "character": 19
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert!(maybe_res.is_some());
+ let (maybe_res, maybe_err) = client
+ .write_request::<_, _, PerformanceAverages>("deno/performance", json!({}))
+ .unwrap();
+ assert!(maybe_err.is_none());
+ if let Some(res) = maybe_res {
+ assert!(res.averages.len() >= 6);
+ } else {
+ panic!("unexpected result");
+ }
+ shutdown(&mut client);
+}
diff --git a/cli/tests/lsp/code_action_resolve_request.json b/cli/tests/lsp/code_action_params.json
index 48a2eea3b..d026d61f6 100644
--- a/cli/tests/lsp/code_action_resolve_request.json
+++ b/cli/tests/lsp/code_action_params.json
@@ -1,10 +1,18 @@
{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "codeAction/resolve",
- "params": {
- "title": "Add all missing 'async' modifiers",
- "kind": "quickfix",
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 2
+ },
+ "end": {
+ "line": 1,
+ "character": 7
+ }
+ },
+ "context": {
"diagnostics": [
{
"range": {
@@ -24,9 +32,8 @@
"relatedInformation": []
}
],
- "data": {
- "specifier": "file:///a/file.ts",
- "fixId": "fixAwaitInSyncFunction"
- }
+ "only": [
+ "quickfix"
+ ]
}
}
diff --git a/cli/tests/lsp/code_action_params_cache.json b/cli/tests/lsp/code_action_params_cache.json
new file mode 100644
index 000000000..61ae555a3
--- /dev/null
+++ b/cli/tests/lsp/code_action_params_cache.json
@@ -0,0 +1,41 @@
+{
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 19
+ },
+ "end": {
+ "line": 0,
+ "character": 49
+ }
+ },
+ "context": {
+ "diagnostics": [
+ {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 19
+ },
+ "end": {
+ "line": 0,
+ "character": 49
+ }
+ },
+ "severity": 1,
+ "code": "no-cache",
+ "source": "deno",
+ "message": "Unable to load the remote module: \"https://deno.land/x/a/mod.ts\".",
+ "data": {
+ "specifier": "https://deno.land/x/a/mod.ts"
+ }
+ }
+ ],
+ "only": [
+ "quickfix"
+ ]
+ }
+}
diff --git a/cli/tests/lsp/code_action_request.json b/cli/tests/lsp/code_action_request.json
deleted file mode 100644
index af6cbee8b..000000000
--- a/cli/tests/lsp/code_action_request.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/codeAction",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "range": {
- "start": {
- "line": 1,
- "character": 2
- },
- "end": {
- "line": 1,
- "character": 7
- }
- },
- "context": {
- "diagnostics": [
- {
- "range": {
- "start": {
- "line": 1,
- "character": 2
- },
- "end": {
- "line": 1,
- "character": 7
- }
- },
- "severity": 1,
- "code": 1308,
- "source": "deno-ts",
- "message": "'await' expressions are only allowed within async functions and at the top levels of modules.",
- "relatedInformation": []
- }
- ],
- "only": [
- "quickfix"
- ]
- }
- }
-}
diff --git a/cli/tests/lsp/code_action_request_cache.json b/cli/tests/lsp/code_action_request_cache.json
deleted file mode 100644
index 8e296be32..000000000
--- a/cli/tests/lsp/code_action_request_cache.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/codeAction",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "range": {
- "start": {
- "line": 0,
- "character": 19
- },
- "end": {
- "line": 0,
- "character": 49
- }
- },
- "context": {
- "diagnostics": [
- {
- "range": {
- "start": {
- "line": 0,
- "character": 19
- },
- "end": {
- "line": 0,
- "character": 49
- }
- },
- "severity": 1,
- "code": "no-cache",
- "source": "deno",
- "message": "Unable to load the remote module: \"https://deno.land/x/a/mod.ts\".",
- "data": {
- "specifier": "https://deno.land/x/a/mod.ts"
- }
- }
- ],
- "only": [
- "quickfix"
- ]
- }
- }
-}
diff --git a/cli/tests/lsp/code_action_resolve_params.json b/cli/tests/lsp/code_action_resolve_params.json
new file mode 100644
index 000000000..50c1f9a43
--- /dev/null
+++ b/cli/tests/lsp/code_action_resolve_params.json
@@ -0,0 +1,27 @@
+{
+ "title": "Add all missing 'async' modifiers",
+ "kind": "quickfix",
+ "diagnostics": [
+ {
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 2
+ },
+ "end": {
+ "line": 1,
+ "character": 7
+ }
+ },
+ "severity": 1,
+ "code": 1308,
+ "source": "deno-ts",
+ "message": "'await' expressions are only allowed within async functions and at the top levels of modules.",
+ "relatedInformation": []
+ }
+ ],
+ "data": {
+ "specifier": "file:///a/file.ts",
+ "fixId": "fixAwaitInSyncFunction"
+ }
+}
diff --git a/cli/tests/lsp/code_action_resolve_request_response.json b/cli/tests/lsp/code_action_resolve_response.json
index e3f5b3f0e..e3f5b3f0e 100644
--- a/cli/tests/lsp/code_action_resolve_request_response.json
+++ b/cli/tests/lsp/code_action_resolve_response.json
diff --git a/cli/tests/lsp/code_lens_request.json b/cli/tests/lsp/code_lens_request.json
deleted file mode 100644
index a876153bf..000000000
--- a/cli/tests/lsp/code_lens_request.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/codeLens",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- }
- }
-}
diff --git a/cli/tests/lsp/code_lens_request_asset.json b/cli/tests/lsp/code_lens_request_asset.json
deleted file mode 100644
index 6aa246ce5..000000000
--- a/cli/tests/lsp/code_lens_request_asset.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "textDocument/codeLens",
- "params": {
- "textDocument": {
- "uri": "deno:/asset//lib.deno.shared_globals.d.ts"
- }
- }
-}
diff --git a/cli/tests/lsp/code_lens_resolve_request.json b/cli/tests/lsp/code_lens_resolve_request.json
deleted file mode 100644
index 150603cd4..000000000
--- a/cli/tests/lsp/code_lens_resolve_request.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "codeLens/resolve",
- "params": {
- "range": {
- "start": {
- "line": 0,
- "character": 6
- },
- "end": {
- "line": 0,
- "character": 7
- }
- },
- "data": {
- "specifier": "file:///a/file.ts",
- "source": "references"
- }
- }
-}
diff --git a/cli/tests/lsp/code_lens_resolve_request_asset.json b/cli/tests/lsp/code_lens_resolve_request_asset.json
deleted file mode 100644
index 027af96b6..000000000
--- a/cli/tests/lsp/code_lens_resolve_request_asset.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 5,
- "method": "codeLens/resolve",
- "params": {
- "range": {
- "start": {
- "line": 416,
- "character": 12
- },
- "end": {
- "line": 416,
- "character": 19
- }
- },
- "data": {
- "specifier": "asset:///lib.deno.shared_globals.d.ts",
- "source": "references"
- }
- }
-}
diff --git a/cli/tests/lsp/code_lens_resolve_request_impl.json b/cli/tests/lsp/code_lens_resolve_request_impl.json
deleted file mode 100644
index e44d19675..000000000
--- a/cli/tests/lsp/code_lens_resolve_request_impl.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "codeLens/resolve",
- "params": {
- "range": {
- "start": {
- "line": 0,
- "character": 10
- },
- "end": {
- "line": 0,
- "character": 11
- }
- },
- "data": {
- "specifier": "file:///a/file.ts",
- "source": "implementations"
- }
- }
-}
diff --git a/cli/tests/lsp/code_lens_resolve_response.json b/cli/tests/lsp/code_lens_resolve_response.json
new file mode 100644
index 000000000..1400eb4e6
--- /dev/null
+++ b/cli/tests/lsp/code_lens_resolve_response.json
@@ -0,0 +1,38 @@
+{
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 6
+ },
+ "end": {
+ "line": 0,
+ "character": 7
+ }
+ },
+ "command": {
+ "title": "1 reference",
+ "command": "deno.showReferences",
+ "arguments": [
+ "file:///a/file.ts",
+ {
+ "line": 0,
+ "character": 6
+ },
+ [
+ {
+ "uri": "file:///a/file.ts",
+ "range": {
+ "start": {
+ "line": 12,
+ "character": 14
+ },
+ "end": {
+ "line": 12,
+ "character": 15
+ }
+ }
+ }
+ ]
+ ]
+ }
+}
diff --git a/cli/tests/lsp/code_lens_resolve_response_impl.json b/cli/tests/lsp/code_lens_resolve_response_impl.json
new file mode 100644
index 000000000..cabf2f833
--- /dev/null
+++ b/cli/tests/lsp/code_lens_resolve_response_impl.json
@@ -0,0 +1,38 @@
+{
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 10
+ },
+ "end": {
+ "line": 0,
+ "character": 11
+ }
+ },
+ "command": {
+ "title": "1 implementation",
+ "command": "deno.showReferences",
+ "arguments": [
+ "file:///a/file.ts",
+ {
+ "line": 0,
+ "character": 10
+ },
+ [
+ {
+ "uri": "file:///a/file.ts",
+ "range": {
+ "start": {
+ "line": 4,
+ "character": 6
+ },
+ "end": {
+ "line": 4,
+ "character": 7
+ }
+ }
+ }
+ ]
+ ]
+ }
+}
diff --git a/cli/tests/lsp/code_lens_response.json b/cli/tests/lsp/code_lens_response.json
new file mode 100644
index 000000000..e3a87e4be
--- /dev/null
+++ b/cli/tests/lsp/code_lens_response.json
@@ -0,0 +1,34 @@
+[
+ {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 6
+ },
+ "end": {
+ "line": 0,
+ "character": 7
+ }
+ },
+ "data": {
+ "specifier": "file:///a/file.ts",
+ "source": "references"
+ }
+ },
+ {
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 2
+ },
+ "end": {
+ "line": 1,
+ "character": 3
+ }
+ },
+ "data": {
+ "specifier": "file:///a/file.ts",
+ "source": "references"
+ }
+ }
+]
diff --git a/cli/tests/lsp/code_lens_response_impl.json b/cli/tests/lsp/code_lens_response_impl.json
new file mode 100644
index 000000000..b0073a23f
--- /dev/null
+++ b/cli/tests/lsp/code_lens_response_impl.json
@@ -0,0 +1,50 @@
+[
+ {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 10
+ },
+ "end": {
+ "line": 0,
+ "character": 11
+ }
+ },
+ "data": {
+ "specifier": "file:///a/file.ts",
+ "source": "implementations"
+ }
+ },
+ {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 10
+ },
+ "end": {
+ "line": 0,
+ "character": 11
+ }
+ },
+ "data": {
+ "specifier": "file:///a/file.ts",
+ "source": "references"
+ }
+ },
+ {
+ "range": {
+ "start": {
+ "line": 4,
+ "character": 6
+ },
+ "end": {
+ "line": 4,
+ "character": 7
+ }
+ },
+ "data": {
+ "specifier": "file:///a/file.ts",
+ "source": "references"
+ }
+ }
+]
diff --git a/cli/tests/lsp/completion_request.json b/cli/tests/lsp/completion_request.json
deleted file mode 100644
index 81bf719a9..000000000
--- a/cli/tests/lsp/completion_request.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/completion",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 0,
- "character": 5
- },
- "context": {
- "triggerKind": 2,
- "triggerCharacter": "."
- }
- }
-}
diff --git a/cli/tests/lsp/completion_request_optional.json b/cli/tests/lsp/completion_request_optional.json
deleted file mode 100644
index 5e86c33ff..000000000
--- a/cli/tests/lsp/completion_request_optional.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/completion",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 8,
- "character": 4
- },
- "context": {
- "triggerKind": 2,
- "triggerCharacter": "."
- }
- }
-}
diff --git a/cli/tests/lsp/completion_request_params_optional.json b/cli/tests/lsp/completion_request_params_optional.json
new file mode 100644
index 000000000..1f3c079c7
--- /dev/null
+++ b/cli/tests/lsp/completion_request_params_optional.json
@@ -0,0 +1,13 @@
+{
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 8,
+ "character": 4
+ },
+ "context": {
+ "triggerKind": 2,
+ "triggerCharacter": "."
+ }
+}
diff --git a/cli/tests/lsp/completion_request_registry.json b/cli/tests/lsp/completion_request_registry.json
deleted file mode 100644
index 2165fbdab..000000000
--- a/cli/tests/lsp/completion_request_registry.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/completion",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 0,
- "character": 46
- },
- "context": {
- "triggerKind": 2,
- "triggerCharacter": "@"
- }
- }
-}
diff --git a/cli/tests/lsp/completion_request_registry_02.json b/cli/tests/lsp/completion_request_registry_02.json
deleted file mode 100644
index 21c3bc475..000000000
--- a/cli/tests/lsp/completion_request_registry_02.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/completion",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 0,
- "character": 20
- },
- "context": {
- "triggerKind": 2,
- "triggerCharacter": "\""
- }
- }
-}
diff --git a/cli/tests/lsp/completion_request_response_empty.json b/cli/tests/lsp/completion_request_response_empty.json
new file mode 100644
index 000000000..272dfb475
--- /dev/null
+++ b/cli/tests/lsp/completion_request_response_empty.json
@@ -0,0 +1,38 @@
+{
+ "isIncomplete": false,
+ "items": [
+ {
+ "label": ".",
+ "kind": 19,
+ "detail": "(local)",
+ "sortText": "1",
+ "insertText": "."
+ },
+ {
+ "label": "..",
+ "kind": 19,
+ "detail": "(local)",
+ "sortText": "1",
+ "insertText": ".."
+ },
+ {
+ "label": "http://localhost:4545",
+ "kind": 19,
+ "detail": "(registry)",
+ "sortText": "2",
+ "textEdit": {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 20
+ },
+ "end": {
+ "line": 0,
+ "character": 20
+ }
+ },
+ "newText": "http://localhost:4545"
+ }
+ }
+ ]
+}
diff --git a/cli/tests/lsp/completion_resolve_params.json b/cli/tests/lsp/completion_resolve_params.json
new file mode 100644
index 000000000..26231036d
--- /dev/null
+++ b/cli/tests/lsp/completion_resolve_params.json
@@ -0,0 +1,14 @@
+{
+ "label": "build",
+ "kind": 6,
+ "sortText": "1",
+ "insertTextFormat": 1,
+ "data": {
+ "tsc": {
+ "specifier": "file:///a/file.ts",
+ "position": 5,
+ "name": "build",
+ "useCodeSnippet": false
+ }
+ }
+}
diff --git a/cli/tests/lsp/completion_resolve_params_optional.json b/cli/tests/lsp/completion_resolve_params_optional.json
new file mode 100644
index 000000000..cb99bf960
--- /dev/null
+++ b/cli/tests/lsp/completion_resolve_params_optional.json
@@ -0,0 +1,15 @@
+{
+ "label": "b?",
+ "kind": 5,
+ "sortText": "1",
+ "filterText": "b",
+ "insertText": "b",
+ "data": {
+ "tsc": {
+ "specifier": "file:///a/file.ts",
+ "position": 79,
+ "name": "b",
+ "useCodeSnippet": false
+ }
+ }
+}
diff --git a/cli/tests/lsp/completion_resolve_params_registry.json b/cli/tests/lsp/completion_resolve_params_registry.json
new file mode 100644
index 000000000..99a4a048e
--- /dev/null
+++ b/cli/tests/lsp/completion_resolve_params_registry.json
@@ -0,0 +1,20 @@
+{
+ "label": "v2.0.0",
+ "kind": 19,
+ "detail": "(version)",
+ "sortText": "0000000003",
+ "filterText": "http://localhost:4545/x/a@v2.0.0",
+ "textEdit": {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 20
+ },
+ "end": {
+ "line": 0,
+ "character": 46
+ }
+ },
+ "newText": "http://localhost:4545/x/a@v2.0.0"
+ }
+}
diff --git a/cli/tests/lsp/completion_resolve_request.json b/cli/tests/lsp/completion_resolve_request.json
deleted file mode 100644
index 7b78fb440..000000000
--- a/cli/tests/lsp/completion_resolve_request.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "completionItem/resolve",
- "params": {
- "label": "build",
- "kind": 6,
- "sortText": "1",
- "insertTextFormat": 1,
- "data": {
- "tsc": {
- "specifier": "file:///a/file.ts",
- "position": 5,
- "name": "build",
- "useCodeSnippet": false
- }
- }
- }
-}
diff --git a/cli/tests/lsp/completion_resolve_request_optional.json b/cli/tests/lsp/completion_resolve_request_optional.json
deleted file mode 100644
index ffa60b919..000000000
--- a/cli/tests/lsp/completion_resolve_request_optional.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "completionItem/resolve",
- "params": {
- "label": "b?",
- "kind": 5,
- "sortText": "1",
- "filterText": "b",
- "insertText": "b",
- "data": {
- "tsc": {
- "specifier": "file:///a/file.ts",
- "position": 79,
- "name": "b",
- "useCodeSnippet": false
- }
- }
- }
-}
diff --git a/cli/tests/lsp/completion_resolve_request_registry.json b/cli/tests/lsp/completion_resolve_request_registry.json
deleted file mode 100644
index bae19d060..000000000
--- a/cli/tests/lsp/completion_resolve_request_registry.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "completionItem/resolve",
- "params": {
- "label": "v2.0.0",
- "kind": 19,
- "detail": "(version)",
- "sortText": "0000000003",
- "filterText": "http://localhost:4545/x/a@v2.0.0",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 20
- },
- "end": {
- "line": 0,
- "character": 46
- }
- },
- "newText": "http://localhost:4545/x/a@v2.0.0"
- }
- }
-}
diff --git a/cli/tests/lsp/completion_resolve_response.json b/cli/tests/lsp/completion_resolve_response.json
new file mode 100644
index 000000000..0edbc14ef
--- /dev/null
+++ b/cli/tests/lsp/completion_resolve_response.json
@@ -0,0 +1,11 @@
+{
+ "label": "build",
+ "kind": 6,
+ "detail": "const Deno.build: {\n target: string;\n arch: \"x86_64\" | \"aarch64\";\n os: \"darwin\" | \"linux\" | \"windows\";\n vendor: string;\n env?: string | undefined;\n}",
+ "documentation": {
+ "kind": "markdown",
+ "value": "Build related information."
+ },
+ "sortText": "1",
+ "insertTextFormat": 1
+}
diff --git a/cli/tests/lsp/completion_resolve_response_registry.json b/cli/tests/lsp/completion_resolve_response_registry.json
new file mode 100644
index 000000000..99a4a048e
--- /dev/null
+++ b/cli/tests/lsp/completion_resolve_response_registry.json
@@ -0,0 +1,20 @@
+{
+ "label": "v2.0.0",
+ "kind": 19,
+ "detail": "(version)",
+ "sortText": "0000000003",
+ "filterText": "http://localhost:4545/x/a@v2.0.0",
+ "textEdit": {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 20
+ },
+ "end": {
+ "line": 0,
+ "character": 46
+ }
+ },
+ "newText": "http://localhost:4545/x/a@v2.0.0"
+ }
+}
diff --git a/cli/tests/lsp/definition_request_asset.json b/cli/tests/lsp/definition_request_asset.json
deleted file mode 100644
index 5e117cf14..000000000
--- a/cli/tests/lsp/definition_request_asset.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "textDocument/definition",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 0,
- "character": 14
- }
- }
-}
diff --git a/cli/tests/lsp/did_change_notification_large.json b/cli/tests/lsp/did_change_notification_large.json
deleted file mode 100644
index c4999a7c3..000000000
--- a/cli/tests/lsp/did_change_notification_large.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didChange",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "version": 2
- },
- "contentChanges": [
- {
- "range": {
- "start": {
- "line": 444,
- "character": 11
- },
- "end": {
- "line": 444,
- "character": 14
- }
- },
- "text": "+++"
- }
- ]
- }
-}
diff --git a/cli/tests/lsp/did_change_notification_large_02.json b/cli/tests/lsp/did_change_notification_large_02.json
deleted file mode 100644
index e8744d620..000000000
--- a/cli/tests/lsp/did_change_notification_large_02.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didChange",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "version": 2
- },
- "contentChanges": [
- {
- "range": {
- "start": {
- "line": 445,
- "character": 4
- },
- "end": {
- "line": 445,
- "character": 4
- }
- },
- "text": "// "
- }
- ]
- }
-}
diff --git a/cli/tests/lsp/did_change_notification_large_03.json b/cli/tests/lsp/did_change_notification_large_03.json
deleted file mode 100644
index f39234510..000000000
--- a/cli/tests/lsp/did_change_notification_large_03.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didChange",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "version": 2
- },
- "contentChanges": [
- {
- "range": {
- "start": {
- "line": 477,
- "character": 4
- },
- "end": {
- "line": 477,
- "character": 9
- }
- },
- "text": "error"
- }
- ]
- }
-}
diff --git a/cli/tests/lsp/did_change_notification_mbc.json b/cli/tests/lsp/did_change_notification_mbc.json
deleted file mode 100644
index fed742d39..000000000
--- a/cli/tests/lsp/did_change_notification_mbc.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didChange",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "version": 2
- },
- "contentChanges": [
- {
- "range": {
- "start": {
- "line": 1,
- "character": 11
- },
- "end": {
- "line": 1,
- "character": 13
- }
- },
- "text": ""
- }
- ]
- }
-}
diff --git a/cli/tests/lsp/did_open_notification.json b/cli/tests/lsp/did_open_notification.json
deleted file mode 100644
index 04f12a7b3..000000000
--- a/cli/tests/lsp/did_open_notification.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "console.log(Deno.args);\n"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_asset.json b/cli/tests/lsp/did_open_notification_asset.json
deleted file mode 100644
index 413353f29..000000000
--- a/cli/tests/lsp/did_open_notification_asset.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "console.log(Date.now());\n"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_cache.json b/cli/tests/lsp/did_open_notification_cache.json
deleted file mode 100644
index 6f21ee5cd..000000000
--- a/cli/tests/lsp/did_open_notification_cache.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "import * as a from \"https://deno.land/x/a/mod.ts\";\n\nconsole.log(a);\n"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_cl_impl.json b/cli/tests/lsp/did_open_notification_cl_impl.json
deleted file mode 100644
index eabcd7ccc..000000000
--- a/cli/tests/lsp/did_open_notification_cl_impl.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "interface A {\n b(): void;\n}\n\nclass B implements A {\n b() {\n console.log(\"b\");\n }\n}\n"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_cl_references.json b/cli/tests/lsp/did_open_notification_cl_references.json
deleted file mode 100644
index 546ba5674..000000000
--- a/cli/tests/lsp/did_open_notification_cl_references.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "class A {\n a = \"a\";\n\n b() {\n console.log(this.a);\n }\n\n c() {\n this.a = \"c\";\n }\n}\n\nconst a = new A();\na.b();\n"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_code_action.json b/cli/tests/lsp/did_open_notification_code_action.json
deleted file mode 100644
index 57559cf3c..000000000
--- a/cli/tests/lsp/did_open_notification_code_action.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "export function a(): void {\n await Promise.resolve(\"a\");\n}\n\nexport function b(): void {\n await Promise.resolve(\"b\");\n}\n"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_completion_optional.json b/cli/tests/lsp/did_open_notification_completion_optional.json
deleted file mode 100644
index 5e919c80a..000000000
--- a/cli/tests/lsp/did_open_notification_completion_optional.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "interface A {\n b?: string;\n}\n\nconst o: A = {};\n\nfunction c(s: string) {}\n\nc(o.)"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_completion_registry.json b/cli/tests/lsp/did_open_notification_completion_registry.json
deleted file mode 100644
index cb8ad2592..000000000
--- a/cli/tests/lsp/did_open_notification_completion_registry.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "import * as a from \"http://localhost:4545/x/a@\""
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_completion_registry_02.json b/cli/tests/lsp/did_open_notification_completion_registry_02.json
deleted file mode 100644
index a53882b56..000000000
--- a/cli/tests/lsp/did_open_notification_completion_registry_02.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "import * as a from \"\""
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_completions.json b/cli/tests/lsp/did_open_notification_completions.json
deleted file mode 100644
index edcdc9373..000000000
--- a/cli/tests/lsp/did_open_notification_completions.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "Deno."
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_large.json b/cli/tests/lsp/did_open_notification_large.json
deleted file mode 100644
index 4a467891c..000000000
--- a/cli/tests/lsp/did_open_notification_large.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "javascript",
- "version": 1,
- "text": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\n// @ts-check\n/// <reference path=\"./compiler.d.ts\" />\n// deno-lint-ignore-file no-undef\n\n// This module is the entry point for \"compiler\" isolate, ie. the one\n// that is created when Deno needs to type check TypeScript, and in some\n// instances convert TypeScript to JavaScript.\n\n// Removes the `__proto__` for security reasons. This intentionally makes\n// Deno non compliant with ECMA-262 Annex B.2.2.1\ndelete Object.prototype.__proto__;\n\n((window) => {\n /** @type {DenoCore} */\n const core = window.Deno.core;\n\n let logDebug = false;\n let logSource = \"JS\";\n\n function setLogDebug(debug, source) {\n logDebug = debug;\n if (source) {\n logSource = source;\n }\n }\n\n function debug(...args) {\n if (logDebug) {\n const stringifiedArgs = args.map((arg) =>\n typeof arg === \"string\" ? arg : JSON.stringify(arg)\n ).join(\" \");\n // adding a non-zero integer value to the end of the debug string causes\n // the message to be printed to stderr instead of stdout, which is better\n // aligned to the behaviour of debug messages\n core.print(`DEBUG ${logSource} - ${stringifiedArgs}\\n`, 1);\n }\n }\n\n function error(...args) {\n const stringifiedArgs = args.map((arg) =>\n typeof arg === \"string\" || arg instanceof Error\n ? String(arg)\n : JSON.stringify(arg)\n ).join(\" \");\n core.print(`ERROR ${logSource} = ${stringifiedArgs}\\n`, 1);\n }\n\n class AssertionError extends Error {\n constructor(msg) {\n super(msg);\n this.name = \"AssertionError\";\n }\n }\n\n function assert(cond, msg = \"Assertion failed.\") {\n if (!cond) {\n throw new AssertionError(msg);\n }\n }\n\n /** @type {Map<string, ts.SourceFile>} */\n const sourceFileCache = new Map();\n\n /** @param {ts.DiagnosticRelatedInformation} diagnostic */\n function fromRelatedInformation({\n start,\n length,\n file,\n messageText: msgText,\n ...ri\n }) {\n let messageText;\n let messageChain;\n if (typeof msgText === \"object\") {\n messageChain = msgText;\n } else {\n messageText = msgText;\n }\n if (start !== undefined && length !== undefined && file) {\n const startPos = file.getLineAndCharacterOfPosition(start);\n const sourceLine = file.getFullText().split(\"\\n\")[startPos.line];\n const fileName = file.fileName;\n return {\n start: startPos,\n end: file.getLineAndCharacterOfPosition(start + length),\n fileName,\n messageChain,\n messageText,\n sourceLine,\n ...ri,\n };\n } else {\n return {\n messageChain,\n messageText,\n ...ri,\n };\n }\n }\n\n /** @param {ts.Diagnostic[]} diagnostics */\n function fromTypeScriptDiagnostic(diagnostics) {\n return diagnostics.map(({ relatedInformation: ri, source, ...diag }) => {\n /** @type {any} */\n const value = fromRelatedInformation(diag);\n value.relatedInformation = ri\n ? ri.map(fromRelatedInformation)\n : undefined;\n value.source = source;\n return value;\n });\n }\n\n // Using incremental compile APIs requires that all\n // paths must be either relative or absolute. Since\n // analysis in Rust operates on fully resolved URLs,\n // it makes sense to use the same scheme here.\n const ASSETS = \"asset:///\";\n const CACHE = \"cache:///\";\n\n /** Diagnostics that are intentionally ignored when compiling TypeScript in\n * Deno, as they provide misleading or incorrect information. */\n const IGNORED_DIAGNOSTICS = [\n // TS1208: All files must be modules when the '--isolatedModules' flag is\n // provided. We can ignore because we guarantee that all files are\n // modules.\n 1208,\n // TS1375: 'await' expressions are only allowed at the top level of a file\n // when that file is a module, but this file has no imports or exports.\n // Consider adding an empty 'export {}' to make this file a module.\n 1375,\n // TS1103: 'for-await-of' statement is only allowed within an async function\n // or async generator.\n 1103,\n // TS2306: File 'file:///Users/rld/src/deno/cli/tests/subdir/amd_like.js' is\n // not a module.\n 2306,\n // TS2691: An import path cannot end with a '.ts' extension. Consider\n // importing 'bad-module' instead.\n 2691,\n // TS2792: Cannot find module. Did you mean to set the 'moduleResolution'\n // option to 'node', or to add aliases to the 'paths' option?\n 2792,\n // TS5009: Cannot find the common subdirectory path for the input files.\n 5009,\n // TS5055: Cannot write file\n // 'http://localhost:4545/cli/tests/subdir/mt_application_x_javascript.j4.js'\n // because it would overwrite input file.\n 5055,\n // TypeScript is overly opinionated that only CommonJS modules kinds can\n // support JSON imports. Allegedly this was fixed in\n // Microsoft/TypeScript#26825 but that doesn't seem to be working here,\n // so we will ignore complaints about this compiler setting.\n 5070,\n // TS7016: Could not find a declaration file for module '...'. '...'\n // implicitly has an 'any' type. This is due to `allowJs` being off by\n // default but importing of a JavaScript module.\n 7016,\n ];\n\n const SNAPSHOT_COMPILE_OPTIONS = {\n esModuleInterop: true,\n jsx: ts.JsxEmit.React,\n module: ts.ModuleKind.ESNext,\n noEmit: true,\n strict: true,\n target: ts.ScriptTarget.ESNext,\n };\n\n class ScriptSnapshot {\n /** @type {string} */\n specifier;\n /** @type {string} */\n version;\n /**\n * @param {string} specifier\n * @param {string} version \n */\n constructor(specifier, version) {\n this.specifier = specifier;\n this.version = version;\n }\n /**\n * @param {number} start \n * @param {number} end \n * @returns {string}\n */\n getText(start, end) {\n const { specifier, version } = this;\n debug(\n `snapshot.getText(${start}, ${end}) specifier: ${specifier} version: ${version}`,\n );\n return core.jsonOpSync(\"op_get_text\", { specifier, version, start, end });\n }\n /**\n * @returns {number}\n */\n getLength() {\n const { specifier, version } = this;\n debug(`snapshot.getLength() specifier: ${specifier} version: ${version}`);\n return core.jsonOpSync(\"op_get_length\", { specifier, version });\n }\n /**\n * @param {ScriptSnapshot} oldSnapshot\n * @returns {ts.TextChangeRange | undefined}\n */\n getChangeRange(oldSnapshot) {\n const { specifier, version } = this;\n const { version: oldVersion } = oldSnapshot;\n const oldLength = oldSnapshot.getLength();\n debug(\n `snapshot.getLength() specifier: ${specifier} oldVersion: ${oldVersion} version: ${version}`,\n );\n return core.jsonOpSync(\n \"op_get_change_range\",\n { specifier, oldLength, oldVersion, version },\n );\n }\n dispose() {\n const { specifier, version } = this;\n debug(`snapshot.dispose() specifier: ${specifier} version: ${version}`);\n core.jsonOpSync(\"op_dispose\", { specifier, version });\n }\n }\n\n /** @type {ts.CompilerOptions} */\n let compilationSettings = {};\n\n /** @type {ts.LanguageService} */\n let languageService;\n\n /** An object literal of the incremental compiler host, which provides the\n * specific \"bindings\" to the Deno environment that tsc needs to work.\n *\n * @type {ts.CompilerHost & ts.LanguageServiceHost} */\n const host = {\n fileExists(fileName) {\n debug(`host.fileExists(\"${fileName}\")`);\n return false;\n },\n readFile(specifier) {\n debug(`host.readFile(\"${specifier}\")`);\n return core.jsonOpSync(\"op_load\", { specifier }).data;\n },\n getSourceFile(\n specifier,\n languageVersion,\n _onError,\n _shouldCreateNewSourceFile,\n ) {\n debug(\n `host.getSourceFile(\"${specifier}\", ${\n ts.ScriptTarget[languageVersion]\n })`,\n );\n let sourceFile = sourceFileCache.get(specifier);\n if (sourceFile) {\n return sourceFile;\n }\n\n /** @type {{ data: string; hash?: string; scriptKind: ts.ScriptKind }} */\n const { data, hash, scriptKind } = core.jsonOpSync(\n \"op_load\",\n { specifier },\n );\n assert(\n data != null,\n `\"data\" is unexpectedly null for \"${specifier}\".`,\n );\n sourceFile = ts.createSourceFile(\n specifier,\n data,\n languageVersion,\n false,\n scriptKind,\n );\n sourceFile.moduleName = specifier;\n sourceFile.version = hash;\n sourceFileCache.set(specifier, sourceFile);\n return sourceFile;\n },\n getDefaultLibFileName() {\n return `${ASSETS}/lib.esnext.d.ts`;\n },\n getDefaultLibLocation() {\n return ASSETS;\n },\n writeFile(fileName, data, _writeByteOrderMark, _onError, sourceFiles) {\n debug(`host.writeFile(\"${fileName}\")`);\n let maybeSpecifiers;\n if (sourceFiles) {\n maybeSpecifiers = sourceFiles.map((sf) => sf.moduleName);\n }\n return core.jsonOpSync(\n \"op_emit\",\n { maybeSpecifiers, fileName, data },\n );\n },\n getCurrentDirectory() {\n return CACHE;\n },\n getCanonicalFileName(fileName) {\n return fileName;\n },\n useCaseSensitiveFileNames() {\n return true;\n },\n getNewLine() {\n return \"\\n\";\n },\n resolveModuleNames(specifiers, base) {\n debug(`host.resolveModuleNames()`);\n debug(` base: ${base}`);\n debug(` specifiers: ${specifiers.join(\", \")}`);\n /** @type {Array<[string, ts.Extension] | undefined>} */\n const resolved = core.jsonOpSync(\"op_resolve\", {\n specifiers,\n base,\n });\n if (resolved) {\n const result = resolved.map((item) => {\n if (item) {\n const [resolvedFileName, extension] = item;\n return {\n resolvedFileName,\n extension,\n isExternalLibraryImport: false,\n };\n }\n return undefined;\n });\n result.length = specifiers.length;\n return result;\n } else {\n return new Array(specifiers.length);\n }\n },\n createHash(data) {\n return core.jsonOpSync(\"op_create_hash\", { data }).hash;\n },\n\n // LanguageServiceHost\n getCompilationSettings() {\n debug(\"host.getCompilationSettings()\");\n return compilationSettings;\n },\n getScriptFileNames() {\n debug(\"host.getScriptFileNames()\");\n return core.jsonOpSync(\"op_script_names\", undefined);\n },\n getScriptVersion(specifier) {\n debug(`host.getScriptVersion(\"${specifier}\")`);\n const sourceFile = sourceFileCache.get(specifier);\n if (sourceFile) {\n return sourceFile.version ?? \"1\";\n }\n return core.jsonOpSync(\"op_script_version\", { specifier });\n },\n getScriptSnapshot(specifier) {\n debug(`host.getScriptSnapshot(\"${specifier}\")`);\n const sourceFile = sourceFileCache.get(specifier);\n if (sourceFile) {\n return {\n getText(start, end) {\n return sourceFile.text.substring(start, end);\n },\n getLength() {\n return sourceFile.text.length;\n },\n getChangeRange() {\n return undefined;\n },\n };\n }\n /** @type {string | undefined} */\n const version = core.jsonOpSync(\"op_script_version\", { specifier });\n if (version != null) {\n return new ScriptSnapshot(specifier, version);\n }\n return undefined;\n },\n };\n\n /** @type {Array<[string, number]>} */\n const stats = [];\n let statsStart = 0;\n\n function performanceStart() {\n stats.length = 0;\n statsStart = Date.now();\n ts.performance.enable();\n }\n\n /**\n * @param {{ program: ts.Program | ts.EmitAndSemanticDiagnosticsBuilderProgram, fileCount?: number }} options \n */\n function performanceProgram({ program, fileCount }) {\n if (program) {\n if (\"getProgram\" in program) {\n program = program.getProgram();\n }\n stats.push([\"Files\", program.getSourceFiles().length]);\n stats.push([\"Nodes\", program.getNodeCount()]);\n stats.push([\"Identifiers\", program.getIdentifierCount()]);\n stats.push([\"Symbols\", program.getSymbolCount()]);\n stats.push([\"Types\", program.getTypeCount()]);\n stats.push([\"Instantiations\", program.getInstantiationCount()]);\n } else if (fileCount != null) {\n stats.push([\"Files\", fileCount]);\n }\n const programTime = ts.performance.getDuration(\"Program\");\n const bindTime = ts.performance.getDuration(\"Bind\");\n const checkTime = ts.performance.getDuration(\"Check\");\n const emitTime = ts.performance.getDuration(\"Emit\");\n stats.push([\"Parse time\", programTime]);\n stats.push([\"Bind time\", bindTime]);\n stats.push([\"Check time\", checkTime]);\n stats.push([\"Emit time\", emitTime]);\n stats.push(\n [\"Total TS time\", programTime + bindTime + checkTime + emitTime],\n );\n }\n\n function performanceEnd() {\n const duration = Date.now() - statsStart;\n stats.push([\"Compile time\", duration]);\n return stats;\n }\n\n /**\n * @typedef {object} Request\n * @property {Record<string, any>} config\n * @property {boolean} debug\n * @property {string[]} rootNames\n */\n\n /** The API that is called by Rust when executing a request.\n * @param {Request} request\n */\n function exec({ config, debug: debugFlag, rootNames }) {\n setLogDebug(debugFlag, \"TS\");\n performanceStart();\n debug(\">>> exec start\", { rootNames });\n debug(config);\n\n const { options, errors: configFileParsingDiagnostics } = ts\n .convertCompilerOptionsFromJson(config, \"\");\n // The `allowNonTsExtensions` is a \"hidden\" compiler option used in VSCode\n // which is not allowed to be passed in JSON, we need it to allow special\n // URLs which Deno supports. So we need to either ignore the diagnostic, or\n // inject it ourselves.\n Object.assign(options, { allowNonTsExtensions: true });\n const program = ts.createIncrementalProgram({\n rootNames,\n options,\n host,\n configFileParsingDiagnostics,\n });\n\n const { diagnostics: emitDiagnostics } = program.emit();\n\n const diagnostics = [\n ...program.getConfigFileParsingDiagnostics(),\n ...program.getSyntacticDiagnostics(),\n ...program.getOptionsDiagnostics(),\n ...program.getGlobalDiagnostics(),\n ...program.getSemanticDiagnostics(),\n ...emitDiagnostics,\n ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code));\n performanceProgram({ program });\n\n core.jsonOpSync(\"op_respond\", {\n diagnostics: fromTypeScriptDiagnostic(diagnostics),\n stats: performanceEnd(),\n });\n debug(\"<<< exec stop\");\n }\n\n /**\n * @param {number} id \n * @param {any} data \n */\n function respond(id, data = null) {\n core.jsonOpSync(\"op_respond\", { id, data });\n }\n\n /**\n * @param {LanguageServerRequest} request \n */\n function serverRequest({ id, ...request }) {\n debug(`serverRequest()`, { id, ...request });\n switch (request.method) {\n case \"configure\": {\n const { options, errors } = ts\n .convertCompilerOptionsFromJson(request.compilerOptions, \"\");\n Object.assign(options, { allowNonTsExtensions: true });\n if (errors.length) {\n debug(ts.formatDiagnostics(errors, host));\n }\n compilationSettings = options;\n return respond(id, true);\n }\n case \"getAsset\": {\n const sourceFile = host.getSourceFile(\n request.specifier,\n ts.ScriptTarget.ESNext,\n );\n return respond(id, sourceFile && sourceFile.text);\n }\n case \"getDiagnostics\": {\n try {\n /** @type {Record<string, any[]>} */\n const diagnosticMap = {};\n for (const specifier of request.specifiers) {\n diagnosticMap[specifier] = fromTypeScriptDiagnostic([\n ...languageService.getSemanticDiagnostics(specifier),\n ...languageService.getSuggestionDiagnostics(specifier),\n ...languageService.getSyntacticDiagnostics(specifier),\n ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code)));\n }\n return respond(id, diagnosticMap);\n } catch (e) {\n if (\"stack\" in e) {\n error(e.stack);\n } else {\n error(e);\n }\n return respond(id, {});\n }\n }\n case \"getQuickInfo\": {\n return respond(\n id,\n languageService.getQuickInfoAtPosition(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"getCompletions\": {\n return respond(\n id,\n languageService.getCompletionsAtPosition(\n request.specifier,\n request.position,\n request.preferences,\n ),\n );\n }\n case \"getDocumentHighlights\": {\n return respond(\n id,\n languageService.getDocumentHighlights(\n request.specifier,\n request.position,\n request.filesToSearch,\n ),\n );\n }\n case \"getReferences\": {\n return respond(\n id,\n languageService.getReferencesAtPosition(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"getDefinition\": {\n return respond(\n id,\n languageService.getDefinitionAndBoundSpan(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"getImplementation\": {\n return respond(\n id,\n languageService.getImplementationAtPosition(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"findRenameLocations\": {\n return respond(\n id,\n languageService.findRenameLocations(\n request.specifier,\n request.position,\n request.findInStrings,\n request.findInComments,\n request.providePrefixAndSuffixTextForRename,\n ),\n );\n }\n default:\n throw new TypeError(\n // @ts-ignore exhausted case statement sets type to never\n `Invalid request method for request: \"${request.method}\" (${id})`,\n );\n }\n }\n\n /** @param {{ debug: boolean; }} init */\n function serverInit({ debug: debugFlag }) {\n if (hasStarted) {\n throw new Error(\"The language server has already been initialized.\");\n }\n hasStarted = true;\n languageService = ts.createLanguageService(host);\n core.ops();\n setLogDebug(debugFlag, \"TSLS\");\n debug(\"serverInit()\");\n }\n\n let hasStarted = false;\n\n /** Startup the runtime environment, setting various flags.\n * @param {{ debugFlag?: boolean; legacyFlag?: boolean; }} msg\n */\n function startup({ debugFlag = false }) {\n if (hasStarted) {\n throw new Error(\"The compiler runtime already started.\");\n }\n hasStarted = true;\n core.ops();\n setLogDebug(!!debugFlag, \"TS\");\n }\n\n // Setup the compiler runtime during the build process.\n core.ops();\n core.registerErrorClass(\"Error\", Error);\n\n // A build time only op that provides some setup information that is used to\n // ensure the snapshot is setup properly.\n /** @type {{ buildSpecifier: string; libs: string[] }} */\n const { buildSpecifier, libs } = core.jsonOpSync(\"op_build_info\", {});\n for (const lib of libs) {\n const specifier = `lib.${lib}.d.ts`;\n // we are using internal APIs here to \"inject\" our custom libraries into\n // tsc, so things like `\"lib\": [ \"deno.ns\" ]` are supported.\n if (!ts.libs.includes(lib)) {\n ts.libs.push(lib);\n ts.libMap.set(lib, `lib.${lib}.d.ts`);\n }\n // we are caching in memory common type libraries that will be re-used by\n // tsc on when the snapshot is restored\n assert(\n host.getSourceFile(`${ASSETS}${specifier}`, ts.ScriptTarget.ESNext),\n );\n }\n // this helps ensure as much as possible is in memory that is re-usable\n // before the snapshotting is done, which helps unsure fast \"startup\" for\n // subsequent uses of tsc in Deno.\n const TS_SNAPSHOT_PROGRAM = ts.createProgram({\n rootNames: [buildSpecifier],\n options: SNAPSHOT_COMPILE_OPTIONS,\n host,\n });\n ts.getPreEmitDiagnostics(TS_SNAPSHOT_PROGRAM);\n\n // exposes the two functions that are called by `tsc::exec()` when type\n // checking TypeScript.\n globalThis.startup = startup;\n globalThis.exec = exec;\n\n // exposes the functions that are called when the compiler is used as a\n // language service.\n globalThis.serverInit = serverInit;\n globalThis.serverRequest = serverRequest;\n})(this);\n"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_mbc.json b/cli/tests/lsp/did_open_notification_mbc.json
deleted file mode 100644
index d7dd9444e..000000000
--- a/cli/tests/lsp/did_open_notification_mbc.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "const a = `编写软件很难`;\nconst b = `👍🦕😃`;\nconsole.log(a, b);\n"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_mbc_fmt.json b/cli/tests/lsp/did_open_notification_mbc_fmt.json
deleted file mode 100644
index 528dad25d..000000000
--- a/cli/tests/lsp/did_open_notification_mbc_fmt.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "const bar = '👍🇺🇸😃'\nconsole.log('hello deno')\n"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_notification_unstable.json b/cli/tests/lsp/did_open_notification_unstable.json
deleted file mode 100644
index bb7a1f679..000000000
--- a/cli/tests/lsp/did_open_notification_unstable.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "console.log(Deno.openPlugin);\n"
- }
- }
-}
diff --git a/cli/tests/lsp/did_open_params_doc_symbol.json b/cli/tests/lsp/did_open_params_doc_symbol.json
new file mode 100644
index 000000000..c74877191
--- /dev/null
+++ b/cli/tests/lsp/did_open_params_doc_symbol.json
@@ -0,0 +1,8 @@
+{
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "interface IFoo {\n foo(): boolean;\n}\n\nclass Bar implements IFoo {\n constructor(public x: number) { }\n foo() { return true; }\n /** @deprecated */\n baz() { return false; }\n get value(): number { return 0; }\n set value(newVavlue: number) { return; }\n static staticBar = new Bar(0);\n private static getStaticBar() { return Bar.staticBar; }\n}\n\nenum Values { value1, value2 }\n\nvar bar: IFoo = new Bar(3);"
+ }
+}
diff --git a/cli/tests/lsp/did_open_params_large.json b/cli/tests/lsp/did_open_params_large.json
new file mode 100644
index 000000000..b78d6e799
--- /dev/null
+++ b/cli/tests/lsp/did_open_params_large.json
@@ -0,0 +1,8 @@
+{
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "javascript",
+ "version": 1,
+ "text": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\n// @ts-check\n/// <reference path=\"./compiler.d.ts\" />\n// deno-lint-ignore-file no-undef\n\n// This module is the entry point for \"compiler\" isolate, ie. the one\n// that is created when Deno needs to type check TypeScript, and in some\n// instances convert TypeScript to JavaScript.\n\n// Removes the `__proto__` for security reasons. This intentionally makes\n// Deno non compliant with ECMA-262 Annex B.2.2.1\ndelete Object.prototype.__proto__;\n\n((window) => {\n /** @type {DenoCore} */\n const core = window.Deno.core;\n\n let logDebug = false;\n let logSource = \"JS\";\n\n function setLogDebug(debug, source) {\n logDebug = debug;\n if (source) {\n logSource = source;\n }\n }\n\n function debug(...args) {\n if (logDebug) {\n const stringifiedArgs = args.map((arg) =>\n typeof arg === \"string\" ? arg : JSON.stringify(arg)\n ).join(\" \");\n // adding a non-zero integer value to the end of the debug string causes\n // the message to be printed to stderr instead of stdout, which is better\n // aligned to the behaviour of debug messages\n core.print(`DEBUG ${logSource} - ${stringifiedArgs}\\n`, 1);\n }\n }\n\n function error(...args) {\n const stringifiedArgs = args.map((arg) =>\n typeof arg === \"string\" || arg instanceof Error\n ? String(arg)\n : JSON.stringify(arg)\n ).join(\" \");\n core.print(`ERROR ${logSource} = ${stringifiedArgs}\\n`, 1);\n }\n\n class AssertionError extends Error {\n constructor(msg) {\n super(msg);\n this.name = \"AssertionError\";\n }\n }\n\n function assert(cond, msg = \"Assertion failed.\") {\n if (!cond) {\n throw new AssertionError(msg);\n }\n }\n\n /** @type {Map<string, ts.SourceFile>} */\n const sourceFileCache = new Map();\n\n /** @param {ts.DiagnosticRelatedInformation} diagnostic */\n function fromRelatedInformation({\n start,\n length,\n file,\n messageText: msgText,\n ...ri\n }) {\n let messageText;\n let messageChain;\n if (typeof msgText === \"object\") {\n messageChain = msgText;\n } else {\n messageText = msgText;\n }\n if (start !== undefined && length !== undefined && file) {\n const startPos = file.getLineAndCharacterOfPosition(start);\n const sourceLine = file.getFullText().split(\"\\n\")[startPos.line];\n const fileName = file.fileName;\n return {\n start: startPos,\n end: file.getLineAndCharacterOfPosition(start + length),\n fileName,\n messageChain,\n messageText,\n sourceLine,\n ...ri,\n };\n } else {\n return {\n messageChain,\n messageText,\n ...ri,\n };\n }\n }\n\n /** @param {ts.Diagnostic[]} diagnostics */\n function fromTypeScriptDiagnostic(diagnostics) {\n return diagnostics.map(({ relatedInformation: ri, source, ...diag }) => {\n /** @type {any} */\n const value = fromRelatedInformation(diag);\n value.relatedInformation = ri\n ? ri.map(fromRelatedInformation)\n : undefined;\n value.source = source;\n return value;\n });\n }\n\n // Using incremental compile APIs requires that all\n // paths must be either relative or absolute. Since\n // analysis in Rust operates on fully resolved URLs,\n // it makes sense to use the same scheme here.\n const ASSETS = \"asset:///\";\n const CACHE = \"cache:///\";\n\n /** Diagnostics that are intentionally ignored when compiling TypeScript in\n * Deno, as they provide misleading or incorrect information. */\n const IGNORED_DIAGNOSTICS = [\n // TS1208: All files must be modules when the '--isolatedModules' flag is\n // provided. We can ignore because we guarantee that all files are\n // modules.\n 1208,\n // TS1375: 'await' expressions are only allowed at the top level of a file\n // when that file is a module, but this file has no imports or exports.\n // Consider adding an empty 'export {}' to make this file a module.\n 1375,\n // TS1103: 'for-await-of' statement is only allowed within an async function\n // or async generator.\n 1103,\n // TS2306: File 'file:///Users/rld/src/deno/cli/tests/subdir/amd_like.js' is\n // not a module.\n 2306,\n // TS2691: An import path cannot end with a '.ts' extension. Consider\n // importing 'bad-module' instead.\n 2691,\n // TS2792: Cannot find module. Did you mean to set the 'moduleResolution'\n // option to 'node', or to add aliases to the 'paths' option?\n 2792,\n // TS5009: Cannot find the common subdirectory path for the input files.\n 5009,\n // TS5055: Cannot write file\n // 'http://localhost:4545/cli/tests/subdir/mt_application_x_javascript.j4.js'\n // because it would overwrite input file.\n 5055,\n // TypeScript is overly opinionated that only CommonJS modules kinds can\n // support JSON imports. Allegedly this was fixed in\n // Microsoft/TypeScript#26825 but that doesn't seem to be working here,\n // so we will ignore complaints about this compiler setting.\n 5070,\n // TS7016: Could not find a declaration file for module '...'. '...'\n // implicitly has an 'any' type. This is due to `allowJs` being off by\n // default but importing of a JavaScript module.\n 7016,\n ];\n\n const SNAPSHOT_COMPILE_OPTIONS = {\n esModuleInterop: true,\n jsx: ts.JsxEmit.React,\n module: ts.ModuleKind.ESNext,\n noEmit: true,\n strict: true,\n target: ts.ScriptTarget.ESNext,\n };\n\n class ScriptSnapshot {\n /** @type {string} */\n specifier;\n /** @type {string} */\n version;\n /**\n * @param {string} specifier\n * @param {string} version \n */\n constructor(specifier, version) {\n this.specifier = specifier;\n this.version = version;\n }\n /**\n * @param {number} start \n * @param {number} end \n * @returns {string}\n */\n getText(start, end) {\n const { specifier, version } = this;\n debug(\n `snapshot.getText(${start}, ${end}) specifier: ${specifier} version: ${version}`,\n );\n return core.jsonOpSync(\"op_get_text\", { specifier, version, start, end });\n }\n /**\n * @returns {number}\n */\n getLength() {\n const { specifier, version } = this;\n debug(`snapshot.getLength() specifier: ${specifier} version: ${version}`);\n return core.jsonOpSync(\"op_get_length\", { specifier, version });\n }\n /**\n * @param {ScriptSnapshot} oldSnapshot\n * @returns {ts.TextChangeRange | undefined}\n */\n getChangeRange(oldSnapshot) {\n const { specifier, version } = this;\n const { version: oldVersion } = oldSnapshot;\n const oldLength = oldSnapshot.getLength();\n debug(\n `snapshot.getLength() specifier: ${specifier} oldVersion: ${oldVersion} version: ${version}`,\n );\n return core.jsonOpSync(\n \"op_get_change_range\",\n { specifier, oldLength, oldVersion, version },\n );\n }\n dispose() {\n const { specifier, version } = this;\n debug(`snapshot.dispose() specifier: ${specifier} version: ${version}`);\n core.jsonOpSync(\"op_dispose\", { specifier, version });\n }\n }\n\n /** @type {ts.CompilerOptions} */\n let compilationSettings = {};\n\n /** @type {ts.LanguageService} */\n let languageService;\n\n /** An object literal of the incremental compiler host, which provides the\n * specific \"bindings\" to the Deno environment that tsc needs to work.\n *\n * @type {ts.CompilerHost & ts.LanguageServiceHost} */\n const host = {\n fileExists(fileName) {\n debug(`host.fileExists(\"${fileName}\")`);\n return false;\n },\n readFile(specifier) {\n debug(`host.readFile(\"${specifier}\")`);\n return core.jsonOpSync(\"op_load\", { specifier }).data;\n },\n getSourceFile(\n specifier,\n languageVersion,\n _onError,\n _shouldCreateNewSourceFile,\n ) {\n debug(\n `host.getSourceFile(\"${specifier}\", ${\n ts.ScriptTarget[languageVersion]\n })`,\n );\n let sourceFile = sourceFileCache.get(specifier);\n if (sourceFile) {\n return sourceFile;\n }\n\n /** @type {{ data: string; hash?: string; scriptKind: ts.ScriptKind }} */\n const { data, hash, scriptKind } = core.jsonOpSync(\n \"op_load\",\n { specifier },\n );\n assert(\n data != null,\n `\"data\" is unexpectedly null for \"${specifier}\".`,\n );\n sourceFile = ts.createSourceFile(\n specifier,\n data,\n languageVersion,\n false,\n scriptKind,\n );\n sourceFile.moduleName = specifier;\n sourceFile.version = hash;\n sourceFileCache.set(specifier, sourceFile);\n return sourceFile;\n },\n getDefaultLibFileName() {\n return `${ASSETS}/lib.esnext.d.ts`;\n },\n getDefaultLibLocation() {\n return ASSETS;\n },\n writeFile(fileName, data, _writeByteOrderMark, _onError, sourceFiles) {\n debug(`host.writeFile(\"${fileName}\")`);\n let maybeSpecifiers;\n if (sourceFiles) {\n maybeSpecifiers = sourceFiles.map((sf) => sf.moduleName);\n }\n return core.jsonOpSync(\n \"op_emit\",\n { maybeSpecifiers, fileName, data },\n );\n },\n getCurrentDirectory() {\n return CACHE;\n },\n getCanonicalFileName(fileName) {\n return fileName;\n },\n useCaseSensitiveFileNames() {\n return true;\n },\n getNewLine() {\n return \"\\n\";\n },\n resolveModuleNames(specifiers, base) {\n debug(`host.resolveModuleNames()`);\n debug(` base: ${base}`);\n debug(` specifiers: ${specifiers.join(\", \")}`);\n /** @type {Array<[string, ts.Extension] | undefined>} */\n const resolved = core.jsonOpSync(\"op_resolve\", {\n specifiers,\n base,\n });\n if (resolved) {\n const result = resolved.map((item) => {\n if (item) {\n const [resolvedFileName, extension] = item;\n return {\n resolvedFileName,\n extension,\n isExternalLibraryImport: false,\n };\n }\n return undefined;\n });\n result.length = specifiers.length;\n return result;\n } else {\n return new Array(specifiers.length);\n }\n },\n createHash(data) {\n return core.jsonOpSync(\"op_create_hash\", { data }).hash;\n },\n\n // LanguageServiceHost\n getCompilationSettings() {\n debug(\"host.getCompilationSettings()\");\n return compilationSettings;\n },\n getScriptFileNames() {\n debug(\"host.getScriptFileNames()\");\n return core.jsonOpSync(\"op_script_names\", undefined);\n },\n getScriptVersion(specifier) {\n debug(`host.getScriptVersion(\"${specifier}\")`);\n const sourceFile = sourceFileCache.get(specifier);\n if (sourceFile) {\n return sourceFile.version ?? \"1\";\n }\n return core.jsonOpSync(\"op_script_version\", { specifier });\n },\n getScriptSnapshot(specifier) {\n debug(`host.getScriptSnapshot(\"${specifier}\")`);\n const sourceFile = sourceFileCache.get(specifier);\n if (sourceFile) {\n return {\n getText(start, end) {\n return sourceFile.text.substring(start, end);\n },\n getLength() {\n return sourceFile.text.length;\n },\n getChangeRange() {\n return undefined;\n },\n };\n }\n /** @type {string | undefined} */\n const version = core.jsonOpSync(\"op_script_version\", { specifier });\n if (version != null) {\n return new ScriptSnapshot(specifier, version);\n }\n return undefined;\n },\n };\n\n /** @type {Array<[string, number]>} */\n const stats = [];\n let statsStart = 0;\n\n function performanceStart() {\n stats.length = 0;\n statsStart = Date.now();\n ts.performance.enable();\n }\n\n /**\n * @param {{ program: ts.Program | ts.EmitAndSemanticDiagnosticsBuilderProgram, fileCount?: number }} options \n */\n function performanceProgram({ program, fileCount }) {\n if (program) {\n if (\"getProgram\" in program) {\n program = program.getProgram();\n }\n stats.push([\"Files\", program.getSourceFiles().length]);\n stats.push([\"Nodes\", program.getNodeCount()]);\n stats.push([\"Identifiers\", program.getIdentifierCount()]);\n stats.push([\"Symbols\", program.getSymbolCount()]);\n stats.push([\"Types\", program.getTypeCount()]);\n stats.push([\"Instantiations\", program.getInstantiationCount()]);\n } else if (fileCount != null) {\n stats.push([\"Files\", fileCount]);\n }\n const programTime = ts.performance.getDuration(\"Program\");\n const bindTime = ts.performance.getDuration(\"Bind\");\n const checkTime = ts.performance.getDuration(\"Check\");\n const emitTime = ts.performance.getDuration(\"Emit\");\n stats.push([\"Parse time\", programTime]);\n stats.push([\"Bind time\", bindTime]);\n stats.push([\"Check time\", checkTime]);\n stats.push([\"Emit time\", emitTime]);\n stats.push(\n [\"Total TS time\", programTime + bindTime + checkTime + emitTime],\n );\n }\n\n function performanceEnd() {\n const duration = Date.now() - statsStart;\n stats.push([\"Compile time\", duration]);\n return stats;\n }\n\n /**\n * @typedef {object} Request\n * @property {Record<string, any>} config\n * @property {boolean} debug\n * @property {string[]} rootNames\n */\n\n /** The API that is called by Rust when executing a request.\n * @param {Request} request\n */\n function exec({ config, debug: debugFlag, rootNames }) {\n setLogDebug(debugFlag, \"TS\");\n performanceStart();\n debug(\">>> exec start\", { rootNames });\n debug(config);\n\n const { options, errors: configFileParsingDiagnostics } = ts\n .convertCompilerOptionsFromJson(config, \"\");\n // The `allowNonTsExtensions` is a \"hidden\" compiler option used in VSCode\n // which is not allowed to be passed in JSON, we need it to allow special\n // URLs which Deno supports. So we need to either ignore the diagnostic, or\n // inject it ourselves.\n Object.assign(options, { allowNonTsExtensions: true });\n const program = ts.createIncrementalProgram({\n rootNames,\n options,\n host,\n configFileParsingDiagnostics,\n });\n\n const { diagnostics: emitDiagnostics } = program.emit();\n\n const diagnostics = [\n ...program.getConfigFileParsingDiagnostics(),\n ...program.getSyntacticDiagnostics(),\n ...program.getOptionsDiagnostics(),\n ...program.getGlobalDiagnostics(),\n ...program.getSemanticDiagnostics(),\n ...emitDiagnostics,\n ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code));\n performanceProgram({ program });\n\n core.jsonOpSync(\"op_respond\", {\n diagnostics: fromTypeScriptDiagnostic(diagnostics),\n stats: performanceEnd(),\n });\n debug(\"<<< exec stop\");\n }\n\n /**\n * @param {number} id \n * @param {any} data \n */\n function respond(id, data = null) {\n core.jsonOpSync(\"op_respond\", { id, data });\n }\n\n /**\n * @param {LanguageServerRequest} request \n */\n function serverRequest({ id, ...request }) {\n debug(`serverRequest()`, { id, ...request });\n switch (request.method) {\n case \"configure\": {\n const { options, errors } = ts\n .convertCompilerOptionsFromJson(request.compilerOptions, \"\");\n Object.assign(options, { allowNonTsExtensions: true });\n if (errors.length) {\n debug(ts.formatDiagnostics(errors, host));\n }\n compilationSettings = options;\n return respond(id, true);\n }\n case \"getAsset\": {\n const sourceFile = host.getSourceFile(\n request.specifier,\n ts.ScriptTarget.ESNext,\n );\n return respond(id, sourceFile && sourceFile.text);\n }\n case \"getDiagnostics\": {\n try {\n /** @type {Record<string, any[]>} */\n const diagnosticMap = {};\n for (const specifier of request.specifiers) {\n diagnosticMap[specifier] = fromTypeScriptDiagnostic([\n ...languageService.getSemanticDiagnostics(specifier),\n ...languageService.getSuggestionDiagnostics(specifier),\n ...languageService.getSyntacticDiagnostics(specifier),\n ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code)));\n }\n return respond(id, diagnosticMap);\n } catch (e) {\n if (\"stack\" in e) {\n error(e.stack);\n } else {\n error(e);\n }\n return respond(id, {});\n }\n }\n case \"getQuickInfo\": {\n return respond(\n id,\n languageService.getQuickInfoAtPosition(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"getCompletions\": {\n return respond(\n id,\n languageService.getCompletionsAtPosition(\n request.specifier,\n request.position,\n request.preferences,\n ),\n );\n }\n case \"getDocumentHighlights\": {\n return respond(\n id,\n languageService.getDocumentHighlights(\n request.specifier,\n request.position,\n request.filesToSearch,\n ),\n );\n }\n case \"getReferences\": {\n return respond(\n id,\n languageService.getReferencesAtPosition(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"getDefinition\": {\n return respond(\n id,\n languageService.getDefinitionAndBoundSpan(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"getImplementation\": {\n return respond(\n id,\n languageService.getImplementationAtPosition(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"findRenameLocations\": {\n return respond(\n id,\n languageService.findRenameLocations(\n request.specifier,\n request.position,\n request.findInStrings,\n request.findInComments,\n request.providePrefixAndSuffixTextForRename,\n ),\n );\n }\n default:\n throw new TypeError(\n // @ts-ignore exhausted case statement sets type to never\n `Invalid request method for request: \"${request.method}\" (${id})`,\n );\n }\n }\n\n /** @param {{ debug: boolean; }} init */\n function serverInit({ debug: debugFlag }) {\n if (hasStarted) {\n throw new Error(\"The language server has already been initialized.\");\n }\n hasStarted = true;\n languageService = ts.createLanguageService(host);\n core.ops();\n setLogDebug(debugFlag, \"TSLS\");\n debug(\"serverInit()\");\n }\n\n let hasStarted = false;\n\n /** Startup the runtime environment, setting various flags.\n * @param {{ debugFlag?: boolean; legacyFlag?: boolean; }} msg\n */\n function startup({ debugFlag = false }) {\n if (hasStarted) {\n throw new Error(\"The compiler runtime already started.\");\n }\n hasStarted = true;\n core.ops();\n setLogDebug(!!debugFlag, \"TS\");\n }\n\n // Setup the compiler runtime during the build process.\n core.ops();\n core.registerErrorClass(\"Error\", Error);\n\n // A build time only op that provides some setup information that is used to\n // ensure the snapshot is setup properly.\n /** @type {{ buildSpecifier: string; libs: string[] }} */\n const { buildSpecifier, libs } = core.jsonOpSync(\"op_build_info\", {});\n for (const lib of libs) {\n const specifier = `lib.${lib}.d.ts`;\n // we are using internal APIs here to \"inject\" our custom libraries into\n // tsc, so things like `\"lib\": [ \"deno.ns\" ]` are supported.\n if (!ts.libs.includes(lib)) {\n ts.libs.push(lib);\n ts.libMap.set(lib, `lib.${lib}.d.ts`);\n }\n // we are caching in memory common type libraries that will be re-used by\n // tsc on when the snapshot is restored\n assert(\n host.getSourceFile(`${ASSETS}${specifier}`, ts.ScriptTarget.ESNext),\n );\n }\n // this helps ensure as much as possible is in memory that is re-usable\n // before the snapshotting is done, which helps unsure fast \"startup\" for\n // subsequent uses of tsc in Deno.\n const TS_SNAPSHOT_PROGRAM = ts.createProgram({\n rootNames: [buildSpecifier],\n options: SNAPSHOT_COMPILE_OPTIONS,\n host,\n });\n ts.getPreEmitDiagnostics(TS_SNAPSHOT_PROGRAM);\n\n // exposes the two functions that are called by `tsc::exec()` when type\n // checking TypeScript.\n globalThis.startup = startup;\n globalThis.exec = exec;\n\n // exposes the functions that are called when the compiler is used as a\n // language service.\n globalThis.serverInit = serverInit;\n globalThis.serverRequest = serverRequest;\n})(this);\n"
+ }
+}
diff --git a/cli/tests/lsp/did_open_params_semantic_tokens.json b/cli/tests/lsp/did_open_params_semantic_tokens.json
new file mode 100644
index 000000000..5cf48ae05
--- /dev/null
+++ b/cli/tests/lsp/did_open_params_semantic_tokens.json
@@ -0,0 +1,8 @@
+{
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "enum Values { value1, value2 }\n\nasync function baz(s: string): Promise<string> {\n const r = s.slice(0);\n return r;\n}\n\ninterface IFoo {\n readonly x: number;\n foo(): boolean;\n}\n\nclass Bar implements IFoo {\n constructor(public readonly x: number) { }\n foo() { return true; }\n static staticBar = new Bar(0);\n private static getStaticBar() { return Bar.staticBar; }\n}\n"
+ }
+}
diff --git a/cli/tests/lsp/document_symbol_did_open_notification.json b/cli/tests/lsp/document_symbol_did_open_notification.json
deleted file mode 100644
index 31c37c152..000000000
--- a/cli/tests/lsp/document_symbol_did_open_notification.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "interface IFoo {\n foo(): boolean;\n}\n\nclass Bar implements IFoo {\n constructor(public x: number) { }\n foo() { return true; }\n /** @deprecated */\n baz() { return false; }\n get value(): number { return 0; }\n set value(newVavlue: number) { return; }\n static staticBar = new Bar(0);\n private static getStaticBar() { return Bar.staticBar; }\n}\n\nenum Values { value1, value2 }\n\nvar bar: IFoo = new Bar(3);"
- }
- }
-}
diff --git a/cli/tests/lsp/document_symbol_request.json b/cli/tests/lsp/document_symbol_request.json
deleted file mode 100644
index a31317fc3..000000000
--- a/cli/tests/lsp/document_symbol_request.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/documentSymbol",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- }
- }
-}
diff --git a/cli/tests/lsp/document_symbol_response.json b/cli/tests/lsp/document_symbol_response.json
new file mode 100644
index 000000000..89d56ef70
--- /dev/null
+++ b/cli/tests/lsp/document_symbol_response.json
@@ -0,0 +1,371 @@
+[
+ {
+ "name": "bar",
+ "kind": 13,
+ "range": {
+ "start": {
+ "line": 17,
+ "character": 4
+ },
+ "end": {
+ "line": 17,
+ "character": 26
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 17,
+ "character": 4
+ },
+ "end": {
+ "line": 17,
+ "character": 7
+ }
+ }
+ },
+ {
+ "name": "Bar",
+ "kind": 5,
+ "range": {
+ "start": {
+ "line": 4,
+ "character": 0
+ },
+ "end": {
+ "line": 13,
+ "character": 1
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 4,
+ "character": 6
+ },
+ "end": {
+ "line": 4,
+ "character": 9
+ }
+ },
+ "children": [
+ {
+ "name": "constructor",
+ "kind": 9,
+ "range": {
+ "start": {
+ "line": 5,
+ "character": 2
+ },
+ "end": {
+ "line": 5,
+ "character": 35
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 5,
+ "character": 2
+ },
+ "end": {
+ "line": 5,
+ "character": 35
+ }
+ }
+ },
+ {
+ "name": "baz",
+ "kind": 6,
+ "tags": [
+ 1
+ ],
+ "range": {
+ "start": {
+ "line": 8,
+ "character": 2
+ },
+ "end": {
+ "line": 8,
+ "character": 25
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 8,
+ "character": 2
+ },
+ "end": {
+ "line": 8,
+ "character": 5
+ }
+ }
+ },
+ {
+ "name": "foo",
+ "kind": 6,
+ "range": {
+ "start": {
+ "line": 6,
+ "character": 2
+ },
+ "end": {
+ "line": 6,
+ "character": 24
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 6,
+ "character": 2
+ },
+ "end": {
+ "line": 6,
+ "character": 5
+ }
+ }
+ },
+ {
+ "name": "getStaticBar",
+ "kind": 6,
+ "range": {
+ "start": {
+ "line": 12,
+ "character": 2
+ },
+ "end": {
+ "line": 12,
+ "character": 57
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 12,
+ "character": 17
+ },
+ "end": {
+ "line": 12,
+ "character": 29
+ }
+ }
+ },
+ {
+ "name": "staticBar",
+ "kind": 7,
+ "range": {
+ "start": {
+ "line": 11,
+ "character": 2
+ },
+ "end": {
+ "line": 11,
+ "character": 32
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 11,
+ "character": 9
+ },
+ "end": {
+ "line": 11,
+ "character": 18
+ }
+ }
+ },
+ {
+ "name": "value",
+ "kind": 7,
+ "range": {
+ "start": {
+ "line": 9,
+ "character": 2
+ },
+ "end": {
+ "line": 9,
+ "character": 35
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 9,
+ "character": 6
+ },
+ "end": {
+ "line": 9,
+ "character": 11
+ }
+ }
+ },
+ {
+ "name": "value",
+ "kind": 7,
+ "range": {
+ "start": {
+ "line": 10,
+ "character": 2
+ },
+ "end": {
+ "line": 10,
+ "character": 42
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 10,
+ "character": 6
+ },
+ "end": {
+ "line": 10,
+ "character": 11
+ }
+ }
+ },
+ {
+ "name": "x",
+ "kind": 7,
+ "range": {
+ "start": {
+ "line": 5,
+ "character": 14
+ },
+ "end": {
+ "line": 5,
+ "character": 30
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 5,
+ "character": 21
+ },
+ "end": {
+ "line": 5,
+ "character": 22
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "IFoo",
+ "kind": 11,
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 0
+ },
+ "end": {
+ "line": 2,
+ "character": 1
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 0,
+ "character": 10
+ },
+ "end": {
+ "line": 0,
+ "character": 14
+ }
+ },
+ "children": [
+ {
+ "name": "foo",
+ "kind": 6,
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 2
+ },
+ "end": {
+ "line": 1,
+ "character": 17
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 1,
+ "character": 2
+ },
+ "end": {
+ "line": 1,
+ "character": 5
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "Values",
+ "kind": 10,
+ "range": {
+ "start": {
+ "line": 15,
+ "character": 0
+ },
+ "end": {
+ "line": 15,
+ "character": 30
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 15,
+ "character": 5
+ },
+ "end": {
+ "line": 15,
+ "character": 11
+ }
+ },
+ "children": [
+ {
+ "name": "value1",
+ "kind": 13,
+ "range": {
+ "start": {
+ "line": 15,
+ "character": 14
+ },
+ "end": {
+ "line": 15,
+ "character": 20
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 15,
+ "character": 14
+ },
+ "end": {
+ "line": 15,
+ "character": 20
+ }
+ }
+ },
+ {
+ "name": "value2",
+ "kind": 13,
+ "range": {
+ "start": {
+ "line": 15,
+ "character": 22
+ },
+ "end": {
+ "line": 15,
+ "character": 28
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 15,
+ "character": 22
+ },
+ "end": {
+ "line": 15,
+ "character": 28
+ }
+ }
+ }
+ ]
+ }
+]
diff --git a/cli/tests/lsp/exit_notification.json b/cli/tests/lsp/exit_notification.json
deleted file mode 100644
index 799a0d1d5..000000000
--- a/cli/tests/lsp/exit_notification.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "exit",
- "params": null
-}
diff --git a/cli/tests/lsp/folding_range_did_open_notification.json b/cli/tests/lsp/folding_range_did_open_notification.json
deleted file mode 100644
index 938d99751..000000000
--- a/cli/tests/lsp/folding_range_did_open_notification.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "// #region 1\n/*\n * Some comment\n */\nclass Foo {\n bar(a, b) {\n if (a === b) {\n return true;\n }\n return false;\n }\n}\n// #endregion"
- }
- }
-}
diff --git a/cli/tests/lsp/folding_range_request.json b/cli/tests/lsp/folding_range_request.json
deleted file mode 100644
index e82b6ec0b..000000000
--- a/cli/tests/lsp/folding_range_request.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/foldingRange",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- }
- }
-}
diff --git a/cli/tests/lsp/formatting_mbc_response.json b/cli/tests/lsp/formatting_mbc_response.json
new file mode 100644
index 000000000..1c0b9f8e8
--- /dev/null
+++ b/cli/tests/lsp/formatting_mbc_response.json
@@ -0,0 +1,54 @@
+[
+ {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 12
+ },
+ "end": {
+ "line": 0,
+ "character": 13
+ }
+ },
+ "newText": "\""
+ },
+ {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 21
+ },
+ "end": {
+ "line": 0,
+ "character": 22
+ }
+ },
+ "newText": "\";"
+ },
+ {
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 12
+ },
+ "end": {
+ "line": 1,
+ "character": 13
+ }
+ },
+ "newText": "\""
+ },
+ {
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 23
+ },
+ "end": {
+ "line": 1,
+ "character": 25
+ }
+ },
+ "newText": "\");"
+ }
+]
diff --git a/cli/tests/lsp/formatting_request_mbc_fmt.json b/cli/tests/lsp/formatting_request_mbc_fmt.json
deleted file mode 100644
index f20cc18e6..000000000
--- a/cli/tests/lsp/formatting_request_mbc_fmt.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/formatting",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "options": {
- "tabSize": 2,
- "insertSpaces": true
- }
- }
-}
diff --git a/cli/tests/lsp/hover_request.json b/cli/tests/lsp/hover_request.json
deleted file mode 100644
index f12bd52df..000000000
--- a/cli/tests/lsp/hover_request.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/hover",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 0,
- "character": 19
- }
- }
-}
diff --git a/cli/tests/lsp/hover_request_asset.json b/cli/tests/lsp/hover_request_asset.json
deleted file mode 100644
index 2ae96acd5..000000000
--- a/cli/tests/lsp/hover_request_asset.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 5,
- "method": "textDocument/hover",
- "params": {
- "textDocument": {
- "uri": "deno:/asset//lib.es2015.symbol.wellknown.d.ts"
- },
- "position": {
- "line": 109,
- "character": 13
- }
- }
-}
diff --git a/cli/tests/lsp/hover_request_large_01.json b/cli/tests/lsp/hover_request_large_01.json
deleted file mode 100644
index 78ddee5a3..000000000
--- a/cli/tests/lsp/hover_request_large_01.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/hover",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 421,
- "character": 30
- }
- }
-}
diff --git a/cli/tests/lsp/hover_request_large_02.json b/cli/tests/lsp/hover_request_large_02.json
deleted file mode 100644
index 4d7eae150..000000000
--- a/cli/tests/lsp/hover_request_large_02.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/hover",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 444,
- "character": 6
- }
- }
-}
diff --git a/cli/tests/lsp/hover_request_large_03.json b/cli/tests/lsp/hover_request_large_03.json
deleted file mode 100644
index 5309450dd..000000000
--- a/cli/tests/lsp/hover_request_large_03.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/hover",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 461,
- "character": 34
- }
- }
-}
diff --git a/cli/tests/lsp/hover_request_mbc.json b/cli/tests/lsp/hover_request_mbc.json
deleted file mode 100644
index 6e7c55e08..000000000
--- a/cli/tests/lsp/hover_request_mbc.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/hover",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 2,
- "character": 15
- }
- }
-}
diff --git a/cli/tests/lsp/incoming_calls_params.json b/cli/tests/lsp/incoming_calls_params.json
new file mode 100644
index 000000000..6b38d26ee
--- /dev/null
+++ b/cli/tests/lsp/incoming_calls_params.json
@@ -0,0 +1,28 @@
+{
+ "item": {
+ "name": "baz",
+ "kind": 6,
+ "detail": "Bar",
+ "uri": "file:///a/file.ts",
+ "range": {
+ "start": {
+ "line": 5,
+ "character": 2
+ },
+ "end": {
+ "line": 7,
+ "character": 3
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 5,
+ "character": 2
+ },
+ "end": {
+ "line": 5,
+ "character": 5
+ }
+ }
+ }
+}
diff --git a/cli/tests/lsp/incoming_calls_request.json b/cli/tests/lsp/incoming_calls_request.json
deleted file mode 100644
index 47af92c1b..000000000
--- a/cli/tests/lsp/incoming_calls_request.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "callHierarchy/incomingCalls",
- "params": {
- "item": {
- "name": "baz",
- "kind": 6,
- "detail": "Bar",
- "uri": "file:///a/file.ts",
- "range": {
- "start": {
- "line": 5,
- "character": 2
- },
- "end": {
- "line": 7,
- "character": 3
- }
- },
- "selectionRange": {
- "start": {
- "line": 5,
- "character": 2
- },
- "end": {
- "line": 5,
- "character": 5
- }
- }
- }
- }
-}
diff --git a/cli/tests/lsp/incoming_calls_response.json b/cli/tests/lsp/incoming_calls_response.json
new file mode 100644
index 000000000..231919a8c
--- /dev/null
+++ b/cli/tests/lsp/incoming_calls_response.json
@@ -0,0 +1,42 @@
+[
+ {
+ "from": {
+ "name": "main",
+ "kind": 12,
+ "detail": "",
+ "uri": "file:///a/file.ts",
+ "range": {
+ "start": {
+ "line": 10,
+ "character": 0
+ },
+ "end": {
+ "line": 13,
+ "character": 1
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 10,
+ "character": 9
+ },
+ "end": {
+ "line": 10,
+ "character": 13
+ }
+ }
+ },
+ "fromRanges": [
+ {
+ "start": {
+ "line": 12,
+ "character": 6
+ },
+ "end": {
+ "line": 12,
+ "character": 9
+ }
+ }
+ ]
+ }
+]
diff --git a/cli/tests/lsp/initialize_params.json b/cli/tests/lsp/initialize_params.json
new file mode 100644
index 000000000..b00e5720d
--- /dev/null
+++ b/cli/tests/lsp/initialize_params.json
@@ -0,0 +1,56 @@
+{
+ "processId": 0,
+ "clientInfo": {
+ "name": "test-harness",
+ "version": "1.0.0"
+ },
+ "rootUri": null,
+ "initializationOptions": {
+ "enable": true,
+ "codeLens": {
+ "implementations": true,
+ "references": true
+ },
+ "importMap": null,
+ "lint": true,
+ "suggest": {
+ "autoImports": true,
+ "completeFunctionCalls": false,
+ "names": true,
+ "paths": true,
+ "imports": {
+ "hosts": {}
+ }
+ },
+ "unstable": false
+ },
+ "capabilities": {
+ "textDocument": {
+ "codeAction": {
+ "codeActionLiteralSupport": {
+ "codeActionKind": {
+ "valueSet": [
+ "quickfix"
+ ]
+ }
+ },
+ "isPreferredSupport": true,
+ "dataSupport": true,
+ "resolveSupport": {
+ "properties": [
+ "edit"
+ ]
+ }
+ },
+ "foldingRange": {
+ "lineFoldingOnly": true
+ },
+ "synchronization": {
+ "dynamicRegistration": true,
+ "willSave": true,
+ "willSaveWaitUntil": true,
+ "didSave": true
+ }
+ }
+ }
+}
diff --git a/cli/tests/lsp/initialize_params_disabled.json b/cli/tests/lsp/initialize_params_disabled.json
new file mode 100644
index 000000000..ea12dfac5
--- /dev/null
+++ b/cli/tests/lsp/initialize_params_disabled.json
@@ -0,0 +1,56 @@
+{
+ "processId": 0,
+ "clientInfo": {
+ "name": "test-harness",
+ "version": "1.0.0"
+ },
+ "rootUri": null,
+ "initializationOptions": {
+ "enable": false,
+ "codeLens": {
+ "implementations": true,
+ "references": true
+ },
+ "importMap": null,
+ "lint": true,
+ "suggest": {
+ "autoImports": true,
+ "completeFunctionCalls": false,
+ "names": true,
+ "paths": true,
+ "imports": {
+ "hosts": {}
+ }
+ },
+ "unstable": false
+ },
+ "capabilities": {
+ "textDocument": {
+ "codeAction": {
+ "codeActionLiteralSupport": {
+ "codeActionKind": {
+ "valueSet": [
+ "quickfix"
+ ]
+ }
+ },
+ "isPreferredSupport": true,
+ "dataSupport": true,
+ "resolveSupport": {
+ "properties": [
+ "edit"
+ ]
+ }
+ },
+ "foldingRange": {
+ "lineFoldingOnly": true
+ },
+ "synchronization": {
+ "dynamicRegistration": true,
+ "willSave": true,
+ "willSaveWaitUntil": true,
+ "didSave": true
+ }
+ }
+ }
+}
diff --git a/cli/tests/lsp/initialize_params_registry.json b/cli/tests/lsp/initialize_params_registry.json
new file mode 100644
index 000000000..38777b3d4
--- /dev/null
+++ b/cli/tests/lsp/initialize_params_registry.json
@@ -0,0 +1,58 @@
+{
+ "processId": 0,
+ "clientInfo": {
+ "name": "test-harness",
+ "version": "1.0.0"
+ },
+ "rootUri": null,
+ "initializationOptions": {
+ "enable": true,
+ "codeLens": {
+ "implementations": true,
+ "references": true
+ },
+ "importMap": null,
+ "lint": true,
+ "suggest": {
+ "autoImports": true,
+ "completeFunctionCalls": false,
+ "names": true,
+ "paths": true,
+ "imports": {
+ "hosts": {
+ "http://localhost:4545/": true
+ }
+ }
+ },
+ "unstable": false
+ },
+ "capabilities": {
+ "textDocument": {
+ "codeAction": {
+ "codeActionLiteralSupport": {
+ "codeActionKind": {
+ "valueSet": [
+ "quickfix"
+ ]
+ }
+ },
+ "isPreferredSupport": true,
+ "dataSupport": true,
+ "resolveSupport": {
+ "properties": [
+ "edit"
+ ]
+ }
+ },
+ "foldingRange": {
+ "lineFoldingOnly": true
+ },
+ "synchronization": {
+ "dynamicRegistration": true,
+ "willSave": true,
+ "willSaveWaitUntil": true,
+ "didSave": true
+ }
+ }
+ }
+}
diff --git a/cli/tests/lsp/initialize_params_unstable.json b/cli/tests/lsp/initialize_params_unstable.json
new file mode 100644
index 000000000..fd8ccdd83
--- /dev/null
+++ b/cli/tests/lsp/initialize_params_unstable.json
@@ -0,0 +1,56 @@
+{
+ "processId": 0,
+ "clientInfo": {
+ "name": "test-harness",
+ "version": "1.0.0"
+ },
+ "rootUri": null,
+ "initializationOptions": {
+ "enable": true,
+ "codeLens": {
+ "implementations": true,
+ "references": true
+ },
+ "importMap": null,
+ "lint": true,
+ "suggest": {
+ "autoImports": true,
+ "completeFunctionCalls": false,
+ "names": true,
+ "paths": true,
+ "imports": {
+ "hosts": {}
+ }
+ },
+ "unstable": true
+ },
+ "capabilities": {
+ "textDocument": {
+ "codeAction": {
+ "codeActionLiteralSupport": {
+ "codeActionKind": {
+ "valueSet": [
+ "quickfix"
+ ]
+ }
+ },
+ "isPreferredSupport": true,
+ "dataSupport": true,
+ "resolveSupport": {
+ "properties": [
+ "edit"
+ ]
+ }
+ },
+ "foldingRange": {
+ "lineFoldingOnly": true
+ },
+ "synchronization": {
+ "dynamicRegistration": true,
+ "willSave": true,
+ "willSaveWaitUntil": true,
+ "didSave": true
+ }
+ }
+ }
+}
diff --git a/cli/tests/lsp/initialize_request.json b/cli/tests/lsp/initialize_request.json
deleted file mode 100644
index a6610ffe9..000000000
--- a/cli/tests/lsp/initialize_request.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 1,
- "method": "initialize",
- "params": {
- "processId": 0,
- "clientInfo": {
- "name": "test-harness",
- "version": "1.0.0"
- },
- "rootUri": null,
- "initializationOptions": {
- "enable": true,
- "codeLens": {
- "implementations": true,
- "references": true
- },
- "importMap": null,
- "lint": true,
- "suggest": {
- "autoImports": true,
- "completeFunctionCalls": false,
- "names": true,
- "paths": true,
- "imports": {
- "hosts": {}
- }
- },
- "unstable": false
- },
- "capabilities": {
- "textDocument": {
- "codeAction": {
- "codeActionLiteralSupport": {
- "codeActionKind": {
- "valueSet": [
- "quickfix"
- ]
- }
- },
- "isPreferredSupport": true,
- "dataSupport": true,
- "resolveSupport": {
- "properties": [
- "edit"
- ]
- }
- },
- "foldingRange": {
- "lineFoldingOnly": true
- },
- "synchronization": {
- "dynamicRegistration": true,
- "willSave": true,
- "willSaveWaitUntil": true,
- "didSave": true
- }
- }
- }
- }
-}
diff --git a/cli/tests/lsp/initialize_request_disabled.json b/cli/tests/lsp/initialize_request_disabled.json
deleted file mode 100644
index f763375f8..000000000
--- a/cli/tests/lsp/initialize_request_disabled.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 1,
- "method": "initialize",
- "params": {
- "processId": 0,
- "clientInfo": {
- "name": "test-harness",
- "version": "1.0.0"
- },
- "rootUri": null,
- "initializationOptions": {
- "enable": false,
- "lint": true,
- "importMap": null,
- "unstable": false
- },
- "capabilities": {
- "textDocument": {
- "synchronization": {
- "dynamicRegistration": true,
- "willSave": true,
- "willSaveWaitUntil": true,
- "didSave": true
- }
- }
- }
- }
-}
diff --git a/cli/tests/lsp/initialize_request_registry.json b/cli/tests/lsp/initialize_request_registry.json
deleted file mode 100644
index 94480934f..000000000
--- a/cli/tests/lsp/initialize_request_registry.json
+++ /dev/null
@@ -1,63 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 1,
- "method": "initialize",
- "params": {
- "processId": 0,
- "clientInfo": {
- "name": "test-harness",
- "version": "1.0.0"
- },
- "rootUri": null,
- "initializationOptions": {
- "enable": true,
- "codeLens": {
- "implementations": true,
- "references": true
- },
- "importMap": null,
- "lint": true,
- "suggest": {
- "autoImports": true,
- "completeFunctionCalls": false,
- "names": true,
- "paths": true,
- "imports": {
- "hosts": {
- "http://localhost:4545/": true
- }
- }
- },
- "unstable": false
- },
- "capabilities": {
- "textDocument": {
- "codeAction": {
- "codeActionLiteralSupport": {
- "codeActionKind": {
- "valueSet": [
- "quickfix"
- ]
- }
- },
- "isPreferredSupport": true,
- "dataSupport": true,
- "resolveSupport": {
- "properties": [
- "edit"
- ]
- }
- },
- "foldingRange": {
- "lineFoldingOnly": true
- },
- "synchronization": {
- "dynamicRegistration": true,
- "willSave": true,
- "willSaveWaitUntil": true,
- "didSave": true
- }
- }
- }
- }
-}
diff --git a/cli/tests/lsp/initialize_request_unstable.json b/cli/tests/lsp/initialize_request_unstable.json
deleted file mode 100644
index 8c086c838..000000000
--- a/cli/tests/lsp/initialize_request_unstable.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 1,
- "method": "initialize",
- "params": {
- "processId": 0,
- "clientInfo": {
- "name": "test-harness",
- "version": "1.0.0"
- },
- "rootUri": null,
- "initializationOptions": {
- "enable": true,
- "lint": true,
- "unstable": true,
- "config": null,
- "importMap": null
- },
- "capabilities": {
- "textDocument": {
- "synchronization": {
- "dynamicRegistration": true,
- "willSave": true,
- "willSaveWaitUntil": true,
- "didSave": true
- }
- }
- }
- }
-}
diff --git a/cli/tests/lsp/initialized_notification.json b/cli/tests/lsp/initialized_notification.json
deleted file mode 100644
index 972f8abc8..000000000
--- a/cli/tests/lsp/initialized_notification.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "initialized",
- "params": {}
-}
diff --git a/cli/tests/lsp/outgoing_calls_params.json b/cli/tests/lsp/outgoing_calls_params.json
new file mode 100644
index 000000000..6b38d26ee
--- /dev/null
+++ b/cli/tests/lsp/outgoing_calls_params.json
@@ -0,0 +1,28 @@
+{
+ "item": {
+ "name": "baz",
+ "kind": 6,
+ "detail": "Bar",
+ "uri": "file:///a/file.ts",
+ "range": {
+ "start": {
+ "line": 5,
+ "character": 2
+ },
+ "end": {
+ "line": 7,
+ "character": 3
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 5,
+ "character": 2
+ },
+ "end": {
+ "line": 5,
+ "character": 5
+ }
+ }
+ }
+}
diff --git a/cli/tests/lsp/outgoing_calls_request.json b/cli/tests/lsp/outgoing_calls_request.json
deleted file mode 100644
index a8d224ae8..000000000
--- a/cli/tests/lsp/outgoing_calls_request.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 5,
- "method": "callHierarchy/outgoingCalls",
- "params": {
- "item": {
- "name": "baz",
- "kind": 6,
- "detail": "Bar",
- "uri": "file:///a/file.ts",
- "range": {
- "start": {
- "line": 5,
- "character": 2
- },
- "end": {
- "line": 7,
- "character": 3
- }
- },
- "selectionRange": {
- "start": {
- "line": 5,
- "character": 2
- },
- "end": {
- "line": 5,
- "character": 5
- }
- }
- }
- }
-}
diff --git a/cli/tests/lsp/outgoing_calls_response.json b/cli/tests/lsp/outgoing_calls_response.json
new file mode 100644
index 000000000..c7cf85cf8
--- /dev/null
+++ b/cli/tests/lsp/outgoing_calls_response.json
@@ -0,0 +1,42 @@
+[
+ {
+ "to": {
+ "name": "foo",
+ "kind": 12,
+ "detail": "",
+ "uri": "file:///a/file.ts",
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 0
+ },
+ "end": {
+ "line": 2,
+ "character": 1
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 0,
+ "character": 9
+ },
+ "end": {
+ "line": 0,
+ "character": 12
+ }
+ }
+ },
+ "fromRanges": [
+ {
+ "start": {
+ "line": 6,
+ "character": 11
+ },
+ "end": {
+ "line": 6,
+ "character": 14
+ }
+ }
+ ]
+ }
+]
diff --git a/cli/tests/lsp/performance_request.json b/cli/tests/lsp/performance_request.json
deleted file mode 100644
index cb389cb9d..000000000
--- a/cli/tests/lsp/performance_request.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 99,
- "method": "deno/performance",
- "params": {}
-}
diff --git a/cli/tests/lsp/prepare_call_hierarchy_did_open_notification.json b/cli/tests/lsp/prepare_call_hierarchy_did_open_notification.json
deleted file mode 100644
index a75bd3a53..000000000
--- a/cli/tests/lsp/prepare_call_hierarchy_did_open_notification.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "function foo() {\n return false;\n}\n\nclass Bar {\n baz() {\n return foo();\n }\n}\n\nfunction main() {\n const bar = new Bar();\n bar.baz();\n}\n\nmain();"
- }
- }
-}
diff --git a/cli/tests/lsp/prepare_call_hierarchy_request.json b/cli/tests/lsp/prepare_call_hierarchy_request.json
deleted file mode 100644
index 1f469ee8b..000000000
--- a/cli/tests/lsp/prepare_call_hierarchy_request.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/prepareCallHierarchy",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 5,
- "character": 3
- }
- }
-}
diff --git a/cli/tests/lsp/prepare_call_hierarchy_response.json b/cli/tests/lsp/prepare_call_hierarchy_response.json
new file mode 100644
index 000000000..93a7d4f1b
--- /dev/null
+++ b/cli/tests/lsp/prepare_call_hierarchy_response.json
@@ -0,0 +1,28 @@
+[
+ {
+ "name": "baz",
+ "kind": 6,
+ "detail": "Bar",
+ "uri": "file:///a/file.ts",
+ "range": {
+ "start": {
+ "line": 5,
+ "character": 2
+ },
+ "end": {
+ "line": 7,
+ "character": 3
+ }
+ },
+ "selectionRange": {
+ "start": {
+ "line": 5,
+ "character": 2
+ },
+ "end": {
+ "line": 5,
+ "character": 5
+ }
+ }
+ }
+]
diff --git a/cli/tests/lsp/references_request_asset.json b/cli/tests/lsp/references_request_asset.json
deleted file mode 100644
index 6c2430e50..000000000
--- a/cli/tests/lsp/references_request_asset.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/references",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 0,
- "character": 3
- },
- "context": {
- "includeDeclaration": true
- }
- }
-}
diff --git a/cli/tests/lsp/rename_did_open_notification.json b/cli/tests/lsp/rename_did_open_notification.json
deleted file mode 100644
index c6323b742..000000000
--- a/cli/tests/lsp/rename_did_open_notification.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "let variable = 'a';\nconsole.log(variable);"
- }
- }
-}
diff --git a/cli/tests/lsp/rename_request.json b/cli/tests/lsp/rename_request.json
deleted file mode 100644
index a317d9257..000000000
--- a/cli/tests/lsp/rename_request.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/rename",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "line": 0,
- "character": 4
- },
- "newName": "variable_modified"
- }
-}
diff --git a/cli/tests/lsp/rename_response.json b/cli/tests/lsp/rename_response.json
new file mode 100644
index 000000000..5e0e28e4c
--- /dev/null
+++ b/cli/tests/lsp/rename_response.json
@@ -0,0 +1,38 @@
+{
+ "documentChanges": [
+ {
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "version": 1
+ },
+ "edits": [
+ {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 4
+ },
+ "end": {
+ "line": 0,
+ "character": 12
+ }
+ },
+ "newText": "variable_modified"
+ },
+ {
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 12
+ },
+ "end": {
+ "line": 1,
+ "character": 20
+ }
+ },
+ "newText": "variable_modified"
+ }
+ ]
+ }
+ ]
+}
diff --git a/cli/tests/lsp/selection_range_did_open_notification.json b/cli/tests/lsp/selection_range_did_open_notification.json
deleted file mode 100644
index a6b3d9d39..000000000
--- a/cli/tests/lsp/selection_range_did_open_notification.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "class Foo {\n bar(a, b) {\n if (a === b) {\n return true;\n }\n return false;\n }\n}"
- }
- }
-}
diff --git a/cli/tests/lsp/selection_range_request.json b/cli/tests/lsp/selection_range_request.json
deleted file mode 100644
index 5125fa6a0..000000000
--- a/cli/tests/lsp/selection_range_request.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/selectionRange",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "positions": [
- {
- "line": 2,
- "character": 8
- }
- ]
- }
-}
diff --git a/cli/tests/lsp/selection_range_response.json b/cli/tests/lsp/selection_range_response.json
new file mode 100644
index 000000000..b5eef5ddc
--- /dev/null
+++ b/cli/tests/lsp/selection_range_response.json
@@ -0,0 +1,86 @@
+[
+ {
+ "range": {
+ "start": {
+ "line": 2,
+ "character": 8
+ },
+ "end": {
+ "line": 2,
+ "character": 9
+ }
+ },
+ "parent": {
+ "range": {
+ "start": {
+ "line": 2,
+ "character": 8
+ },
+ "end": {
+ "line": 2,
+ "character": 15
+ }
+ },
+ "parent": {
+ "range": {
+ "start": {
+ "line": 2,
+ "character": 4
+ },
+ "end": {
+ "line": 4,
+ "character": 5
+ }
+ },
+ "parent": {
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 13
+ },
+ "end": {
+ "line": 6,
+ "character": 2
+ }
+ },
+ "parent": {
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 2
+ },
+ "end": {
+ "line": 6,
+ "character": 3
+ }
+ },
+ "parent": {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 11
+ },
+ "end": {
+ "line": 7,
+ "character": 0
+ }
+ },
+ "parent": {
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 0
+ },
+ "end": {
+ "line": 7,
+ "character": 1
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+]
diff --git a/cli/tests/lsp/semantic_tokens_did_open_notification.json b/cli/tests/lsp/semantic_tokens_did_open_notification.json
deleted file mode 100644
index 3bf1f6c44..000000000
--- a/cli/tests/lsp/semantic_tokens_did_open_notification.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "enum Values { value1, value2 }\n\nasync function baz(s: string): Promise<string> {\n const r = s.slice(0);\n return r;\n}\n\ninterface IFoo {\n readonly x: number;\n foo(): boolean;\n}\n\nclass Bar implements IFoo {\n constructor(public readonly x: number) { }\n foo() { return true; }\n static staticBar = new Bar(0);\n private static getStaticBar() { return Bar.staticBar; }\n}\n"
- }
- }
-}
diff --git a/cli/tests/lsp/semantic_tokens_full_request.json b/cli/tests/lsp/semantic_tokens_full_request.json
deleted file mode 100644
index 748cc4382..000000000
--- a/cli/tests/lsp/semantic_tokens_full_request.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 2,
- "method": "textDocument/semanticTokens/full",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- }
- }
-}
diff --git a/cli/tests/lsp/semantic_tokens_range_request.json b/cli/tests/lsp/semantic_tokens_range_request.json
deleted file mode 100644
index 3b09944a1..000000000
--- a/cli/tests/lsp/semantic_tokens_range_request.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "textDocument/semanticTokens/range",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "range": {
- "start": {
- "line": 0,
- "character": 0
- },
- "end": {
- "line": 6,
- "character": 0
- }
- }
- }
-}
diff --git a/cli/tests/lsp/shutdown_request.json b/cli/tests/lsp/shutdown_request.json
deleted file mode 100644
index fd4d78460..000000000
--- a/cli/tests/lsp/shutdown_request.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 3,
- "method": "shutdown",
- "params": null
-}
diff --git a/cli/tests/lsp/signature_help_did_change_notification.json b/cli/tests/lsp/signature_help_did_change_notification.json
deleted file mode 100644
index f88eaa9ff..000000000
--- a/cli/tests/lsp/signature_help_did_change_notification.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didChange",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "version": 2
- },
- "contentChanges": [
- {
- "range": {
- "start": {
- "line": 9,
- "character": 4
- },
- "end": {
- "line": 9,
- "character": 4
- }
- },
- "text": "123, "
- }
- ]
- }
-}
diff --git a/cli/tests/lsp/signature_help_did_open_notification.json b/cli/tests/lsp/signature_help_did_open_notification.json
deleted file mode 100644
index 1ba1f7586..000000000
--- a/cli/tests/lsp/signature_help_did_open_notification.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "jsonrpc": "2.0",
- "method": "textDocument/didOpen",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "/**\n * Adds two numbers.\n * @param a This is a first number.\n * @param b This is a second number.\n */\nfunction add(a: number, b: number) {\n return a + b;\n}\n\nadd("
- }
- }
-}
diff --git a/cli/tests/lsp/signature_help_request_01.json b/cli/tests/lsp/signature_help_request_01.json
deleted file mode 100644
index c3e185e08..000000000
--- a/cli/tests/lsp/signature_help_request_01.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 1,
- "method": "textDocument/signatureHelp",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "character": 4,
- "line": 9
- },
- "context": {
- "triggerKind": 2,
- "triggerCharacter": "(",
- "isRetrigger": false
- }
- }
-}
diff --git a/cli/tests/lsp/signature_help_request_02.json b/cli/tests/lsp/signature_help_request_02.json
deleted file mode 100644
index c2a6e0abb..000000000
--- a/cli/tests/lsp/signature_help_request_02.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "id": 2,
- "jsonrpc": "2.0",
- "method": "textDocument/signatureHelp",
- "params": {
- "textDocument": {
- "uri": "file:///a/file.ts"
- },
- "position": {
- "character": 8,
- "line": 9
- }
- }
-}
diff --git a/cli/tests/lsp/virtual_text_document_request.json b/cli/tests/lsp/virtual_text_document_request.json
deleted file mode 100644
index 6ffab4a35..000000000
--- a/cli/tests/lsp/virtual_text_document_request.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "jsonrpc": "2.0",
- "id": 4,
- "method": "deno/virtualTextDocument",
- "params": {
- "textDocument": {
- "uri": "deno:/asset//lib.deno.shared_globals.d.ts"
- }
- }
-}