Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add starting real goto definition tests #118

Merged
merged 1 commit into from
Dec 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions tests/e2e/goto.rs → tests/e2e/goto_definition.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use cairo_lang_test_utils::parse_test_file::TestRunnerResult;
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use indoc::indoc;
use lsp_types::{
ClientCapabilities, GotoCapability, GotoDefinitionParams, GotoDefinitionResponse,
TextDocumentClientCapabilities, TextDocumentPositionParams, lsp_request,
Expand All @@ -9,12 +10,17 @@ use crate::support::cursor::{peek_caret, peek_selection};
use crate::support::{cursors, sandbox};

cairo_lang_test_utils::test_file_test!(
goto,
goto_definition,
"tests/test_data/goto",
{
enum_variants: "enum_variants.txt",
inline_macros: "inline_macros.txt",
items: "items.txt",
modules: "modules.txt",
struct_members: "struct_members.txt",
variables: "variables.txt",
},
test_goto_members
test_goto_definition
);

fn caps(base: ClientCapabilities) -> ClientCapabilities {
Expand All @@ -32,21 +38,21 @@ fn caps(base: ClientCapabilities) -> ClientCapabilities {
}
}

/// Perform hover test.
///
/// This function spawns a sandbox language server with the given code in the `src/lib.cairo` file.
/// The Cairo source code is expected to contain caret markers.
/// The function then requests goto definition information at each caret position and compares
/// the result with the expected hover information from the snapshot file.
fn test_goto_members(
fn test_goto_definition(
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(),
"cairo_project.toml" => indoc! {r#"
[crate_roots]
hello = "src"

[config.global]
edition = "2024_07"
"#},
"src/lib.cairo" => cairo.clone(),
}
client_capabilities = caps;
Expand All @@ -68,17 +74,26 @@ fn test_goto_members(
work_done_progress_params: Default::default(),
partial_result_params: Default::default(),
};
let goto_definition_response =
let response =
ls.send_request::<lsp_request!("textDocument/definition")>(code_action_params);

if let Some(goto_definition_response) = goto_definition_response {
if let GotoDefinitionResponse::Scalar(location) = goto_definition_response {
match response {
Some(GotoDefinitionResponse::Scalar(location)) => {
report.push_str("---\n");
report.push_str(&peek_selection(&cairo, &location.range));
} else {
panic!("Unexpected GotoDefinitionResponse variant.")
}
} else {
panic!("Goto definition request failed.");
Some(GotoDefinitionResponse::Array(locations)) => {
for location in locations {
report.push_str("---\n");
report.push_str(&peek_selection(&cairo, &location.range));
}
}
Some(GotoDefinitionResponse::Link(_)) => {
panic!("unexpected GotoDefinitionResponse::Link");
}
None => {
report.push_str("None");
mkaput marked this conversation as resolved.
Show resolved Hide resolved
}
}
goto_definitions.insert(format!("Goto definition #{}", n), report);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
mod analysis;
mod code_actions;
mod completions;
mod goto;
mod goto_definition;
mod hover;
mod macro_expand;
mod semantic_tokens;
Expand Down
28 changes: 28 additions & 0 deletions tests/test_data/goto/enum_variants.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//! > Test goto definition of an enum variant.

//! > test_runner_name
test_goto_definition

//! > cairo_code
enum Foo {
Bar,
Baz,
}

fn main() {
let foo = Foo::Ba<caret>r;
match foo {
Foo::Ba<caret>r => {}
_ => {}
}
}

//! > Goto definition #0
let foo = Foo::Ba<caret>r;
---
<sel>Bar</sel>,

//! > Goto definition #1
Foo::Ba<caret>r => {}
---
<sel>Bar</sel>,
17 changes: 17 additions & 0 deletions tests/test_data/goto/inline_macros.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! > Test goto definition on inline macro.

//! > test_runner_name
test_goto_definition

//! > cairo_code
// FIXME(#116): This is wrong.
fn main() {
prin<caret>t!("Hello, world!");
}

//! > Goto definition #0
prin<caret>t!("Hello, world!");
---
<sel>fn main() {
print!("Hello, world!");
}</sel>
185 changes: 185 additions & 0 deletions tests/test_data/goto/items.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
//! > Test goto definition of a function.

//! > test_runner_name
test_goto_definition

//! > cairo_code
fn main() {
fo<caret>o();
}

fn foo() {} // good

mod bar {
fn foo() {} // bad
}

//! > Goto definition #0
fo<caret>o();
---
<sel>fn foo() {}</sel> // good

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

//! > Test goto definition of a struct.

//! > test_runner_name
test_goto_definition

//! > cairo_code
struct Foo {
field: felt252,
}

fn main() {
let foo = Fo<caret>o { field: 0 };
}

fn calc(foo: Fo<caret>o) {}

//! > Goto definition #0
let foo = Fo<caret>o { field: 0 };
---
<sel>struct Foo {
field: felt252,
}</sel>

//! > Goto definition #1
fn calc(foo: Fo<caret>o) {}
---
<sel>struct Foo {
field: felt252,
}</sel>

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

//! > Test goto definition of an enum.

//! > test_runner_name
test_goto_definition

//! > cairo_code
enum Foo {
Bar,
Baz,
}

fn main() {
let foo = Fo<caret>o::Bar;
}

fn calc(foo: Fo<caret>o) {}

//! > Goto definition #0
let foo = Fo<caret>o::Bar;
---
<sel>enum Foo {
Bar,
Baz,
}</sel>

//! > Goto definition #1
fn calc(foo: Fo<caret>o) {}
---
<sel>enum Foo {
Bar,
Baz,
}</sel>

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

//! > Test goto definition with traits.

//! > test_runner_name
test_goto_definition

//! > cairo_code
pub trait ShapeGeometry<T> {
fn boundary(self: T) -> u64;
fn area(self: T) -> u64;
}

mod rectangle {
use super::Sha<caret>peGeometry;

#[derive(Copy, Drop)]
pub struct Rectangle {
pub height: u64,
pub width: u64,
}

impl RectangleGeometry of ShapeGe<caret>ometry<Recta<caret>ngle> {
fn boun<caret>dary(self: Recta<caret>ngle) -> u64 {
2 * (self.height + self.width)
}
fn area(self: Rectangle) -> u64 {
self.height * self.width
}
}
}

use rectangle::Rectangle;

fn main() {
let rect = Rectangle { height: 5, width: 7 };
let area = ShapeGeo<caret>metry::ar<caret>ea(rect);
}

//! > Goto definition #0
use super::Sha<caret>peGeometry;
---
<sel>pub trait ShapeGeometry<T> {
fn boundary(self: T) -> u64;
fn area(self: T) -> u64;
}</sel>

//! > Goto definition #1
impl RectangleGeometry of ShapeGe<caret>ometry<Rectangle> {
---
<sel>pub trait ShapeGeometry<T> {
fn boundary(self: T) -> u64;
fn area(self: T) -> u64;
}</sel>

//! > Goto definition #2
impl RectangleGeometry of ShapeGeometry<Recta<caret>ngle> {
---
<sel>#[derive(Copy, Drop)]
pub struct Rectangle {
pub height: u64,
pub width: u64,
}</sel>

//! > Goto definition #3
fn boun<caret>dary(self: Rectangle) -> u64 {
---
<sel>impl RectangleGeometry of ShapeGeometry<Rectangle> {
fn boundary(self: Rectangle) -> u64 {
2 * (self.height + self.width)
}
fn area(self: Rectangle) -> u64 {
self.height * self.width
}
}</sel>
mkaput marked this conversation as resolved.
Show resolved Hide resolved

//! > Goto definition #4
fn boundary(self: Recta<caret>ngle) -> u64 {
---
<sel>#[derive(Copy, Drop)]
pub struct Rectangle {
pub height: u64,
pub width: u64,
}</sel>

//! > Goto definition #5
let area = ShapeGeo<caret>metry::area(rect);
---
<sel>pub trait ShapeGeometry<T> {
fn boundary(self: T) -> u64;
fn area(self: T) -> u64;
}</sel>

//! > Goto definition #6
let area = ShapeGeometry::ar<caret>ea(rect);
---
<sel>fn area(self: T) -> u64;</sel>
64 changes: 64 additions & 0 deletions tests/test_data/goto/modules.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//! > Test goto definition of a module.

//! > test_runner_name
test_goto_definition

//! > cairo_code
fn main() {
modu<caret>le::ba<caret>r::foo();
}

mod module {
// good
mod module {
// bad
}

mod bar { // good
fn foo() {}
}
}

//! > Goto definition #0
modu<caret>le::bar::foo();
---
mod module <sel>{
// good
mod module {
// bad
}

mod bar { // good
fn foo() {}
}
}</sel>

//! > Goto definition #1
module::ba<caret>r::foo();
---
mod bar <sel>{ // good
fn foo() {}
}</sel>

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

//! > Test goto definition of a function in a submodule.

//! > test_runner_name
test_goto_definition

//! > cairo_code
fn main() {
module::fo<caret>o();
}

fn foo() {} // bad

mod module {
fn foo() {} // good
}

//! > Goto definition #0
module::fo<caret>o();
---
<sel>fn foo() {}</sel> // good
Loading
Loading