Skip to content

Commit

Permalink
Split bindings Handle into separate Definition and Reference
Browse files Browse the repository at this point in the history
  • Loading branch information
ggiraldez committed Jul 31, 2024
1 parent b2bbf9a commit 2e7fce6
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 54 deletions.
3 changes: 2 additions & 1 deletion crates/codegen/runtime/cargo/src/runtime/bindings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use semver::Version;
use crate::cst::KindTypes;

pub type Bindings = metaslang_bindings::Bindings<KindTypes>;
pub type Handle<'a> = metaslang_bindings::Handle<'a, KindTypes>;
pub type Definition<'a> = metaslang_bindings::Definition<'a, KindTypes>;
pub type Reference<'a> = metaslang_bindings::Reference<'a, KindTypes>;

pub fn create(version: Version) -> Bindings {
create_with_resolver(version, Arc::new(DefaultPathResolver {}))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::fmt;
use semver::Version;

use super::CommandError;
use crate::bindings::{self, Bindings, Handle};
use crate::bindings::{self, Bindings, Definition, Reference};
use crate::cursor::Cursor;

pub fn execute(file_path_string: &str, version: Version) -> Result<(), CommandError> {
Expand Down Expand Up @@ -49,7 +49,7 @@ impl<'a> fmt::Display for DisplayRange<'a> {
}
}

struct DisplayDefinition<'a>(&'a Handle<'a>);
struct DisplayDefinition<'a>(&'a Definition<'a>);

impl<'a> fmt::Display for DisplayDefinition<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -68,7 +68,7 @@ impl<'a> fmt::Display for DisplayDefinition<'a> {
}
}

struct DisplayReference<'a>(&'a Handle<'a>);
struct DisplayReference<'a>(&'a Reference<'a>);

impl<'a> fmt::Display for DisplayReference<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down
77 changes: 54 additions & 23 deletions crates/metaslang/bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,55 +91,90 @@ impl<KT: KindTypes + 'static> Bindings<KT> {
builder
}

