tamer: asg::air: Merge Pkg closing span
The `Pkg` span will now properly reflect the entire definition of the package including the opening and closing tags. This was found while I was working on a graph traversal. DEV-13597main
parent
39e98210be
commit
4afc8c22e6
|
@ -501,7 +501,10 @@ impl ParseState for AirAggregate {
|
|||
.err(AsgError::NestedPkgOpen(span, oi_pkg.span()))
|
||||
}
|
||||
|
||||
(PkgDfn(_, es), PkgClose(_)) => Transition(Empty(es)).incomplete(),
|
||||
(PkgDfn(oi_pkg, es), PkgClose(span)) => {
|
||||
oi_pkg.close(asg, span);
|
||||
Transition(Empty(es)).incomplete()
|
||||
}
|
||||
|
||||
(st @ (Empty(..) | BuildingExpr(..)), PkgClose(span)) => {
|
||||
Transition(st).err(AsgError::InvalidPkgCloseContext(span))
|
||||
|
|
|
@ -263,7 +263,7 @@ fn pkg_is_rooted() {
|
|||
.expect("missing rooted package")
|
||||
.resolve(&asg);
|
||||
|
||||
assert_eq!(pkg.span(), S1);
|
||||
assert_eq!(pkg.span(), S1.merge(S2).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1075,38 +1075,48 @@ fn expr_ref_outside_of_expr_context() {
|
|||
|
||||
#[test]
|
||||
fn idents_share_defining_pkg() {
|
||||
let id_foo = SPair("foo".into(), S2);
|
||||
let id_bar = SPair("bar".into(), S4);
|
||||
let id_baz = SPair("baz".into(), S5);
|
||||
let id_foo = SPair("foo".into(), S3);
|
||||
let id_bar = SPair("bar".into(), S5);
|
||||
let id_baz = SPair("baz".into(), S6);
|
||||
|
||||
// An expression nested within another.
|
||||
let toks = vec![
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
Air::PkgOpen(S1),
|
||||
Air::ExprOpen(ExprOp::Sum, S2),
|
||||
Air::ExprIdent(id_foo),
|
||||
Air::ExprOpen(ExprOp::Sum, S3),
|
||||
Air::ExprOpen(ExprOp::Sum, S4),
|
||||
Air::ExprIdent(id_bar),
|
||||
Air::ExprRef(id_baz),
|
||||
Air::ExprClose(S6),
|
||||
Air::ExprClose(S7),
|
||||
Air::ExprClose(S8),
|
||||
Air::PkgClose(S9),
|
||||
];
|
||||
|
||||
let asg = asg_from_toks(toks);
|
||||
let mut sut = Sut::parse(toks.into_iter());
|
||||
assert!(sut.all(|x| x.is_ok()));
|
||||
let asg = sut.finalize().unwrap().into_context();
|
||||
|
||||
let oi_foo = asg.lookup(id_foo).unwrap();
|
||||
let oi_bar = asg.lookup(id_bar).unwrap();
|
||||
|
||||
assert_eq!(oi_foo.src_pkg(&asg).unwrap(), oi_bar.src_pkg(&asg).unwrap());
|
||||
|
||||
// Missing identifiers should not have a source package,
|
||||
// since we don't know what defined it yet.
|
||||
let oi_baz = asg.lookup(id_baz).unwrap();
|
||||
assert_eq!(None, oi_baz.src_pkg(&asg));
|
||||
|
||||
// Ontological sanity check:
|
||||
// edges from the package to identifiers defined by it should not be
|
||||
// considered cross edges.
|
||||
let oi_pkg = oi_foo.src_pkg(&asg).unwrap();
|
||||
assert!(oi_pkg.edges(&asg).all(|rel| !rel.is_cross_edge()));
|
||||
|
||||
// Missing identifiers should not have a source package,
|
||||
// since we don't know what defined it yet.
|
||||
let oi_baz = asg.lookup(id_baz).unwrap();
|
||||
assert_eq!(None, oi_baz.src_pkg(&asg));
|
||||
// The package span should encompass the entire definition.
|
||||
assert_eq!(
|
||||
S1.merge(S9),
|
||||
oi_foo.src_pkg(&asg).map(|pkg| pkg.resolve(&asg).span())
|
||||
)
|
||||
}
|
||||
|
||||
fn asg_from_toks<I: IntoIterator<Item = Air>>(toks: I) -> Asg
|
||||
|
|
|
@ -23,7 +23,7 @@ use super::{
|
|||
Ident, Object, ObjectIndex, ObjectRel, ObjectRelFrom, ObjectRelTy,
|
||||
ObjectRelatable,
|
||||
};
|
||||
use crate::{asg::Asg, span::Span};
|
||||
use crate::{asg::Asg, f::Functor, span::Span};
|
||||
use std::fmt::Display;
|
||||
|
||||
#[cfg(doc)]
|
||||
|
@ -50,6 +50,14 @@ impl Display for Pkg {
|
|||
}
|
||||
}
|
||||
|
||||
impl Functor<Span> for Pkg {
|
||||
fn map(self, f: impl FnOnce(Span) -> Span) -> Self::Target {
|
||||
match self {
|
||||
Self(span) => Self(f(span)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Subset of [`ObjectKind`]s that are valid targets for edges from
|
||||
/// [`Ident`].
|
||||
///
|
||||
|
@ -107,4 +115,9 @@ impl ObjectIndex<Pkg> {
|
|||
pub fn defines(self, asg: &mut Asg, oi: ObjectIndex<Ident>) -> Self {
|
||||
self.add_edge_to(asg, oi)
|
||||
}
|
||||
|
||||
/// Complete the definition of a package.
|
||||
pub fn close(self, asg: &mut Asg, span: Span) -> Self {
|
||||
self.map_obj(asg, Pkg::fmap(|open| open.merge(span).unwrap_or(open)))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue