Skip to content

Commit

Permalink
add an error message if some messages are lopsided
Browse files Browse the repository at this point in the history
If a message type is never sent or never received,
this leads to From<$ty> implementations being missing.

The implementation here adds a check and throws and error
pointint to the messages.

Closes #13
  • Loading branch information
drahnr committed Dec 8, 2022
1 parent 6e8c9d0 commit 06b1f43
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 7 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions orchestra/proc-macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"]
proc-macro = true

[dependencies]
syn = { version = "1.0.95", features = ["full", "extra-traits"] }
syn = { version = "1.0.105", features = ["full", "extra-traits"] }
quote = "1.0.20"
proc-macro2 = "1.0.43"
proc-macro2 = { version = "1.0.47", features = ["span-locations"] }
proc-macro-crate = "1.1.3"
expander = { version = "0.0.6", default-features = false }
petgraph = "0.6.0"
Expand Down
51 changes: 50 additions & 1 deletion orchestra/proc-macro/src/impl_message_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;

use itertools::Itertools;
use quote::quote;
use syn::{spanned::Spanned, Result};

Expand Down Expand Up @@ -50,7 +53,7 @@ pub(crate) fn impl_message_wrapper_enum(info: &OrchestraInfo) -> Result<proc_mac
(TokenStream::new(), TokenStream::new())
};

let ts = quote! {
let mut ts = quote! {
/// Generated message type wrapper over all possible messages
/// used by any subsystem.
#[allow(missing_docs)]
Expand Down Expand Up @@ -81,5 +84,51 @@ pub(crate) fn impl_message_wrapper_enum(info: &OrchestraInfo) -> Result<proc_mac
#outgoing_from_impl
};

// TODO it's not perfect, if the same type is used with different paths
// the detection will fail
let outgoing = HashSet::<&Path>::from_iter(
info.subsystems().iter().map(|ssf| ssf.messages_to_send.iter()).flatten(),
);
let incoming =
HashSet::<&Path>::from_iter(info.subsystems().iter().map(|ssf| &ssf.message_to_consume));

// Try to maintain the ordering according to the span start in the declaration.
fn cmp<'p, 'q>(a: &'p &&Path, b: &'q &&Path) -> std::cmp::Ordering {
a.span()
.start()
.partial_cmp(&b.span().start())
.unwrap_or(std::cmp::Ordering::Equal)
}

// sent but not received
for sbnr in outgoing.difference(&incoming).sorted_by(cmp) {
ts.extend(
syn::Error::new(
sbnr.span(),
format!(
"Message {} is sent but never received",
sbnr.get_ident()
.expect("Message is a path that must end in an identifier. qed")
),
)
.to_compile_error(),
);
}

// received but not sent
for rbns in incoming.difference(&outgoing).sorted_by(cmp) {
ts.extend(
syn::Error::new(
rbns.span(),
format!(
"Message {} is received but never sent",
rbns.get_ident()
.expect("Message is a path that must end in an identifier. qed")
),
)
.to_compile_error(),
);
}

Ok(ts)
}

0 comments on commit 06b1f43

Please sign in to comment.