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

Rewrite find references tests to insta #192

Merged
merged 1 commit into from
Jan 21, 2025
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
71 changes: 71 additions & 0 deletions tests/e2e/find_references/enums.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use crate::find_references::find_references;
use crate::support::insta::test_transform;

#[test]
fn enum_name() {
test_transform!(find_references, r#"
enum Fo<caret>o {
Bar,
Baz,
}

fn main() {
let foo = Foo::Bar;
let foobar: Foo = foo;
}

fn calc(foo: Foo) {}

mod rectangle {
use super::Foo;
}

mod trick {
struct Foo {}
}
"#, @r"
<sel=declaration>enum <sel>Foo</sel> {
Bar,
Baz,
}</sel>

fn main() {
let foo = <sel>Foo</sel>::Bar;
let foobar: <sel>Foo</sel> = foo;
}

fn calc(foo: <sel>Foo</sel>) {}

mod rectangle {
use super::<sel>Foo</sel>;
}

mod trick {
struct Foo {}
}
")
}

// FIXME(#164): Pattern should also be selected.
#[test]
fn enum_variants() {
test_transform!(find_references, r#"
enum Foo { Bar, Baz }
fn main() {
let foo = Foo::Ba<caret>r;
match foo {
Foo::Bar => {}
_ => {}
}
}
"#, @r"
enum Foo { <sel=declaration>Bar</sel>, Baz }
fn main() {
let foo = Foo::Bar;
match foo {
Foo::Bar => {}
_ => {}
}
}
")
}
52 changes: 52 additions & 0 deletions tests/e2e/find_references/fns.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use crate::find_references::find_references;
use crate::support::insta::test_transform;

// FIXME(#129): definition stable ptr for functions is wrong and causes declaration slipping here.
#[test]
fn fn_via_definition() {
test_transform!(find_references, r#"
fn pow<caret>2(x: felt252) -> felt252 { x * x }
fn main() {
let x = pow2(2) + pow2(3);
}
"#, @r"
<sel=declaration>fn <sel>pow2</sel>(x: felt252) -> felt252 { x * x }</sel>
fn main() {
let x = <sel>pow2</sel>(2) + <sel>pow2</sel>(3);
}
")
}

// FIXME(#129): definition stable ptr for functions is wrong and causes declaration slipping here.
#[test]
fn fn_via_call() {
test_transform!(find_references, r#"
fn pow2(x: felt252) -> felt252 { x * x }
fn main() {
let x = po<caret>w2(2) + pow2(3);
}
"#, @r"
<sel=declaration>fn <sel>pow2</sel>(x: felt252) -> felt252 { x * x }</sel>
fn main() {
let x = <sel>pow2</sel>(2) + <sel>pow2</sel>(3);
}
")
}

// FIXME(#164): Pattern should not match here.
#[test]
fn unused_function() {
test_transform!(find_references, r#"
fn pow<caret>2(x: felt252) -> felt252 { x * x }
fn main() {
let pow2 = 2;
let x = pow2 + pow2;
}
"#, @r"
<sel=declaration>fn <sel>pow2</sel>(x: felt252) -> felt252 { x * x }</sel>
fn main() {
let <sel>pow2</sel> = 2;
let x = pow2 + pow2;
}
")
}
24 changes: 24 additions & 0 deletions tests/e2e/find_references/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::find_references::find_references;
use crate::support::insta::test_transform;

#[test]
fn inline_macro() {
test_transform!(find_references, r#"
fn main() {
print!("Hello world!");
let arr = arr<caret>ay![1, 2, 3, 4, 5];
}
fn bar() {
let forty_two = array![42];
}
"#, @r#"
// found several references in the core crate
fn main() {
print!("Hello world!");
let arr = <sel>array</sel>![1, 2, 3, 4, 5];
}
fn bar() {
let forty_two = <sel>array</sel>![42];
}
"#)
}
151 changes: 151 additions & 0 deletions tests/e2e/find_references/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
use std::collections::HashSet;
use std::hash::{Hash, Hasher};

use itertools::Itertools;
use lsp_types::{
ClientCapabilities, Location, ReferenceClientCapabilities, ReferenceContext, ReferenceParams,
TextDocumentClientCapabilities, TextDocumentPositionParams, lsp_request,
};

use crate::support::cairo_project_toml::CAIRO_PROJECT_TOML_2024_07;
use crate::support::cursor::render_selections_with_attrs;
use crate::support::{cursors, sandbox};

mod enums;
mod fns;
mod macros;
mod structs;
mod traits;
mod vars;

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 find_references(cairo_code: &str) -> String {
let (cairo, cursors) = cursors(cairo_code);

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

ls.open_all_cairo_files_and_wait_for_project_update();

assert_eq!(cursors.carets().len(), 1);
let position = cursors.carets()[0];

let mut query = |include_declaration: bool| {
let params = ReferenceParams {
text_document_position: TextDocumentPositionParams {
text_document: ls.doc_id("src/lib.cairo"),
position,
},
context: ReferenceContext { include_declaration },
work_done_progress_params: Default::default(),
partial_result_params: Default::default(),
};
let locations = ls.send_request::<lsp_request!("textDocument/references")>(params)?;
Some(locations.into_iter().map(LocationForComparison).collect::<HashSet<_>>())
};

match (query(false), query(true)) {
(None, None) => "none response".into(),
(Some(_), None) => panic!(
"references excluding declaration returned response, but including declaration did not"
),
(None, Some(_)) => panic!(
"references including declaration returned response, but excluding declaration did not"
),
(Some(excluding_declaration), Some(including_declaration)) => {
assert!(
excluding_declaration.is_subset(&including_declaration),
"include_declarations: true should return a superset of include_declarations: \
false"
);

let mut declarations: Vec<Location> = including_declaration
.difference(&excluding_declaration)
.sorted()
.map(|l| l.0.clone())
.collect();

let mut usages = excluding_declaration
.intersection(&including_declaration)
.sorted()
.map(|l| l.0.clone())
.collect::<Vec<_>>();

let mut result = String::new();

if remove_core_references(&mut declarations) || remove_core_references(&mut usages) {
result.push_str("// found several references in the core crate\n");
}

let ranges = declarations
.into_iter()
.map(|loc| (loc.range, Some("declaration".to_owned())))
.chain(usages.into_iter().map(|loc| (loc.range, None)))
.collect::<Vec<_>>();

result += &render_selections_with_attrs(&cairo, &ranges);

result
}
}
}

fn remove_core_references(locations: &mut Vec<Location>) -> bool {
// Remove any references found in the core crate.
// We do not want to test core crate contents here, but we want to note that they
// exist.
let mut found_core_refs = false;
locations.retain(|loc| {
let path = loc.uri.path();
if path.contains("/core/src/") || path.contains("/corelib/src/") {
found_core_refs = true;
false
} else {
true
}
});
found_core_refs
}

#[derive(PartialEq, Eq)]
struct LocationForComparison(Location);

impl PartialOrd for LocationForComparison {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for LocationForComparison {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
#[expect(clippy::needless_borrowed_reference)] // Clippy asks to write erroneous code.
let key = |&Self(ref loc)| (loc.uri.as_str(), loc.range.start, loc.range.end);
key(self).cmp(&key(other))
}
}

impl Hash for LocationForComparison {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.uri.hash(state);
self.0.range.start.line.hash(state);
self.0.range.start.character.hash(state);
self.0.range.end.line.hash(state);
self.0.range.end.character.hash(state);
}
}
85 changes: 85 additions & 0 deletions tests/e2e/find_references/structs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use crate::find_references::find_references;
use crate::support::insta::test_transform;

#[test]
fn struct_by_name() {
test_transform!(find_references, r#"
#[derive(Drop)]
struct Fo<caret>o { field: felt252 }
fn main() {
let foo: Foo = Foo { field: 0 };
}
fn calc(foo: Foo) {}
mod rectangle {
use super::Foo;
}
"#, @r"
<sel=declaration>#[derive(Drop)]
struct <sel>Foo</sel> { field: felt252 }</sel>
fn main() {
let foo: <sel>Foo</sel> = <sel>Foo</sel> { field: 0 };
}
fn calc(foo: <sel>Foo</sel>) {}
mod rectangle {
use super::<sel>Foo</sel>;
}
")
}

// FIXME(#129): The results for this are very off.
#[test]
fn struct_member_via_definition() {
test_transform!(find_references, r#"
#[derive(Drop)]
struct Foo { wi<caret>dth: u64 }
fn main() {
let foo = Foo { width: 0 };
let x = foo.width * 2;
}
"#, @r"
<sel=declaration>#[derive(Drop)]
struct <sel>Foo</sel> { width: u64 }</sel>
fn main() {
let foo = <sel>Foo</sel> { width: 0 };
let x = foo.width * 2;
}
")
}

#[test]
fn struct_member_via_constructor() {
test_transform!(find_references, r#"
#[derive(Drop)]
struct Foo { width: u64 }
fn main() {
let foo = Foo { wid<caret>th: 0 };
let x = foo.width * 2;
}
"#, @r"
#[derive(Drop)]
struct Foo { <sel=declaration>width: u64</sel> }
fn main() {
let foo = Foo { <sel>width</sel>: 0 };
let x = foo.<sel>width</sel> * 2;
}
")
}

#[test]
fn struct_member_via_field_access() {
test_transform!(find_references, r#"
#[derive(Drop)]
struct Foo { width: u64 }
fn main() {
let foo = Foo { wid<caret>th: 0 };
let x = foo.width * 2;
}
"#, @r"
#[derive(Drop)]
struct Foo { <sel=declaration>width: u64</sel> }
fn main() {
let foo = Foo { <sel>width</sel>: 0 };
let x = foo.<sel>width</sel> * 2;
}
")
}
Loading
Loading