Skip to content

Commit

Permalink
Use split_multi_file for bindings_output tests and use the SolidityPa…
Browse files Browse the repository at this point in the history
…thResolver
  • Loading branch information
ggiraldez committed Jul 17, 2024
1 parent e751082 commit 6c75d4d
Show file tree
Hide file tree
Showing 25 changed files with 146 additions and 93 deletions.
4 changes: 2 additions & 2 deletions crates/metaslang/bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ pub struct Handle<'a, KT: KindTypes + 'static> {
handle: GraphHandle,
}

impl<KT: KindTypes + 'static> Handle<'_, KT> {
impl<'a, KT: KindTypes + 'static> Handle<'a, KT> {
pub fn is_definition(&self) -> bool {
self.owner.stack_graph[self.handle].is_definition()
}
Expand All @@ -137,7 +137,7 @@ impl<KT: KindTypes + 'static> Handle<'_, KT> {
self.owner.cursors.get(&self.handle).cloned()
}

pub fn get_file(&self) -> Option<&str> {
pub fn get_file(&self) -> Option<&'a str> {
self.owner.stack_graph[self.handle]
.file()
.map(|file| self.owner.stack_graph[file].name())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use std::fs;
use std::sync::Arc;

use anyhow::Result;
use infra_utils::cargo::CargoWorkspace;
use semver::Version;
use slang_solidity::bindings;
use slang_solidity::language::Language;
use slang_solidity::resolver::SolidityPathResolver;

use super::generated::VERSION_BREAKS;
use crate::bindings_assertions::assertions::{
Expand All @@ -28,7 +30,8 @@ pub fn run(group_name: &str, test_name: &str) -> Result<()> {

fn check_assertions_with_version(version: &Version, contents: &str) -> Result<()> {
let language = Language::new(version.clone())?;
let mut bindings = bindings::create(version.clone());
let mut bindings =
bindings::create_with_resolver(version.clone(), Arc::new(SolidityPathResolver {}));
let mut assertions = Assertions::new();

let parts = split_multi_file(contents);
Expand Down
164 changes: 100 additions & 64 deletions crates/solidity/outputs/cargo/tests/src/bindings_output/runner.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::fmt;
use std::ops::Range;
use std::path::Path;
use std::sync::Arc;

use anyhow::Result;
use ariadne::{Color, Config, Label, Report, ReportBuilder, ReportKind, Source};
use ariadne::{Color, Config, FnCache, Label, Report, ReportBuilder, ReportKind, Source};
use infra_utils::cargo::CargoWorkspace;
use infra_utils::codegen::CodegenFileSystem;
use infra_utils::github::GitHub;
Expand All @@ -19,8 +18,10 @@ use slang_solidity::bindings::{self, Handle};
use slang_solidity::cst::KindTypes;
use slang_solidity::language::Language;
use slang_solidity::parse_output::ParseOutput;
use slang_solidity::resolver::SolidityPathResolver;

use super::generated::VERSION_BREAKS;
use crate::multi_part_file::split_multi_file;

pub fn run(group_name: &str, test_name: &str) -> Result<()> {
let test_dir = CargoWorkspace::locate_source_crate("solidity_testing_snapshots")?
Expand All @@ -31,21 +32,18 @@ pub fn run(group_name: &str, test_name: &str) -> Result<()> {
let mut fs = CodegenFileSystem::new(&test_dir)?;

let input_path = test_dir.join("input.sol");

let source = input_path.read_to_string()?;

let mut last_graph_output = None;
let mut last_bindings_output = None;

for version in &VERSION_BREAKS {
let language = Language::new(version.clone())?;

let parse_output = language.parse(Language::ROOT_KIND, &source);

if !GitHub::is_running_in_ci() {
// Don't run this in CI, since the graph outputs are not committed
// to the repository and hence we cannot verify their contents,
// which is what `fs.write_file` does in CI.
let language = Language::new(version.clone())?;
let parse_output = language.parse(Language::ROOT_KIND, &source);
let graph_output = output_graph(version, &parse_output)?;
match last_graph_output {
Some(ref last) if last == &graph_output => (),
Expand All @@ -58,7 +56,7 @@ pub fn run(group_name: &str, test_name: &str) -> Result<()> {
};
}

let bindings_output = output_bindings(version, &parse_output, &source, &input_path)?;
let bindings_output = output_bindings(version, &source)?;
match last_bindings_output {
Some(ref last) if last == &bindings_output => (),
_ => {
Expand Down Expand Up @@ -158,76 +156,114 @@ fn print_graph_as_mermaid(graph: &Graph<KindTypes>) -> impl fmt::Display + '_ {
DisplayGraph(graph)
}

fn output_bindings(
version: &Version,
parse_output: &ParseOutput,
source: &str,
source_path: &Path,
) -> Result<String> {
let mut bindings = bindings::create(version.clone());
bindings.add_file(
source_path.to_str().unwrap(),
parse_output.create_tree_cursor(),
);

let source_id = source_path.strip_repo_root()?.unwrap_str();
let mut builder: ReportBuilder<'_, (&str, Range<usize>)> = Report::build(
ReportKind::Custom("References and definitions", Color::Unset),
source_id,
0,
)
.with_config(Config::default().with_color(false));
struct ParsedPart<'a> {
source_path: &'a str,
source_contents: &'a str,
parse_output: ParseOutput,
}

if !parse_output.is_valid() {
builder = builder.with_note("WARNING: Parsing failed. Results may be incomplete.");
fn output_bindings(version: &Version, contents: &str) -> Result<String> {
let language = Language::new(version.clone())?;
let mut bindings =
bindings::create_with_resolver(version.clone(), Arc::new(SolidityPathResolver {}));
let mut parsed_parts: Vec<ParsedPart<'_>> = Vec::new();

let parts = split_multi_file(contents);
for (part_path, part_source) in &parts {
let parsed_part = language.parse(Language::ROOT_KIND, part_source);
bindings.add_file(part_path, parsed_part.create_tree_cursor());
parsed_parts.push(ParsedPart {
source_path: part_path,
source_contents: part_source,
parse_output: parsed_part,
});
}

let mut definitions: Vec<Handle<'_>> = Vec::new();
let mut buffer = Vec::new();

let mut definitions: Vec<Handle<'_>> = Vec::new();
for definition in bindings.all_definitions() {
let Some(cursor) = definition.get_cursor() else {
continue;
if definition.get_cursor().is_some() {
definitions.push(definition);
};
}

let range = {
let range = cursor.text_range();
let start = source[..range.start.utf8].chars().count();
let end = source[..range.end.utf8].chars().count();
start..end
};
for part in &parsed_parts {
let mut builder: ReportBuilder<'_, (&str, Range<usize>)> = Report::build(
ReportKind::Custom("References and definitions", Color::Unset),
part.source_path,
0,
)
.with_config(Config::default().with_color(false));

definitions.push(definition);
let message = format!("def: {}", definitions.len());
builder = builder.with_label(Label::new((source_id, range)).with_message(message));
}
if !part.parse_output.is_valid() {
builder = builder.with_note("WARNING: Parsing failed. Results may be incomplete.");
}

for reference in bindings.all_references() {
let Some(cursor) = reference.get_cursor() else {
continue;
};
for (index, definition) in definitions.iter().enumerate() {
let Some(cursor) = definition.get_cursor() else {
continue;
};
let def_file = definition
.get_file()
.expect("definition should be in a file");
if def_file != part.source_path {
continue;
}

let range = {
let range = cursor.text_range();
let start = source[..range.start.utf8].chars().count();
let end = source[..range.end.utf8].chars().count();
start..end
};
let range = {
let range = cursor.text_range();
let start = contents[..range.start.utf8].chars().count();
let end = contents[..range.end.utf8].chars().count();
start..end
};

let message = format!("def: {}", index + 1);
builder =
builder.with_label(Label::new((part.source_path, range)).with_message(message));
}

let definition = reference.jump_to_definition();
let message = match definition {
None => "unresolved".to_string(),
Some(definition) => {
let def_id = definitions.iter().position(|d| *d == definition).unwrap();
format!("ref: {}", def_id + 1)
for reference in bindings.all_references() {
let Some(cursor) = reference.get_cursor() else {
continue;
};
let ref_file = reference.get_file().expect("reference should be in a file");
if ref_file != part.source_path {
continue;
}
};

builder = builder.with_label(Label::new((source_id, range)).with_message(message));
}
let range = {
let range = cursor.text_range();
let start = contents[..range.start.utf8].chars().count();
let end = contents[..range.end.utf8].chars().count();
start..end
};

let report = builder.finish();
let mut buffer = Vec::new();
report.write((source_id, Source::from(source)), &mut buffer)?;
let definition = reference.jump_to_definition();
let message = match definition {
None => "unresolved".to_string(),
Some(definition) => {
let def_id = definitions.iter().position(|d| *d == definition).unwrap();
format!("ref: {}", def_id + 1)
}
};

builder =
builder.with_label(Label::new((part.source_path, range)).with_message(message));
}

let report = builder.finish();
let file_cache = FnCache::new(
(move |id| Err(Box::new(format!("Failed to fetch source '{id}'")) as _)) as fn(&_) -> _,
)
.with_sources(
parsed_parts
.iter()
.map(|part| (part.source_path, Source::from(part.source_contents)))
.collect(),
);
report.write(file_cache, &mut buffer)?;
}

let result = String::from_utf8(buffer)?;
Ok(result)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/enums/decls/input.sol:1:1]
╭─[input.sol:1:1]
1 │ contract Test {
│ ──┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/enums/decls/input.sol:1:1]
╭─[input.sol:1:1]
1 │ contract Test {
│ ──┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/enums/in_params/input.sol:1:1]
╭─[input.sol:1:1]
1 │ contract Test {
│ ──┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/enums/in_state_vars/input.sol:1:1]
╭─[input.sol:1:1]
1 │ contract Foo {
│ ─┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/enums/sample/input.sol:1:1]
╭─[input.sol:1:1]
4 │ contract Test {
│ ──┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/enums/sample/input.sol:1:1]
╭─[input.sol:1:1]
4 │ contract Test {
│ ──┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/enums/sample/input.sol:1:1]
╭─[input.sol:1:1]
4 │ contract Test {
│ ──┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/expressions/funcalls/input.sol:1:1]
╭─[input.sol:1:1]
1 │ contract Test {
│ ──┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/expressions/funcalls_named_args/input.sol:1:1]
╭─[input.sol:1:1]
1 │ contract Test {
│ ──┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/expressions/type_expr/input.sol:1:1]
╭─[input.sol:1:1]
1 │ contract Test {
│ ──┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/expressions/type_expr/input.sol:1:1]
╭─[input.sol:1:1]
1 │ contract Test {
│ ──┬─
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

References and definitions:
╭─[crates/solidity/testing/snapshots/bindings_output/imports/alias_import/input.sol:1:1]
╭─[main.sol:1:1]
1 │ import "./other.sol" as other;
2 │ import "./other.sol" as other;
│ ──┬──
│ ╰──── def: 1
│ Note: WARNING: Parsing failed. Results may be incomplete.
───╯
References and definitions:
Loading

0 comments on commit 6c75d4d

Please sign in to comment.