Skip to content

Commit

Permalink
Scaffold textDocuments/references implementation
Browse files Browse the repository at this point in the history
commit-id:c0e7d4d8
  • Loading branch information
mkaput committed Dec 20, 2024
1 parent 38ee40c commit 3403069
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/ide/navigation/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod goto_definition;
pub mod references;
8 changes: 8 additions & 0 deletions src/ide/navigation/references.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use lsp_types::{Location, ReferenceParams};

use crate::lang::db::AnalysisDatabase;

pub fn references(_params: ReferenceParams, _db: &AnalysisDatabase) -> Option<Vec<Location>> {
// TODO(mkaput): Implement this.
None
}
7 changes: 7 additions & 0 deletions src/lsp/capabilities/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ pub trait ClientCapabilitiesExt {

/// The client supports dynamic registration for code action capabilities.
fn code_action_dynamic_registration(&self) -> bool;

/// The client supports dynamic registration for references provider capabilities.
fn references_provider_dynamic_registration(&self) -> bool;
}

impl ClientCapabilitiesExt for ClientCapabilities {
Expand Down Expand Up @@ -88,4 +91,8 @@ impl ClientCapabilitiesExt for ClientCapabilities {
fn code_action_dynamic_registration(&self) -> bool {
try_or_default!(self.text_document.as_ref()?.code_action.as_ref()?.dynamic_registration?)
}

fn references_provider_dynamic_registration(&self) -> bool {
try_or_default!(self.text_document.as_ref()?.references.as_ref()?.dynamic_registration?)
}
}
13 changes: 12 additions & 1 deletion src/lsp/capabilities/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ pub fn collect_server_capabilities(client_capabilities: &ClientCapabilities) ->
.code_action_dynamic_registration()
.not()
.then_some(CodeActionProviderCapability::Simple(true)),
references_provider: client_capabilities
.references_provider_dynamic_registration()
.not()
.then_some(OneOf::Left(true)),
..ServerCapabilities::default()
}
}
Expand Down Expand Up @@ -238,13 +242,20 @@ pub fn collect_dynamic_registrations(

if client_capabilities.code_action_dynamic_registration() {
let registration_options = CodeActionRegistrationOptions {
text_document_registration_options,
text_document_registration_options: text_document_registration_options.clone(),
code_action_options: Default::default(),
};

registrations.push(create_registration("textDocument/codeAction", registration_options));
}

if client_capabilities.references_provider_dynamic_registration() {
registrations.push(create_registration(
"textDocument/references",
&text_document_registration_options,
));
}

registrations
}

Expand Down
5 changes: 4 additions & 1 deletion src/server/routing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use lsp_types::notification::{
};
use lsp_types::request::{
CodeActionRequest, Completion, ExecuteCommand, Formatting, GotoDefinition, HoverRequest,
Request as RequestTrait, SemanticTokensFullRequest,
References, Request as RequestTrait, SemanticTokensFullRequest,
};
use tracing::{error, trace, warn};

Expand Down Expand Up @@ -57,6 +57,9 @@ pub fn request<'a>(request: Request) -> Task<'a> {
request,
BackgroundSchedule::LatencySensitive,
),
References::METHOD => {
background_request_task::<References>(request, BackgroundSchedule::LatencySensitive)
}
SemanticTokensFullRequest::METHOD => background_request_task::<SemanticTokensFullRequest>(
request,
BackgroundSchedule::Worker,
Expand Down
17 changes: 14 additions & 3 deletions src/server/routing/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ use lsp_types::notification::{
};
use lsp_types::request::{
CodeActionRequest, Completion, ExecuteCommand, Formatting, GotoDefinition, HoverRequest,
Request, SemanticTokensFullRequest,
References, Request, SemanticTokensFullRequest,
};
use lsp_types::{
CodeActionParams, CodeActionResponse, CompletionParams, CompletionResponse,
DidChangeConfigurationParams, DidChangeTextDocumentParams, DidChangeWatchedFilesParams,
DidCloseTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams,
DocumentFormattingParams, ExecuteCommandParams, GotoDefinitionParams, GotoDefinitionResponse,
Hover, HoverParams, SemanticTokensParams, SemanticTokensResult, TextDocumentContentChangeEvent,
TextDocumentPositionParams, TextEdit, Url,
Hover, HoverParams, ReferenceParams, SemanticTokensParams, SemanticTokensResult,
TextDocumentContentChangeEvent, TextDocumentPositionParams, TextEdit, Url,
};
use serde_json::Value;
use tracing::error;
Expand Down Expand Up @@ -359,6 +359,17 @@ impl BackgroundDocumentRequestHandler for ExpandMacro {
}
}

