Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit 08bc811

Browse files
author
Hendrik van Antwerpen
committed
Add defines and refers assertions
1 parent 144d64c commit 08bc811

File tree

4 files changed

+423
-65
lines changed

4 files changed

+423
-65
lines changed

stack-graphs/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## Unreleased
9+
10+
### Added
11+
12+
- New `Defines` and `Refers` assertions test for the presence of definitions and references, respectively, without resolution.
13+
14+
### Changed
15+
16+
- The `IncorrectDefinitions` error is renamed to `IncorrectlyDefined`, and `IncorrectDefinitions` is the error used for the `Defines` assertion.
17+
818
## v0.10.2 -- 2023-01-10
919

1020
### Changed

stack-graphs/src/assert.rs

Lines changed: 103 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::arena::Handle;
1414
use crate::graph::File;
1515
use crate::graph::Node;
1616
use crate::graph::StackGraph;
17+
use crate::graph::Symbol;
1718
use crate::paths::Path;
1819
use crate::paths::Paths;
1920
use crate::CancellationError;
@@ -26,6 +27,14 @@ pub enum Assertion {
2627
source: AssertionSource,
2728
targets: Vec<AssertionTarget>,
2829
},
30+
Defines {
31+
source: AssertionSource,
32+
symbols: Vec<Handle<Symbol>>,
33+
},
34+
Refers {
35+
source: AssertionSource,
36+
symbols: Vec<Handle<Symbol>>,
37+
},
2938
}
3039

3140
/// Source position of an assertion
@@ -36,7 +45,20 @@ pub struct AssertionSource {
3645
}
3746

3847
impl AssertionSource {
39-
fn reference_iter<'a>(
48+
fn definitions_iter<'a>(
49+
&'a self,
50+
graph: &'a StackGraph,
51+
) -> impl Iterator<Item = Handle<Node>> + 'a {
52+
graph.nodes_for_file(self.file).filter(move |n| {
53+
graph[*n].is_definition()
54+
&& graph
55+
.source_info(*n)
56+
.map(|s| s.span.contains(&self.position))
57+
.unwrap_or(false)
58+
})
59+
}
60+
61+
fn references_iter<'a>(
4062
&'a self,
4163
graph: &'a StackGraph,
4264
) -> impl Iterator<Item = Handle<Node>> + 'a {
@@ -74,12 +96,22 @@ pub enum AssertionError {
7496
NoReferences {
7597
source: AssertionSource,
7698
},
77-
IncorrectDefinitions {
99+
IncorrectlyDefined {
78100
source: AssertionSource,
79101
references: Vec<Handle<Node>>,
80102
missing_targets: Vec<AssertionTarget>,
81103
unexpected_paths: Vec<Path>,
82104
},
105+
IncorrectDefinitions {
106+
source: AssertionSource,
107+
missing_symbols: Vec<Handle<Symbol>>,
108+
unexpected_symbols: Vec<Handle<Symbol>>,
109+
},
110+
IncorrectReferences {
111+
source: AssertionSource,
112+
missing_symbols: Vec<Handle<Symbol>>,
113+
unexpected_symbols: Vec<Handle<Symbol>>,
114+
},
83115
Cancelled(CancellationError),
84116
}
85117

@@ -98,9 +130,11 @@ impl Assertion {
98130
cancellation_flag: &dyn CancellationFlag,
99131
) -> Result<(), AssertionError> {
100132
match self {
101-
Assertion::Defined { source, targets } => {
133+
Self::Defined { source, targets } => {
102134
self.run_defined(graph, paths, source, targets, cancellation_flag)
103135
}
136+
Self::Defines { source, symbols } => self.run_defines(graph, source, symbols),
137+
Self::Refers { source, symbols } => self.run_refers(graph, source, symbols),
104138
}
105139
}
106140

@@ -112,7 +146,7 @@ impl Assertion {
112146
expected_targets: &Vec<AssertionTarget>,
113147
cancellation_flag: &dyn CancellationFlag,
114148
) -> Result<(), AssertionError> {
115-
let references = source.reference_iter(graph).collect::<Vec<_>>();
149+
let references = source.references_iter(graph).collect::<Vec<_>>();
116150
if references.is_empty() {
117151
return Err(AssertionError::NoReferences {
118152
source: source.clone(),
@@ -146,7 +180,7 @@ impl Assertion {
146180
.cloned()
147181
.collect::<Vec<_>>();
148182
if !missing_targets.is_empty() || !unexpected_paths.is_empty() {
149-
return Err(AssertionError::IncorrectDefinitions {
183+
return Err(AssertionError::IncorrectlyDefined {
150184
source: source.clone(),
151185
references,
152186
missing_targets,
@@ -156,4 +190,68 @@ impl Assertion {
156190

157191
Ok(())
158192
}
193+
194+
fn run_defines(
195+
&self,
196+
graph: &StackGraph,
197+
source: &AssertionSource,
198+
expected_symbols: &Vec<Handle<Symbol>>,
199+
) -> Result<(), AssertionError> {
200+
let actual_symbols = source
201+
.definitions_iter(graph)
202+
.filter_map(|d| graph[d].symbol())
203+
.collect::<Vec<_>>();
204+
let missing_symbols = expected_symbols
205+
.iter()
206+
.filter(|x| !actual_symbols.contains(*x))
207+
.cloned()
208+
.unique()
209+
.collect::<Vec<_>>();
210+
let unexpected_symbols = actual_symbols
211+
.iter()
212+
.filter(|x| !expected_symbols.contains(*x))
213+
.cloned()
214+
.unique()
215+
.collect::<Vec<_>>();
216+
if !missing_symbols.is_empty() || !unexpected_symbols.is_empty() {
217+
return Err(AssertionError::IncorrectDefinitions {
218+
source: source.clone(),
219+
missing_symbols,
220+
unexpected_symbols,
221+
});
222+
}
223+
Ok(())
224+
}
225+
226+
fn run_refers(
227+
&self,
228+
graph: &StackGraph,
229+
source: &AssertionSource,
230+
expected_symbols: &Vec<Handle<Symbol>>,
231+
) -> Result<(), AssertionError> {
232+
let actual_symbols = source
233+
.references_iter(graph)
234+
.filter_map(|d| graph[d].symbol())
235+
.collect::<Vec<_>>();
236+
let missing_symbols = expected_symbols
237+
.iter()
238+
.filter(|x| !actual_symbols.contains(*x))
239+
.cloned()
240+
.unique()
241+
.collect::<Vec<_>>();
242+
let unexpected_symbols = actual_symbols
243+
.iter()
244+
.filter(|x| !expected_symbols.contains(*x))
245+
.cloned()
246+
.unique()
247+
.collect::<Vec<_>>();
248+
if !missing_symbols.is_empty() || !unexpected_symbols.is_empty() {
249+
return Err(AssertionError::IncorrectReferences {
250+
source: source.clone(),
251+
missing_symbols,
252+
unexpected_symbols,
253+
});
254+
}
255+
Ok(())
256+
}
159257
}

0 commit comments

Comments
 (0)