Skip to content

Commit

Permalink
support syn2
Browse files Browse the repository at this point in the history
  • Loading branch information
Artem-Romanenia committed Nov 29, 2024
1 parent 82f71ae commit 29499c4
Show file tree
Hide file tree
Showing 17 changed files with 164 additions and 34 deletions.
20 changes: 14 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,17 @@ jobs:
- uses: actions/checkout@v4
- name: Build
run: cargo build --verbose
- name: Run Doc Tests
run: cargo test --package o2o
- name: Run Integration Tests
run: cargo test --package o2o-tests
- name: Run Impl Tests
run: cargo test --package o2o-impl
- name: Run Doc Tests default
run: cargo test -q --package o2o
- name: Run Doc Tests syn1
run: cargo test -q --package o2o --no-default-features --features syn1
- name: Run Doc Tests syn2
run: cargo test -q --package o2o --no-default-features --features syn2
- name: Run Integration Tests syn1
run: cargo test -q --package o2o-tests --no-default-features --features syn1
- name: Run Integration Tests syn2
run: cargo test -q --package o2o-tests --no-default-features --features syn2
- name: Run Impl Tests syn1
run: cargo test -q --package o2o-impl --no-default-features --features syn
- name: Run Impl Tests syn2
run: cargo test -q --package o2o-impl --no-default-features --features syn2
11 changes: 6 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "o2o"
version = "0.5.0"
version = "0.5.1-beta1"
edition = "2021"
authors = ["Artem Romanenia <artem.romanenia@gmail.com>"]
categories = ["rust-patterns", "no-std", "development-tools"]
Expand All @@ -10,12 +10,13 @@ license = "MIT OR Apache-2.0"
repository = "https://github.com/Artem-Romanenia/o2o"

[dependencies]
o2o-impl = { version = "0.5.0", path = "o2o-impl", optional = true }
o2o-macros = { version = "0.5.0", path = "o2o-macros", optional = true }
o2o-impl = { version = "0.5.1-beta1", path = "o2o-impl", optional = true }
o2o-macros = { version = "0.5.1-beta1", path = "o2o-macros", default-features = false, optional = true }

[features]
default = ["macro"]
macro = ["dep:o2o-impl", "dep:o2o-macros"]
default = ["syn1"]
syn1 = ["o2o-impl/syn", "o2o-macros/syn1"]
syn2 = ["o2o-impl/syn2", "o2o-macros/syn2"]

[workspace]
members = ["o2o-impl", "o2o-macros", "o2o-tests"]
27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ And here's the code that `o2o` generates (from here on, generated code is produc

