Skip to content

Commit

Permalink
[bugfix] - Fix openrpc doc generation subscription method handling (M…
Browse files Browse the repository at this point in the history
…ystenLabs#2862)

* fix open rpc doc generation subscription handling

* address PR comment, remove clone
  • Loading branch information
patrickkuo authored Jul 6, 2022
1 parent 552b750 commit e0f48cf
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 37 deletions.
54 changes: 43 additions & 11 deletions crates/sui-open-rpc-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,12 @@ pub fn open_rpc(attr: TokenStream, item: TokenStream) -> TokenStream {
} else {
quote! {None;}
};
let is_pubsub = method.is_pubsub;
methods.push(quote! {
let mut inputs: Vec<sui_open_rpc::ContentDescriptor> = Vec::new();
#(#inputs)*
let result = #returns_ty
builder.add_method(#namespace, #name, inputs, result, #doc, #tag);
builder.add_method(#namespace, #name, inputs, result, #doc, #tag, #is_pubsub);
})
}
let open_rpc_name = quote::format_ident!("{}OpenRpc", &rpc_definition.name);
Expand Down Expand Up @@ -118,18 +119,32 @@ struct Method {
params: Vec<(String, Type)>,
returns: Option<Type>,
doc: String,
is_pubsub: bool,
}

fn parse_rpc_method(trait_data: &mut syn::ItemTrait) -> Result<RpcDefinition, syn::Error> {
let mut methods = Vec::new();
for trait_item in &mut trait_data.items {
if let TraitItem::Method(method) = trait_item {
let method_name = if let Some(attr) = find_attr(&method.attrs, "method").cloned() {
let token: TokenStream = attr.tokens.clone().into();
parse::<NamedAttribute>(token)?.value.value()
} else {
"Unknown method name".to_string()
};
let (method_name, returns, is_pubsub) =
if let Some(attr) = find_attr(&method.attrs, "method") {
let token: TokenStream = attr.tokens.clone().into();
let returns = match &method.sig.output {
syn::ReturnType::Default => None,
syn::ReturnType::Type(_, output) => extract_type_from(output, "RpcResult"),
};
(
parse::<NamedAttribute>(token)?.value.value(),
returns,
false,
)
} else if let Some(attr) = find_attr(&method.attrs, "subscription") {
let token: TokenStream = attr.tokens.clone().into();
let attribute = parse::<SubscriptionNamedAttribute>(token)?;
(attribute.value.value(), Some(attribute.item), true)
} else {
panic!("Unknown method name")
};

let doc = extract_doc_comments(&method.attrs).to_string();

Expand All @@ -155,15 +170,12 @@ fn parse_rpc_method(trait_data: &mut syn::ItemTrait) -> Result<RpcDefinition, sy
})
.collect::<Result<_, _>>()?;

let returns = match &method.sig.output {
syn::ReturnType::Default => None,
syn::ReturnType::Type(_, output) => extract_type_from(output, "RpcResult"),
};
methods.push(Method {
name: method_name,
params,
returns,
doc,
is_pubsub,
});
}
}
Expand Down Expand Up @@ -288,3 +300,23 @@ struct NamedAttribute {
#[inside(_paren_token)]
value: syn::LitStr,
}

#[derive(Parse, Debug)]
struct SubscriptionNamedAttribute {
#[paren]
_paren_token: Paren,
#[inside(_paren_token)]
_ident: Ident,
#[inside(_paren_token)]
_eq_token: Token![=],
#[inside(_paren_token)]
value: syn::LitStr,
#[inside(_paren_token)]
_comma: Token![,],
#[inside(_paren_token)]
_item_ident: Ident,
#[inside(_paren_token)]
_item_eq_token: Token![=],
#[inside(_paren_token)]
item: Type,
}
47 changes: 30 additions & 17 deletions crates/sui-open-rpc/spec/openrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,6 @@
"version": "0.1.0"
},
"methods": [
{
"name": "sui_Unknown method name",
"tags": [
{
"name": "Event Subscription"
}
],
"params": [
{
"name": "filter",
"required": true,
"schema": {
"$ref": "#/components/schemas/EventFilter"
}
}
]
},
{
"name": "sui_batchTransaction",
"tags": [
Expand Down Expand Up @@ -1111,6 +1094,36 @@
}
}
},
{
"name": "sui_subscribeEvent",
"tags": [
{
"name": "Event Subscription"
},
{
"name": "Websocket"
},
{
"name": "PubSub"
}
],
"params": [
{
"name": "filter",
"required": true,
"schema": {
"$ref": "#/components/schemas/EventFilter"
}
}
],
"result": {
"name": "SuiEventEnvelope",
"required": true,
"schema": {
"$ref": "#/components/schemas/EventEnvelope"
}
}
},
{
"name": "sui_syncAccountState",
"tags": [
Expand Down
34 changes: 25 additions & 9 deletions crates/sui-open-rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct Method {
struct Tag {
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
summery: Option<String>,
summary: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
}
Expand Down Expand Up @@ -196,28 +196,44 @@ impl RpcModuleDocBuilder {
result: Option<ContentDescriptor>,
doc: &str,
tag: Option<String>,
is_pubsub: bool,
) {
let description = if doc.trim().is_empty() {
None
} else {
Some(doc.trim().to_string())
};
let name = format!("{}_{}", namespace, name);
let mut tags = tag
.map(|t| Tag {
name: t,
summary: None,
description: None,
})
.into_iter()
.collect::<Vec<_>>();

if is_pubsub {
tags.push(Tag {
name: "Websocket".to_string(),
summary: None,
description: None,
});
tags.push(Tag {
name: "PubSub".to_string(),
summary: None,
description: None,
});
}

self.methods.insert(
name.clone(),
Method {
name,
description,
params,
result,
tags: tag
.map(|t| Tag {
name: t,
summery: None,
description: None,
})
.into_iter()
.collect(),
tags,
},
);
}
Expand Down

0 comments on commit e0f48cf

Please sign in to comment.