pub fn all_definitions(&self) -> impl Iterator<Item = Handle<'_, KT>> + '_ {
pub fn all_definitions(&self) -> impl Iterator<Item = Definition<'_, KT>> + '_ {
self.stack_graph
.iter_nodes()
.filter(|handle| self.stack_graph[*handle].is_definition())
.map(|handle| Handle {
.map(|handle| Definition {
owner: self,
handle,
})
}

pub fn all_references(&self) -> impl Iterator<Item = Handle<'_, KT>> + '_ {
pub fn all_references(&self) -> impl Iterator<Item = Reference<'_, KT>> + '_ {
self.stack_graph
.iter_nodes()
.filter(|handle| self.stack_graph[*handle].is_reference())
.map(|handle| Handle {
.map(|handle| Reference {
owner: self,
handle,
})
}

pub fn cursor_to_handles(&self, cursor: &Cursor<KT>) -> Vec<Handle<'_, KT>> {
let mut handles = Vec::new();
pub fn definition_at(&self, cursor: &Cursor<KT>) -> Option<Definition<'_, KT>> {
for (handle, handle_cursor) in &self.cursors {
if handle_cursor == cursor {
handles.push(Handle {
if handle_cursor == cursor && self.stack_graph[*handle].is_definition() {
return Some(Definition {
owner: self,
handle: *handle,
});
}
}
handles
None
}

pub fn reference_at(&self, cursor: &Cursor<KT>) -> Option<Reference<'_, KT>> {
for (handle, handle_cursor) in &self.cursors {
if handle_cursor == cursor && self.stack_graph[*handle].is_reference() {
return Some(Reference {
owner: self,
handle: *handle,
});
}
}
None
}
}

#[derive(Clone)]
pub struct Handle<'a, KT: KindTypes + 'static> {
pub struct Definition<'a, KT: KindTypes + 'static> {
owner: &'a Bindings<KT>,
handle: GraphHandle,
}

impl<'a, KT: KindTypes + 'static> Handle<'a, KT> {
pub fn is_definition(&self) -> bool {
self.owner.stack_graph[self.handle].is_definition()
impl<'a, KT: KindTypes + 'static> Definition<'a, KT> {
pub fn get_cursor(&self) -> Option<Cursor<KT>> {
self.owner.cursors.get(&self.handle).cloned()
}

pub fn get_file(&self) -> Option<&'a str> {
self.owner.stack_graph[self.handle]
.file()
.map(|file| self.owner.stack_graph[file].name())
}
}

impl<KT: KindTypes + 'static> Debug for Definition<'_, KT> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("BindingsHandle").field(&self.handle).finish()
}
}

pub fn is_reference(&self) -> bool {
self.owner.stack_graph[self.handle].is_reference()
impl<KT: KindTypes + 'static> PartialEq for Definition<'_, KT> {
fn eq(&self, other: &Self) -> bool {
let our_owner: *const Bindings<KT> = self.owner;
let other_owner: *const Bindings<KT> = other.owner;
our_owner == other_owner && self.handle == other.handle
}
}

#[derive(Clone)]
pub struct Reference<'a, KT: KindTypes + 'static> {
owner: &'a Bindings<KT>,
handle: GraphHandle,
}

impl<'a, KT: KindTypes + 'static> Reference<'a, KT> {
pub fn get_cursor(&self) -> Option<Cursor<KT>> {
self.owner.cursors.get(&self.handle).cloned()
}
Expand All @@ -150,11 +185,7 @@ impl<'a, KT: KindTypes + 'static> Handle<'a, KT> {
.map(|file| self.owner.stack_graph[file].name())
}

pub fn jump_to_definition(&self) -> Option<Self> {
if !self.is_reference() {
return None;
}

pub fn jump_to_definition(&self) -> Option<Definition<'a, KT>> {
let mut partials = PartialPaths::new();
let mut reference_paths = Vec::new();
ForwardPartialPathStitcher::find_all_complete_partial_paths(
Expand Down Expand Up @@ -184,20 +215,20 @@ impl<'a, KT: KindTypes + 'static> Handle<'a, KT> {
);
results.sort_by(|a, b| b.edges.len().cmp(&a.edges.len()));
}
results.first().map(|path| Handle {
results.first().map(|path| Definition {
owner: self.owner,
handle: path.end_node(),
})
}
}

impl<KT: KindTypes + 'static> Debug for Handle<'_, KT> {
impl<KT: KindTypes + 'static> Debug for Reference<'_, KT> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("BindingsHandle").field(&self.handle).finish()
}
}

impl<KT: KindTypes + 'static> PartialEq for Handle<'_, KT> {
impl<KT: KindTypes + 'static> PartialEq for Reference<'_, KT> {
fn eq(&self, other: &Self) -> bool {
let our_owner: *const Bindings<KT> = self.owner;
let other_owner: *const Bindings<KT> = other.owner;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::collections::HashMap;
use once_cell::sync::Lazy;
use regex::Regex;
use semver::{Version, VersionReq};
use slang_solidity::bindings::{Bindings, Handle};
use slang_solidity::bindings::{Bindings, Definition};
use slang_solidity::cursor::Cursor;
use slang_solidity::query::Query;
use thiserror::Error;
Expand Down Expand Up @@ -339,18 +339,14 @@ fn check_definitions<'a>(
fn find_definition<'a>(
bindings: &'a Bindings,
assertion: &DefinitionAssertion<'_>,
) -> Result<Handle<'a>, String> {
) -> Result<Definition<'a>, String> {
let DefinitionAssertion { cursor, .. } = assertion;

let handles = bindings.cursor_to_handles(cursor);
if handles.is_empty() {
let Some(definition) = bindings.definition_at(cursor) else {
return Err(format!("{assertion} failed: not found"));
}
let Some(handle) = handles.into_iter().find(|h| h.is_definition()) else {
return Err(format!("{assertion} failed: not a definition"));
};

Ok(handle)
Ok(definition)
}

fn check_references<'a>(
Expand Down Expand Up @@ -438,25 +434,21 @@ fn check_reference_assertion(
fn find_and_resolve_reference<'a>(
bindings: &'a Bindings,
assertion: &ReferenceAssertion<'_>,
) -> Result<Option<Handle<'a>>, String> {
) -> Result<Option<Definition<'a>>, String> {
let ReferenceAssertion { cursor, .. } = assertion;

let handles = bindings.cursor_to_handles(cursor);
if handles.is_empty() {
let Some(reference) = bindings.reference_at(cursor) else {
return Err(format!("{assertion} failed: not found"));
}

let Some(handle) = handles.iter().find(|h| h.is_reference()) else {
return Err(format!("{assertion} failed: not a reference"));
};
Ok(handle.jump_to_definition())

Ok(reference.jump_to_definition())
}

fn lookup_referenced_definition<'a>(
bindings: &'a Bindings,
definitions: &HashMap<String, DefinitionAssertion<'_>>,
assertion: &ReferenceAssertion<'_>,
) -> Result<Handle<'a>, String> {
) -> Result<Definition<'a>, String> {
let ReferenceAssertion { id, .. } = assertion;
let Some(id) = id else {
return Err(format!("{assertion} failed: should not attempt to resolve"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::ops::Range;

use anyhow::Result;
use ariadne::{Color, Config, FnCache, Label, Report, ReportBuilder, ReportKind, Source};
use slang_solidity::bindings::{Bindings, Handle};
use slang_solidity::bindings::{Bindings, Definition};
use slang_solidity::diagnostic;

use super::runner::ParsedPart;
Expand All @@ -13,7 +13,7 @@ pub(crate) fn render_bindings(
) -> Result<String> {
let mut buffer: Vec<u8> = Vec::new();

let mut definitions: Vec<Handle<'_>> = Vec::new();
let mut definitions: Vec<Definition<'_>> = Vec::new();
for definition in bindings.all_definitions() {
if definition.get_cursor().is_some() {
definitions.push(definition);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2e7fce6

Please sign in to comment.