Skip to content

Commit

Permalink
Rewrite find references tests to insta (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkaput authored Jan 21, 2025
1 parent f3b6596 commit db4158f
Show file tree
Hide file tree
Showing 19 changed files with 808 additions and 873 deletions.
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

0 comments on commit db4158f

Please sign in to comment.