- [Traits and `o2o` *trait instructions*](#traits-and-o2o-trait-instructions)
- [Installation](#installation)
- [`syn >=2.*`](#syn-2)
- [no\_std](#no_std)
- [The (not so big) Problem](#the-not-so-big-problem)
- [Inline expressions](#inline-expressions)
Expand Down Expand Up @@ -264,11 +265,20 @@ struct EntityDto { }

## Installation

In a typical project just add this to `Cargo.toml`:
For most projects, just add this to `Cargo.toml`:

``` toml
[dependencies]
o2o = "0.4.9"
o2o = "0.5.1"
```

### `syn >=2.*`

Currently o2o uses `syn >=1.0.3, <2` by default. If you want `syn >=2.*` to be used, here's the way:

``` toml
[dependencies]
o2o = { version = "0.5.1", default-features = false, features = "syn2" }
```

### no_std
Expand All @@ -277,9 +287,18 @@ In `#![no_std]` project, add this to `Cargo.toml`:

``` toml
[dependencies]
o2o-macros = "0.4.9"
o2o-macros = "0.5.1"
# Following line can be ommited if you don't need o2o to produce o2o::traits::(Try)IntoExisting implementations
o2o = { version = "0.5.1", default-features = false }
```

Or, if you want `no_std` *and* `syn2`:

``` toml
[dependencies]
o2o-macros = { version = "0.5.1", default-features = false, features = "syn2" }
# Following line can be ommited if you don't need o2o to produce o2o::traits::(Try)IntoExisting implementations
o2o = { version = "0.4.9", default-features = false }
o2o = { version = "0.5.1", default-features = false }
```

## The (not so big) Problem
Expand Down
5 changes: 3 additions & 2 deletions o2o-impl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "o2o-impl"
version = "0.5.0"
version = "0.5.1-beta1"
edition = "2021"
authors = ["Artem Romanenia <artem.romanenia@gmail.com>"]
description = "Implementation of 'o2o' crate"
Expand All @@ -9,7 +9,8 @@ repository = "https://github.com/Artem-Romanenia/o2o"

[dependencies]
proc-macro2 = "1.0.0"
syn = "1.0.3"
syn = { package = "syn", version = "1.0.3", optional = true }
syn2 = { package = "syn", version = "2.0.0", optional = true }
quote = "1.0.0"

[dev-dependencies]
Expand Down
4 changes: 4 additions & 0 deletions o2o-impl/benches/o2o_benchmarks.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use o2o_impl::expand::derive;
use quote::quote;

#[cfg(feature = "syn2")]
use syn2 as syn;

use syn::DeriveInput;

fn derive_simple_benchmark(c: &mut Criterion) {
Expand Down
4 changes: 4 additions & 0 deletions o2o-impl/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ use crate::attr::{self};
use crate::attr::{DataTypeAttrs, MemberAttrs};
use proc_macro2::Span;
use quote::ToTokens;

#[cfg(feature = "syn2")]
use syn2 as syn;

use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::token::Comma;
Expand Down
69 changes: 59 additions & 10 deletions o2o-impl/src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use std::fmt::Display;
use std::hash::Hash;
use std::ops::{Index, Not};

#[cfg(feature = "syn2")]
use syn2 as syn;

use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};
use syn::parse::{Parse, ParseBuffer, ParseStream};
Expand Down Expand Up @@ -1060,9 +1063,15 @@ pub(crate) fn get_data_type_attrs(input: &[Attribute]) -> Result<(DataTypeAttrs,

let mut instrs: Vec<DataTypeInstruction> = vec![];
for x in input.iter() {
if x.path.is_ident("doc") {
#[cfg(feature = "syn")]
let path = &x.path;

#[cfg(feature = "syn2")]
let path = x.meta.path();

if path.is_ident("doc") {
continue;
} else if x.path.is_ident("o2o") {
} else if path.is_ident("o2o") {
x.parse_args_with(|input: ParseStream| {
let new_instrs: Punctuated<DataTypeInstruction, Token![,]> = Punctuated::parse_terminated_with(input, |input| {
let instr = input.parse::<Ident>()?;
Expand All @@ -1077,9 +1086,18 @@ pub(crate) fn get_data_type_attrs(input: &[Attribute]) -> Result<(DataTypeAttrs,
instrs.extend(new_instrs.into_iter());
Ok(())
})?;
} else if let Some(instr) = x.path.get_ident() {
let p: OptionalParenthesizedTokenStream = syn::parse2(x.tokens.clone())?;
instrs.push(parse_data_type_instruction(instr, p.content(), false, bark)?);
} else if let Some(instr) = path.get_ident() {
#[cfg(feature = "syn")]
let tokens = syn::parse2(x.tokens.clone()).map(|x: OptionalParenthesizedTokenStream|x.content())?;

#[cfg(feature = "syn2")]
let tokens = match &x.meta {
syn2::Meta::Path(_) => TokenStream::new(),
syn2::Meta::List(l) => l.tokens.clone(),
syn2::Meta::NameValue(_) => Err(syn::Error::new(x.span(), "#[name = \"Value\"] syntax is not supported."))?,
};

instrs.push(parse_data_type_instruction(instr, tokens, false, bark)?);
}
}

Expand Down Expand Up @@ -1123,9 +1141,15 @@ pub(crate) fn get_data_type_attrs(input: &[Attribute]) -> Result<(DataTypeAttrs,
pub(crate) fn get_member_attrs(input: SynDataTypeMember, bark: bool) -> Result<MemberAttrs> {
let mut instrs: Vec<MemberInstruction> = vec![];
for x in input.get_attrs().iter() {
if x.path.is_ident("doc") {
#[cfg(feature = "syn")]
let path = &x.path;

#[cfg(feature = "syn2")]
let path = x.meta.path();

if path.is_ident("doc") {
continue;
} else if x.path.is_ident("o2o") {
} else if path.is_ident("o2o") {
x.parse_args_with(|input: ParseStream| {
let new_instrs: Punctuated<MemberInstruction, Token![,]> = Punctuated::parse_terminated_with(input, |input| {
let instr = input.parse::<Ident>()?;
Expand All @@ -1135,9 +1159,18 @@ pub(crate) fn get_member_attrs(input: SynDataTypeMember, bark: bool) -> Result<M
instrs.extend(new_instrs.into_iter());
Ok(())
})?;
} else if let Some(instr) = x.path.get_ident() {
let p: OptionalParenthesizedTokenStream = syn::parse2(x.tokens.clone())?;
instrs.push(parse_member_instruction(instr, p.content(), false, bark)?);
} else if let Some(instr) = path.get_ident() {
#[cfg(feature = "syn")]
let tokens = syn::parse2(x.tokens.clone()).map(|x: OptionalParenthesizedTokenStream|x.content())?;

#[cfg(feature = "syn2")]
let tokens = match &x.meta {
syn2::Meta::Path(_) => TokenStream::new(),
syn2::Meta::List(l) => l.tokens.clone(),
syn2::Meta::NameValue(_) => Err(syn::Error::new(x.span(), "#[name = \"Value\"] syntax is not supported."))?,
};

instrs.push(parse_member_instruction(instr, tokens, false, bark)?);
}
}

Expand Down Expand Up @@ -1371,6 +1404,7 @@ fn peek_ghost_field_name(input: ParseStream) -> bool {
peek_member(input) && (input.peek2(Token![:]) || input.peek2(Brace) || input.peek2(Paren))
}

#[cfg(feature = "syn")]
fn try_parse_child_parents(input: ParseStream) -> Result<Punctuated<ChildParentData, Token![,]>> {
input.parse_terminated(|x| {
let child_path: Punctuated<Member, Token![.]> = Punctuated::parse_separated_nonempty(x)?;
Expand All @@ -1385,6 +1419,21 @@ fn try_parse_child_parents(input: ParseStream) -> Result<Punctuated<ChildParentD
})
}

#[cfg(feature = "syn2")]
fn try_parse_child_parents(input: ParseStream) -> Result<Punctuated<ChildParentData, Token![,]>> {
input.parse_terminated(|x| {
let child_path: Punctuated<Member, Token![.]> = Punctuated::parse_separated_nonempty(x)?;
x.parse::<Token![:]>()?;
let ty = x.parse::<syn::Path>()?;
Ok(ChildParentData {
ty,
type_hint: try_parse_type_hint(x)?,
field_path: child_path.clone(),
field_path_str: child_path.to_token_stream().to_string().chars().filter(|c| !c.is_whitespace()).collect(),
})
}, Token![,])
}

fn try_parse_action(input: ParseStream, allow_braceless: bool) -> Result<Option<TokenStream>> {
if input.is_empty() {
Ok(None)
Expand Down
4 changes: 4 additions & 0 deletions o2o-impl/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ use crate::{
};
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote, ToTokens};

#[cfg(feature = "syn2")]
use syn2 as syn;

use syn::{
parse_quote, Data, DeriveInput, Error, GenericArgument, GenericParam, Index, Lifetime,
Member::{self, Named, Unnamed}, Result
Expand Down
3 changes: 3 additions & 0 deletions o2o-impl/src/kw.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#[cfg(feature = "syn2")]
use syn2 as syn;

syn::custom_keyword!(vars);
syn::custom_keyword!(repeat);
syn::custom_keyword!(permeate);
Expand Down
10 changes: 9 additions & 1 deletion o2o-impl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
#[cfg(all(feature = "syn", feature = "syn2"))]
compile_error!("Features 'syn' and 'syn2' cannot be enabled at the same time");

#[cfg(not(all(feature = "syn", feature = "syn2")))]
mod ast;
#[cfg(not(all(feature = "syn", feature = "syn2")))]
mod attr;
#[cfg(not(all(feature = "syn", feature = "syn2")))]
pub mod expand;
#[cfg(not(all(feature = "syn", feature = "syn2")))]
mod kw;
#[cfg(not(all(feature = "syn", feature = "syn2")))]
mod validate;

mod tests;
mod tests;
4 changes: 4 additions & 0 deletions o2o-impl/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
use crate::expand::derive;
use proc_macro2::TokenStream;
use quote::quote;

#[cfg(feature = "syn2")]
use syn2 as syn;

use syn::{DeriveInput, Error};
use test_case::test_case;

Expand Down
4 changes: 4 additions & 0 deletions o2o-impl/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use crate::{
use proc_macro2::Span;
use quote::ToTokens;
use std::collections::{HashMap, HashSet};

#[cfg(feature = "syn2")]
use syn2 as syn;

use syn::{spanned::Spanned, Result};

pub(crate) fn validate(input: &DataType) -> Result<()> {
Expand Down
12 changes: 9 additions & 3 deletions o2o-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "o2o-macros"
version = "0.5.0"
version = "0.5.1-beta1"
edition = "2021"
authors = ["Artem Romanenia <artem.romanenia@gmail.com>"]
description = "Macro definitions of 'o2o' crate"
Expand All @@ -11,5 +11,11 @@ repository = "https://github.com/Artem-Romanenia/o2o"
proc-macro = true

[dependencies]
o2o-impl = { version = "0.5.0", path = "../o2o-impl" }
syn = "1.0.3"
o2o-impl = { version = "0.5.1-beta1", path = "../o2o-impl" }
syn = { package = "syn", version = "1.0.3", optional = true }
syn2 = { package = "syn", version = "2.0.0", optional = true }

[features]
default = ["syn1"]
syn1 = ["dep:syn", "o2o-impl/syn"]
syn2 = ["dep:syn2", "o2o-impl/syn2"]
4 changes: 4 additions & 0 deletions o2o-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ extern crate o2o_impl;

use o2o_impl::expand::derive;
use proc_macro::TokenStream;

#[cfg(feature = "syn2")]
use syn2 as syn;

use syn::{parse_macro_input, DeriveInput};

/// ### Object to Object mapper for Rust
Expand Down
8 changes: 6 additions & 2 deletions o2o-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
[package]
name = "o2o-tests"
version = "0.5.0"
version = "0.5.1-beta1"
edition = "2021"
authors = ["Artem Romanenia <artem.romanenia@gmail.com>"]
description = "Tests for 'o2o' crate"
license = "MIT OR Apache-2.0"
repository = "https://github.com/Artem-Romanenia/o2o"

[dependencies]
o2o = { version = "0.5.0", path = "../" }
o2o = { version = "0.5.1-beta1", default-features = false, path = "../" }
anyhow = "1.0.86"

[dev-dependencies]
test-case = "3"

[features]
syn1 = ["o2o/syn1"]
syn2 = ["o2o/syn2"]
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![no_std]
#![doc = include_str!("../README.md")]

#[cfg(feature = "macro")]
#[cfg(any(feature = "syn1", feature = "syn2"))]
pub use o2o_macros::*;

pub mod traits;
7 changes: 7 additions & 0 deletions tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cargo test -q -p o2o
cargo test -q -p o2o --no-default-features --features syn1
cargo test -q -p o2o --no-default-features --features syn2
cargo test -q -p o2o-tests --features syn1
cargo test -q -p o2o-tests --features syn2
cargo test -q -p o2o-impl --features syn
cargo test -q -p o2o-impl --features syn2

0 comments on commit 29499c4

Please sign in to comment.