cha_plugin_sdk_macros/
lib.rs1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{Ident, parse_macro_input};
4
5const WIT: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/wit/plugin.wit"));
7
8#[proc_macro]
24pub fn plugin(input: TokenStream) -> TokenStream {
25 let ty = parse_macro_input!(input as Ident);
26 let wit = WIT;
27
28 quote! {
29 wit_bindgen::generate!({
30 inline: #wit,
31 world: "analyzer",
32 });
33 #[allow(unused_imports)]
34 use cha::plugin::types::{
35 ClassInfo, FunctionInfo, ImportInfo, Location, OptionValue, Severity, SmellCategory,
36 };
37
38 pub trait PluginImpl {
41 fn name() -> String;
42 fn analyze(input: AnalysisInput) -> Vec<Finding>;
43 }
44
45 struct __ChaPluginWrapper(std::marker::PhantomData<#ty>);
46
47 impl Guest for __ChaPluginWrapper {
48 fn name() -> String { <#ty as PluginImpl>::name() }
49 fn version() -> String { env!("CARGO_PKG_VERSION").to_string() }
50 fn description() -> String {
51 let d = env!("CARGO_PKG_DESCRIPTION");
52 if d.is_empty() { <#ty as PluginImpl>::name() } else { d.to_string() }
53 }
54 fn authors() -> Vec<String> {
55 let a = env!("CARGO_PKG_AUTHORS");
56 if a.is_empty() { vec![] } else { a.split(':').map(str::to_string).collect() }
57 }
58 fn analyze(input: AnalysisInput) -> Vec<Finding> { <#ty as PluginImpl>::analyze(input) }
59 }
60
61 export!(__ChaPluginWrapper);
62 }
63 .into()
64}