fix: macro crate cannot be compiled alone (#4130)

* fix: macro crate cannot be compiled alone

* Update src/common/macro/Cargo.toml

Co-authored-by: Yingwen <realevenyag@gmail.com>

---------

Co-authored-by: tison <wander4096@gmail.com>
Co-authored-by: Yingwen <realevenyag@gmail.com>
This commit is contained in:
Ning Sun
2024-06-10 22:36:29 -07:00
committed by GitHub
parent 9cae15bd1b
commit 587e99d806
15 changed files with 131 additions and 139 deletions

1
Cargo.lock generated
View File

@@ -1921,7 +1921,6 @@ dependencies = [
"quote",
"snafu 0.8.3",
"static_assertions",
"syn 1.0.109",
"syn 2.0.66",
]

View File

@@ -44,10 +44,10 @@ struct ProcedureStateJson {
/// A function to query procedure state by its id.
/// Such as `procedure_state(pid)`.
#[admin_fn(
name = "ProcedureStateFunction",
display_name = "procedure_state",
sig_fn = "signature",
ret = "string"
name = ProcedureStateFunction,
display_name = procedure_state,
sig_fn = signature,
ret = string
)]
pub(crate) async fn procedure_state(
procedure_service_handler: &ProcedureServiceHandlerRef,

View File

@@ -35,7 +35,7 @@ use crate::helper::cast_u64;
macro_rules! define_region_function {
($name: expr, $display_name_str: expr, $display_name: ident) => {
/// A function to $display_name
#[admin_fn(name = $name, display_name = $display_name_str, sig_fn = "signature", ret = "uint64")]
#[admin_fn(name = $name, display_name = $display_name_str, sig_fn = signature, ret = uint64)]
pub(crate) async fn $display_name(
table_mutation_handler: &TableMutationHandlerRef,
query_ctx: &QueryContextRef,
@@ -53,7 +53,7 @@ macro_rules! define_region_function {
let Some(region_id) = cast_u64(&params[0])? else {
return UnsupportedInputDataTypeSnafu {
function: $display_name_str,
function: stringify!($display_name_str),
datatypes: params.iter().map(|v| v.data_type()).collect::<Vec<_>>(),
}
.fail();
@@ -68,9 +68,9 @@ macro_rules! define_region_function {
};
}
define_region_function!("FlushRegionFunction", "flush_region", flush_region);
define_region_function!(FlushRegionFunction, flush_region, flush_region);
define_region_function!("CompactRegionFunction", "compact_region", compact_region);
define_region_function!(CompactRegionFunction, compact_region, compact_region);
fn signature() -> Signature {
Signature::uniform(1, ConcreteDataType::numerics(), Volatility::Immutable)

View File

@@ -40,10 +40,10 @@ use crate::handlers::TableMutationHandlerRef;
const COMPACT_TYPE_STRICT_WINDOW: &str = "strict_window";
#[admin_fn(
name = "FlushTableFunction",
display_name = "flush_table",
sig_fn = "flush_signature",
ret = "uint64"
name = FlushTableFunction,
display_name = flush_table,
sig_fn = flush_signature,
ret = uint64
)]
pub(crate) async fn flush_table(
table_mutation_handler: &TableMutationHandlerRef,
@@ -87,10 +87,10 @@ pub(crate) async fn flush_table(
}
#[admin_fn(
name = "CompactTableFunction",
display_name = "compact_table",
sig_fn = "compact_signature",
ret = "uint64"
name = CompactTableFunction,
display_name = compact_table,
sig_fn = compact_signature,
ret = uint64
)]
pub(crate) async fn compact_table(
table_mutation_handler: &TableMutationHandlerRef,

View File

@@ -46,10 +46,10 @@ const DEFAULT_REPLAY_TIMEOUT_SECS: u64 = 10;
/// - `from_peer`: the source peer id
/// - `to_peer`: the target peer id
#[admin_fn(
name = "MigrateRegionFunction",
display_name = "migrate_region",
sig_fn = "signature",
ret = "string"
name = MigrateRegionFunction,
display_name = migrate_region,
sig_fn = signature,
ret = string
)]
pub(crate) async fn migrate_region(
procedure_service_handler: &ProcedureServiceHandlerRef,

View File

@@ -13,8 +13,7 @@ workspace = true
[dependencies]
proc-macro2 = "1.0.66"
quote = "1.0"
syn = "1.0"
syn2 = { version = "2.0", package = "syn", features = [
syn = { version = "2.0", features = [
"derive",
"parsing",
"printing",

View File

@@ -16,11 +16,11 @@ use proc_macro::TokenStream;
use quote::quote;
use syn::spanned::Spanned;
use syn::{
parse_macro_input, Attribute, AttributeArgs, Ident, ItemFn, Signature, Type, TypePath,
TypeReference, Visibility,
parse_macro_input, Attribute, Ident, ItemFn, Signature, Type, TypePath, TypeReference,
Visibility,
};
use crate::utils::{extract_arg_map, extract_input_types, get_ident};
use crate::utils::extract_input_types;
/// Internal util macro to early return on error.
macro_rules! ok {
@@ -40,12 +40,31 @@ macro_rules! error {
}
pub(crate) fn process_admin_fn(args: TokenStream, input: TokenStream) -> TokenStream {
let mut result = TokenStream::new();
let mut name: Option<Ident> = None;
let mut display_name: Option<Ident> = None;
let mut sig_fn: Option<Ident> = None;
let mut ret: Option<Ident> = None;
let parser = syn::meta::parser(|meta| {
if meta.path.is_ident("name") {
name = Some(meta.value()?.parse()?);
Ok(())
} else if meta.path.is_ident("display_name") {
display_name = Some(meta.value()?.parse()?);
Ok(())
} else if meta.path.is_ident("sig_fn") {
sig_fn = Some(meta.value()?.parse()?);
Ok(())
} else if meta.path.is_ident("ret") {
ret = Some(meta.value()?.parse()?);
Ok(())
} else {
Err(meta.error("unsupported property"))
}
});
// extract arg map
let arg_pairs = parse_macro_input!(args as AttributeArgs);
let arg_span = arg_pairs[0].span();
let arg_map = ok!(extract_arg_map(arg_pairs));
parse_macro_input!(args with parser);
// decompose the fn block
let compute_fn = parse_macro_input!(input as ItemFn);
@@ -72,16 +91,17 @@ pub(crate) fn process_admin_fn(args: TokenStream, input: TokenStream) -> TokenSt
}
let handler_type = ok!(extract_handler_type(&arg_types));
let mut result = TokenStream::new();
// build the struct and its impl block
// only do this when `display_name` is specified
if let Ok(display_name) = get_ident(&arg_map, "display_name", arg_span) {
if let Some(display_name) = display_name {
let struct_code = build_struct(
attrs,
vis,
fn_name,
ok!(get_ident(&arg_map, "name", arg_span)),
ok!(get_ident(&arg_map, "sig_fn", arg_span)),
ok!(get_ident(&arg_map, "ret", arg_span)),
name.expect("name required"),
sig_fn.expect("sig_fn required"),
ret.expect("ret required"),
handler_type,
display_name,
);

View File

@@ -14,28 +14,24 @@
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use syn::{parse_macro_input, AttributeArgs, ItemFn, Lit, Meta, NestedMeta};
use syn::{parse_macro_input, ItemFn, LitInt};
pub(crate) fn process_print_caller(args: TokenStream, input: TokenStream) -> TokenStream {
let mut depth = 1;
let args = parse_macro_input!(args as AttributeArgs);
for meta in args.iter() {
if let NestedMeta::Meta(Meta::NameValue(name_value)) = meta {
let ident = name_value
.path
.get_ident()
.expect("Expected an ident!")
.to_string();
if ident == "depth" {
let Lit::Int(i) = &name_value.lit else {
panic!("Expected 'depth' to be a valid int!")
};
depth = i.base10_parse::<usize>().expect("Invalid 'depth' value");
break;
}
let parser = syn::meta::parser(|meta| {
if meta.path.is_ident("depth") {
depth = meta
.value()?
.parse::<LitInt>()
.and_then(|v| v.base10_parse::<usize>())
.expect("Invalid 'depth' value");
Ok(())
} else {
Err(meta.error("unsupported property"))
}
}
});
parse_macro_input!(args with parser);
let tokens: TokenStream = quote! {
{

View File

@@ -16,11 +16,10 @@ use proc_macro::TokenStream;
use quote::quote;
use syn::spanned::Spanned;
use syn::{
parse_macro_input, Attribute, AttributeArgs, Ident, ItemFn, Signature, Type, TypeReference,
Visibility,
parse_macro_input, Attribute, Ident, ItemFn, Signature, Type, TypeReference, Visibility,
};
use crate::utils::{extract_arg_map, extract_input_types, get_ident};
use crate::utils::extract_input_types;
macro_rules! ok {
($item:expr) => {
@@ -32,12 +31,27 @@ macro_rules! ok {
}
pub(crate) fn process_range_fn(args: TokenStream, input: TokenStream) -> TokenStream {
let mut result = TokenStream::new();
let mut name: Option<Ident> = None;
let mut display_name: Option<Ident> = None;
let mut ret: Option<Ident> = None;
let parser = syn::meta::parser(|meta| {
if meta.path.is_ident("name") {
name = Some(meta.value()?.parse()?);
Ok(())
} else if meta.path.is_ident("display_name") {
display_name = Some(meta.value()?.parse()?);
Ok(())
} else if meta.path.is_ident("ret") {
ret = Some(meta.value()?.parse()?);
Ok(())
} else {
Err(meta.error("unsupported property"))
}
});
// extract arg map
let arg_pairs = parse_macro_input!(args as AttributeArgs);
let arg_span = arg_pairs[0].span();
let arg_map = ok!(extract_arg_map(arg_pairs));
parse_macro_input!(args with parser);
// decompose the fn block
let compute_fn = parse_macro_input!(input as ItemFn);
@@ -68,25 +82,27 @@ pub(crate) fn process_range_fn(args: TokenStream, input: TokenStream) -> TokenSt
})
.collect::<Vec<_>>();
let mut result = TokenStream::new();
// build the struct and its impl block
// only do this when `display_name` is specified
if let Ok(display_name) = get_ident(&arg_map, "display_name", arg_span) {
if let Some(display_name) = display_name {
let struct_code = build_struct(
attrs,
vis,
ok!(get_ident(&arg_map, "name", arg_span)),
name.clone().expect("name required"),
display_name,
array_types,
ok!(get_ident(&arg_map, "ret", arg_span)),
ret.clone().expect("ret required"),
);
result.extend(struct_code);
}
let calc_fn_code = build_calc_fn(
ok!(get_ident(&arg_map, "name", arg_span)),
name.expect("name required"),
arg_types,
fn_name.clone(),
ok!(get_ident(&arg_map, "ret", arg_span)),
ret.expect("ret required"),
);
// preserve this fn, but remove its `pub` modifier
let input_fn_code: TokenStream = quote! {

View File

@@ -16,13 +16,13 @@
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{quote, quote_spanned};
use syn2::spanned::Spanned;
use syn2::{parenthesized, Attribute, Ident, ItemEnum, Variant};
use syn::spanned::Spanned;
use syn::{parenthesized, Attribute, Ident, ItemEnum, Variant};
pub fn stack_trace_style_impl(args: TokenStream2, input: TokenStream2) -> TokenStream2 {
let input_cloned: TokenStream2 = input.clone();
let error_enum_definition: ItemEnum = syn2::parse2(input_cloned).unwrap();
let error_enum_definition: ItemEnum = syn::parse2(input_cloned).unwrap();
let enum_name = error_enum_definition.ident;
let mut variants = vec![];

View File

@@ -12,48 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::collections::HashMap;
use proc_macro2::Span;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::token::Comma;
use syn::{FnArg, Ident, Meta, MetaNameValue, NestedMeta, Type};
/// Extract a String <-> Ident map from the attribute args.
pub(crate) fn extract_arg_map(args: Vec<NestedMeta>) -> Result<HashMap<String, Ident>, syn::Error> {
args.into_iter()
.map(|meta| {
if let NestedMeta::Meta(Meta::NameValue(MetaNameValue { path, lit, .. })) = meta {
let name = path.get_ident().unwrap().to_string();
let ident = match lit {
syn::Lit::Str(lit_str) => lit_str.parse::<Ident>(),
_ => Err(syn::Error::new(
lit.span(),
"Unexpected attribute format. Expected `name = \"value\"`",
)),
}?;
Ok((name, ident))
} else {
Err(syn::Error::new(
meta.span(),
"Unexpected attribute format. Expected `name = \"value\"`",
))
}
})
.collect::<Result<HashMap<String, Ident>, syn::Error>>()
}
/// Helper function to get an Ident from the previous arg map.
pub(crate) fn get_ident(
map: &HashMap<String, Ident>,
key: &str,
span: Span,
) -> Result<Ident, syn::Error> {
map.get(key)
.cloned()
.ok_or_else(|| syn::Error::new(span, format!("Expect attribute {key} but not found")))
}
use syn::{FnArg, Type};
/// Extract the argument list from the annotated function.
pub(crate) fn extract_input_types(

View File

@@ -28,9 +28,9 @@ use crate::range_array::RangeArray;
/// The average value of all points in the specified interval.
#[range_fn(
name = "AvgOverTime",
ret = "Float64Array",
display_name = "prom_avg_over_time"
name = AvgOverTime,
ret = Float64Array,
display_name = prom_avg_over_time
)]
pub fn avg_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
compute::sum(values).map(|result| result / values.len() as f64)
@@ -38,9 +38,9 @@ pub fn avg_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Op
/// The minimum value of all points in the specified interval.
#[range_fn(
name = "MinOverTime",
ret = "Float64Array",
display_name = "prom_min_over_time"
name = MinOverTime,
ret = Float64Array,
display_name = prom_min_over_time
)]
pub fn min_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
compute::min(values)
@@ -48,9 +48,9 @@ pub fn min_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Op
/// The maximum value of all points in the specified interval.
#[range_fn(
name = "MaxOverTime",
ret = "Float64Array",
display_name = "prom_max_over_time"
name = MaxOverTime,
ret = Float64Array,
display_name = prom_max_over_time
)]
pub fn max_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
compute::max(values)
@@ -58,9 +58,9 @@ pub fn max_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Op
/// The sum of all values in the specified interval.
#[range_fn(
name = "SumOverTime",
ret = "Float64Array",
display_name = "prom_sum_over_time"
name = SumOverTime,
ret = Float64Array,
display_name = prom_sum_over_time
)]
pub fn sum_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
compute::sum(values)
@@ -68,9 +68,9 @@ pub fn sum_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Op
/// The count of all values in the specified interval.
#[range_fn(
name = "CountOverTime",
ret = "Float64Array",
display_name = "prom_count_over_time"
name = CountOverTime,
ret = Float64Array,
display_name = prom_count_over_time
)]
pub fn count_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
if values.is_empty() {
@@ -82,9 +82,9 @@ pub fn count_over_time(_: &TimestampMillisecondArray, values: &Float64Array) ->
/// The most recent point value in specified interval.
#[range_fn(
name = "LastOverTime",
ret = "Float64Array",
display_name = "prom_last_over_time"
name = LastOverTime,
ret = Float64Array,
display_name = prom_last_over_time
)]
pub fn last_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
values.values().last().copied()
@@ -94,9 +94,9 @@ pub fn last_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> O
/// elements (floats or native histograms) and a 1-element vector with the value 1 if
/// the range vector passed to it has no elements.
#[range_fn(
name = "AbsentOverTime",
ret = "Float64Array",
display_name = "prom_absent_over_time"
name = AbsentOverTime,
ret = Float64Array,
display_name = prom_absent_over_time
)]
pub fn absent_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
if values.is_empty() {
@@ -108,9 +108,9 @@ pub fn absent_over_time(_: &TimestampMillisecondArray, values: &Float64Array) ->
/// the value 1 for any series in the specified interval.
#[range_fn(
name = "PresentOverTime",
ret = "Float64Array",
display_name = "prom_present_over_time"
name = PresentOverTime,
ret = Float64Array,
display_name = prom_present_over_time
)]
pub fn present_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
if values.is_empty() {
@@ -124,9 +124,9 @@ pub fn present_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -
/// DataFusion's implementation:
/// <https://github.com/apache/arrow-datafusion/blob/292eb954fc0bad3a1febc597233ba26cb60bda3e/datafusion/physical-expr/src/aggregate/variance.rs#L224-#L241>
#[range_fn(
name = "StdvarOverTime",
ret = "Float64Array",
display_name = "prom_stdvar_over_time"
name = StdvarOverTime,
ret = Float64Array,
display_name = prom_stdvar_over_time
)]
pub fn stdvar_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
if values.is_empty() {
@@ -154,9 +154,9 @@ pub fn stdvar_over_time(_: &TimestampMillisecondArray, values: &Float64Array) ->
/// the population standard deviation of the values in the specified interval.
/// Prometheus's implementation: <https://github.com/prometheus/prometheus/blob/f55ab2217984770aa1eecd0f2d5f54580029b1c0/promql/functions.go#L556-L569>
#[range_fn(
name = "StddevOverTime",
ret = "Float64Array",
display_name = "prom_stddev_over_time"
name = StddevOverTime,
ret = Float64Array,
display_name = prom_stddev_over_time
)]
pub fn stddev_over_time(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
if values.is_empty() {

View File

@@ -29,7 +29,7 @@ use crate::functions::extract_array;
use crate::range_array::RangeArray;
/// used to count the number of value changes that occur within a specific time range
#[range_fn(name = "Changes", ret = "Float64Array", display_name = "prom_changes")]
#[range_fn(name = Changes, ret = Float64Array, display_name = prom_changes)]
pub fn changes(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
if values.is_empty() {
None

View File

@@ -28,7 +28,7 @@ use datatypes::arrow::datatypes::DataType;
use crate::functions::{extract_array, linear_regression};
use crate::range_array::RangeArray;
#[range_fn(name = "Deriv", ret = "Float64Array", display_name = "prom_deriv")]
#[range_fn(name = Deriv, ret = Float64Array, display_name = prom_deriv)]
pub fn deriv(times: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
if values.len() < 2 {
None

View File

@@ -29,7 +29,7 @@ use crate::functions::extract_array;
use crate::range_array::RangeArray;
/// used to count the number of times the time series starts over.
#[range_fn(name = "Resets", ret = "Float64Array", display_name = "prom_resets")]
#[range_fn(name = Resets, ret = Float64Array, display_name = prom_resets)]
pub fn resets(_: &TimestampMillisecondArray, values: &Float64Array) -> Option<f64> {
if values.is_empty() {
None