impl BackgroundDocumentRequestHandler for References {
#[tracing::instrument(name = "textDocument/references", skip_all)]
fn run_with_snapshot(
snapshot: StateSnapshot,
_notifier: Notifier,
params: ReferenceParams,
) -> LSPResult<Option<Vec<lsp_types::Location>>> {
Ok(ide::navigation::references::references(params, &snapshot.db))
}
}

fn is_cairo_file_path(file_path: &Url) -> bool {
file_path.path().ends_with(".cairo")
}
1 change: 1 addition & 0 deletions tests/e2e/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod completions;
mod goto_definition;
mod hover;
mod macro_expand;
mod references;
mod semantic_tokens;
mod support;
mod workspace_configuration;
83 changes: 83 additions & 0 deletions tests/e2e/references.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use cairo_lang_test_utils::parse_test_file::TestRunnerResult;
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use lsp_types::{
ClientCapabilities, ReferenceClientCapabilities, ReferenceContext, ReferenceParams,
TextDocumentClientCapabilities, TextDocumentPositionParams, lsp_request,
};

use crate::support::cursor::{peek_caret, peek_selection};
use crate::support::{cursors, sandbox};

cairo_lang_test_utils::test_file_test!(
references,
"tests/test_data/references",
{
fns: "fns.txt",
},
test_references
);

fn caps(base: ClientCapabilities) -> ClientCapabilities {
ClientCapabilities {
text_document: base.text_document.or_else(Default::default).map(|it| {
TextDocumentClientCapabilities {
references: Some(ReferenceClientCapabilities { dynamic_registration: Some(false) }),
..it
}
}),
..base
}
}

fn test_references(
inputs: &OrderedHashMap<String, String>,
args: &OrderedHashMap<String, String>,
) -> TestRunnerResult {
let (cairo, cursors) = cursors(&inputs["cairo_code"]);

let mut ls = sandbox! {
files {
"cairo_project.toml" => inputs["cairo_project.toml"].clone(),
"src/lib.cairo" => cairo.clone(),
}
client_capabilities = caps;
};

ls.open_all_cairo_files_and_wait_for_project_update();

let mut outputs = OrderedHashMap::default();
for (n, position) in cursors.carets().into_iter().enumerate() {
let mut report = String::new();
report.push_str(&peek_caret(&cairo, position));

let params = ReferenceParams {
text_document_position: TextDocumentPositionParams {
text_document: ls.doc_id("src/lib.cairo"),
position,
},
context: ReferenceContext {
include_declaration: args["include_declaration"] == "true",
},
work_done_progress_params: Default::default(),
partial_result_params: Default::default(),
};
let response = ls.send_request::<lsp_request!("textDocument/references")>(params);

if let Some(mut locations) = response {
// LS does not guarantee any order of the results.
locations
.sort_by_key(|loc| (loc.uri.as_str().to_owned(), loc.range.start, loc.range.end));

report.push_str("---");
for location in locations {
report.push('\n');
report.push_str(&peek_selection(&cairo, &location.range));
}
} else {
report.push_str("none response")
}

outputs.insert(format!("References #{n}"), report);
}
TestRunnerResult::success(outputs)
}
55 changes: 55 additions & 0 deletions tests/test_data/references/fns.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//! > Test references of function.

//! > test_runner_name
test_references(include_declaration: false)

//! > cairo_project.toml
[crate_roots]
hello = "src"

[config.global]
edition = "2024_07"

//! > cairo_code
fn pow<caret>2(x: felt252) -> felt252 { x * x }

fn main() {
let x = po<caret>w2(2) + pow2(3);
}

//! > References #0
fn pow<caret>2(x: felt252) -> felt252 { x * x }
none response

//! > References #1
let x = po<caret>w2(2) + pow2(3);
none response

//! > ==========================================================================

//! > Test references of function including declaration.

//! > test_runner_name
test_references(include_declaration: true)

//! > cairo_project.toml
[crate_roots]
hello = "src"

[config.global]
edition = "2024_07"

//! > cairo_code
fn pow<caret>2(x: felt252) -> felt252 { x * x }

fn main() {
let x = po<caret>w2(2) + pow2(3);
}

//! > References #0
fn pow<caret>2(x: felt252) -> felt252 { x * x }
none response

//! > References #1
let x = po<caret>w2(2) + pow2(3);
none response

0 comments on commit 3403069

Please sign in to comment.