Skip to content

Commit edf50cc

Browse files
committed
feat: auto_implement api
1 parent e83d5ee commit edf50cc

File tree

5 files changed

+66
-35
lines changed

5 files changed

+66
-35
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ reqwest = { version = "0.11.16", features = ["blocking", "json"] }
1313
serde = "1.0.162"
1414
serde_derive = "1.0.162"
1515
serde_json = "1.0.96"
16+
syn = { version = "2.0.15", features = ["full"] }

examples/complex.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
use auto_rust::implement;
1+
use auto_rust::auto_implement;
22

3-
implement!(fn is_email(input: String) -> bool);
3+
#[auto_implement]
4+
#[doc = "This function calculates if the input is a valid email address without use regex."]
5+
fn is_email(input: String) -> bool {
6+
todo!()
7+
}
48

59
fn main() {
610
let result = is_email("bregy@minsky.cc".to_string());

src/generator.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,26 @@ use proc_macro::TokenStream;
44

55
use crate::api::open_ai_chat_completions;
66

7-
pub fn generate_body_function_from_head(
8-
system_message: String,
9-
head: TokenStream,
10-
) -> Result<String, Box<dyn Error>> {
7+
pub fn generate_body_function_from_head(head: TokenStream) -> Result<String, Box<dyn Error>> {
8+
let system_message = "You are an AI code assistant trained on the GPT-4 architecture. Your task is to generate Rust function body implementations based only on the provided function signatures. When the user provides a function signature using the command '/complete', your response must be the plain text function body, without any explanations, formatting, or code blocks. Do not include the function signature, function name, or any other information in your response. Triple backticks (```) and function signatures are strictly prohibited in your response. Responding with any prohibited content will result in a penalty.
9+
example 1:
10+
INPUT: /complete fn my_ip() -> String
11+
OUTPUT:
12+
use std::net::UdpSocket;
13+
14+
let udp_socket = UdpSocket::bind(\"0.0.0.0:0\").unwrap();
15+
udp_socket.connect(\"8.8.8.8:80\").unwrap();
16+
let socket_addr = udp_socket.local_addr().unwrap();
17+
let ip_addr = socket_addr.ip();
18+
ip_addr.to_string()
19+
example 2:
20+
INPUT: /complete fn hello_world() -> String
21+
OUTPUT: \"Hello World\".to_string()
22+
example 3:
23+
INPUT: /complete fn hello_world(name: String) -> String
24+
OUTPUT: format!(\"Hello {}!\", name)
25+
".to_string();
26+
1127
let user_message = format!("/complete {}", head);
1228

1329
let res = open_ai_chat_completions(system_message, user_message).unwrap();

src/lib.rs

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,53 @@ mod generator;
66

77
use dotenv::dotenv;
88
use proc_macro::TokenStream;
9+
use syn::{parse, ItemFn, Lit, Meta, MetaNameValue, __private::ToTokens};
10+
use syn::{Attribute, LitStr};
911

1012
use crate::generator::generate_body_function_from_head;
1113

1214
#[proc_macro]
1315
pub fn implement(_item: TokenStream) -> TokenStream {
16+
// TODO: Evaluate the use of dotenv in this crate
1417
dotenv().ok();
15-
// println!("implement: {:?}", _item);
16-
// let resp = reqwest::blocking::get("https://httpbin.org/ip")
17-
// .unwrap()
18-
// .json::<HashMap<String, String>>()
19-
// .unwrap();
20-
21-
// let ip = resp.get("origin").unwrap().to_owned();
22-
23-
let system_message = "You are an AI code assistant trained on the GPT-4 architecture. Your task is to generate Rust function body implementations based only on the provided function signatures. When the user provides a function signature using the command '/complete', your response must be the plain text function body, without any explanations, formatting, or code blocks. Do not include the function signature, function name, or any other information in your response. Triple backticks (```) and function signatures are strictly prohibited in your response. Responding with any prohibited content will result in a penalty.
24-
example 1:
25-
INPUT: /complete fn my_ip() -> String
26-
OUTPUT: use std::net::UdpSocket;
27-
28-
let udp_socket = UdpSocket::bind(\"0.0.0.0:0\").unwrap();
29-
udp_socket.connect(\"8.8.8.8:80\").unwrap();
30-
let socket_addr = udp_socket.local_addr().unwrap();
31-
let ip_addr = socket_addr.ip();
32-
ip_addr.to_string()
33-
34-
example 2:
35-
INPUT: /complete fn hello_world() -> String
36-
OUTPUT: \"Hello World\".to_string()
37-
".to_string();
38-
let implemented_fn = generate_body_function_from_head(system_message, _item).unwrap();
18+
19+
let implemented_fn = generate_body_function_from_head(_item).unwrap();
3920

4021
println!("{}", implemented_fn);
4122

42-
// let user_message = "/complete fn hello_world() -> String".to_string();
23+
implemented_fn.parse().unwrap()
24+
}
25+
26+
#[proc_macro_attribute]
27+
pub fn auto_implement(args: TokenStream, input: TokenStream) -> TokenStream {
28+
println!("{:?}", input);
4329

44-
// format!("{} {{\"{}\".into()}}", _item, "ip")
45-
// .parse()
46-
// .unwrap()
30+
let ast: ItemFn = syn::parse(input.clone()).expect("Failed to parse input as a function");
4731

48-
implemented_fn.parse().unwrap()
32+
// Search for the information within the attributes.
33+
34+
let mut target_info = String::new();
35+
36+
let fn_header = ast.sig.to_token_stream().to_string();
37+
38+
println!("Function header: {}", fn_header);
39+
40+
for attr in ast.attrs {
41+
let data = attr.to_token_stream().to_string();
42+
// if attr.path().is_ident("doc") {
43+
// if let Ok(Meta::NameValue(meta_name_value)) = attr.parse_args() {
44+
// let info = meta_name_value.value.to_token_stream().to_string();
45+
// // if info.contains("This function calculates") {
46+
47+
// target_info = info;
48+
// break;
49+
// // }
50+
// }
51+
println!("{}", data)
52+
// }
53+
}
54+
55+
println!("Information extracted: {:?}", target_info);
56+
57+
input
4958
}

0 commit comments

Comments
 (0)