mirror of
https://github.com/tuono-labs/tuono
synced 2026-07-25 12:52:47 -07:00
chore: update cargo edition to 2024 (#673)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "tuono"
|
||||
version = "0.19.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
authors = ["V. Ageno <valerioageno@yahoo.it>"]
|
||||
description = "Superfast React fullstack framework"
|
||||
homepage = "https://tuono.dev"
|
||||
|
||||
+26
-22
@@ -1,14 +1,14 @@
|
||||
use crate::mode::Mode;
|
||||
use crate::route::Route;
|
||||
use glob::glob;
|
||||
use glob::GlobError;
|
||||
use glob::glob;
|
||||
use http::Method;
|
||||
use std::collections::hash_set::HashSet;
|
||||
use std::collections::{hash_map::Entry, HashMap};
|
||||
use std::collections::{HashMap, hash_map::Entry};
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Child;
|
||||
@@ -153,9 +153,9 @@ impl App {
|
||||
if let Err(_e) = rust_listener {
|
||||
eprintln!("Error: Failed to bind to port {}", config.server.port);
|
||||
eprintln!(
|
||||
"Please ensure that port {} is not already in use by another process or application.",
|
||||
config.server.port
|
||||
);
|
||||
"Please ensure that port {} is not already in use by another process or application.",
|
||||
config.server.port
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
@@ -167,9 +167,9 @@ impl App {
|
||||
if let Err(_e) = vite_listener {
|
||||
eprintln!("Error: Failed to bind to port {}", vite_port);
|
||||
eprintln!(
|
||||
"Please ensure that port {} is not already in use by another process or application.",
|
||||
vite_port
|
||||
);
|
||||
"Please ensure that port {} is not already in use by another process or application.",
|
||||
vite_port
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
@@ -219,7 +219,9 @@ impl App {
|
||||
Ok(config) => self.config = Some(config),
|
||||
Err(error) => {
|
||||
match error.kind() {
|
||||
io::ErrorKind::NotFound => eprintln!("Failed to read config. Please run `npm install` to generate automatically."),
|
||||
io::ErrorKind::NotFound => eprintln!(
|
||||
"Failed to read config. Please run `npm install` to generate automatically."
|
||||
),
|
||||
_ => {
|
||||
error!("Failed to read config with the following error:");
|
||||
error!("{}", error);
|
||||
@@ -453,19 +455,21 @@ mod tests {
|
||||
.into_iter()
|
||||
.for_each(|(path, expected_has_server_handler)| {
|
||||
if expected_has_server_handler {
|
||||
assert!(app
|
||||
.route_map
|
||||
.get(path)
|
||||
.expect("Failed to get route path")
|
||||
.axum_info
|
||||
.is_some())
|
||||
assert!(
|
||||
app.route_map
|
||||
.get(path)
|
||||
.expect("Failed to get route path")
|
||||
.axum_info
|
||||
.is_some()
|
||||
)
|
||||
} else {
|
||||
assert!(app
|
||||
.route_map
|
||||
.get(path)
|
||||
.expect("Failed to get route path")
|
||||
.axum_info
|
||||
.is_none())
|
||||
assert!(
|
||||
app.route_map
|
||||
.get(path)
|
||||
.expect("Failed to get route path")
|
||||
.axum_info
|
||||
.is_none()
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
use tracing::{span, Level};
|
||||
use tracing::{Level, span};
|
||||
|
||||
use crate::commands::{build, dev, new};
|
||||
use crate::mode::Mode;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use fs_extra::dir::{copy, CopyOptions};
|
||||
use fs_extra::dir::{CopyOptions, copy};
|
||||
use spinners::{Spinner, Spinners};
|
||||
use std::path::PathBuf;
|
||||
use std::thread::sleep;
|
||||
|
||||
@@ -6,7 +6,7 @@ use watchexec_supervisor::command::{Command, Program};
|
||||
use miette::{IntoDiagnostic, Result};
|
||||
use watchexec::Watchexec;
|
||||
use watchexec_signals::Signal;
|
||||
use watchexec_supervisor::job::{start_job, Job};
|
||||
use watchexec_supervisor::job::{Job, start_job};
|
||||
|
||||
use crate::source_builder::SourceBuilder;
|
||||
use console::Term;
|
||||
|
||||
@@ -3,7 +3,7 @@ use reqwest::blocking;
|
||||
use reqwest::blocking::Client;
|
||||
use serde::Deserialize;
|
||||
use std::env;
|
||||
use std::fs::{self, create_dir, File, OpenOptions};
|
||||
use std::fs::{self, File, OpenOptions, create_dir};
|
||||
use std::io::{self, prelude::*};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@@ -100,14 +100,18 @@ pub fn create_new_project(
|
||||
|
||||
if new_project_files.is_empty() {
|
||||
eprintln!("Error: Template '{template}' not found");
|
||||
println!("Hint: you can view the available templates at https://github.com/tuono-labs/tuono/tree/main/examples");
|
||||
println!(
|
||||
"Hint: you can view the available templates at https://github.com/tuono-labs/tuono/tree/main/examples"
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if folder != "." {
|
||||
if Path::new(&folder).exists() {
|
||||
eprintln!("Error: Directory '{folder}' already exists");
|
||||
println!("Hint: you can scaffold a tuono project within an existing folder with 'cd {folder} && tuono new .'");
|
||||
println!(
|
||||
"Hint: you can scaffold a tuono project within an existing folder with 'cd {folder} && tuono new .'"
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
create_dir(&folder).unwrap();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use fs_extra::dir::create_all;
|
||||
use http::Method;
|
||||
use regex::Regex;
|
||||
use reqwest::blocking::Client;
|
||||
use reqwest::Url;
|
||||
use reqwest::blocking::Client;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
@@ -180,7 +180,7 @@ impl Route {
|
||||
return Err(format!(
|
||||
"Failed to get the parent directory {:?}",
|
||||
file_path
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -216,7 +216,7 @@ impl Route {
|
||||
return Err(format!(
|
||||
"Failed to get the parent directory {:?}",
|
||||
data_file_path
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -255,7 +255,7 @@ impl Route {
|
||||
return Err(format!(
|
||||
"Failed to create the JSON file: {:?}",
|
||||
data_file_path
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -100,8 +100,11 @@ fn it_successfully_create_multiple_api_for_the_same_file() {
|
||||
assert!(temp_main_rs_content.contains(
|
||||
r#".route("/api/health_check", post(api_health_check::post_tuono_internal_api))"#
|
||||
));
|
||||
assert!(temp_main_rs_content
|
||||
.contains(r#".route("/api/health_check", get(api_health_check::get_tuono_internal_api))"#));
|
||||
assert!(
|
||||
temp_main_rs_content.contains(
|
||||
r#".route("/api/health_check", get(api_health_check::get_tuono_internal_api))"#
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tempfile::{tempdir, TempDir};
|
||||
use tempfile::{TempDir, tempdir};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TempTuonoProject {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "tuono_internal"
|
||||
version = "0.19.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
authors = ["V. Ageno <valerioageno@yahoo.it>"]
|
||||
description = "Superfast React fullstack framework"
|
||||
homepage = "https://tuono.dev"
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use tempfile::{tempdir, TempDir};
|
||||
use tempfile::{TempDir, tempdir};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TempTuonoProject {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "tuono_lib"
|
||||
version = "0.19.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
authors = ["V. Ageno <valerioageno@yahoo.it>"]
|
||||
description = "Superfast React fullstack framework"
|
||||
homepage = "https://tuono.dev"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{ssr::Js, Payload};
|
||||
use crate::{Payload, ssr::Js};
|
||||
use axum::extract::{Path, Request};
|
||||
use axum::response::Html;
|
||||
use std::collections::HashMap;
|
||||
|
||||
+51
-18
@@ -3,7 +3,12 @@ use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
|
||||
pub fn load_env_vars(mode: Mode) {
|
||||
/// Read the env variables from the .env files
|
||||
/// and set them in the OS env
|
||||
///
|
||||
/// This function is unsafe because it modifies the OS env variables (which needs
|
||||
/// to be done in a single-threaded context).
|
||||
pub unsafe fn load_env_vars(mode: Mode) {
|
||||
let mut env_files = vec![String::from(".env"), String::from(".env.local")];
|
||||
|
||||
let mode_name = match mode {
|
||||
@@ -32,7 +37,9 @@ pub fn load_env_vars(mode: Mode) {
|
||||
continue; // Skip if key exists in system env
|
||||
}
|
||||
|
||||
env::set_var(key, value);
|
||||
unsafe {
|
||||
env::set_var(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +70,9 @@ mod tests {
|
||||
|
||||
fn add_system_var(&mut self, k: &str, v: &str) {
|
||||
self.vars.insert(k.to_string(), v.to_string());
|
||||
env::set_var(k, v);
|
||||
unsafe {
|
||||
env::set_var(k, v);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_env_file(&mut self, file_name: &str, contents: &str) {
|
||||
@@ -86,7 +95,9 @@ mod tests {
|
||||
let _ = fs::remove_file(file.as_str());
|
||||
}
|
||||
for key in self.vars.keys() {
|
||||
env::remove_var(key);
|
||||
unsafe {
|
||||
env::remove_var(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,7 +110,9 @@ mod tests {
|
||||
mock_env.add_system_var("TEST_KEY", "system_value");
|
||||
mock_env.setup_env_file(".env", "TEST_KEY=file_value");
|
||||
|
||||
load_env_vars(Mode::Dev);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Dev);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["TEST_KEY"]);
|
||||
|
||||
@@ -114,7 +127,9 @@ mod tests {
|
||||
mock_env.setup_env_file(".env", "TEST_KEY=base_value");
|
||||
mock_env.setup_env_file(".env.development", "TEST_KEY=development_value");
|
||||
|
||||
load_env_vars(Mode::Dev);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Dev);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["TEST_KEY"]);
|
||||
|
||||
@@ -129,7 +144,9 @@ mod tests {
|
||||
mock_env.setup_env_file(".env", "TEST_KEY=base_value");
|
||||
mock_env.setup_env_file(".env.production", "TEST_KEY=production_value");
|
||||
|
||||
load_env_vars(Mode::Prod);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Prod);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["TEST_KEY"]);
|
||||
|
||||
@@ -144,7 +161,9 @@ mod tests {
|
||||
mock_env.setup_env_file(".env", "TEST_KEY=base_value");
|
||||
mock_env.setup_env_file(".env.local", "TEST_KEY=local_value");
|
||||
|
||||
load_env_vars(Mode::Dev);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Dev);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["TEST_KEY"]);
|
||||
|
||||
@@ -160,7 +179,9 @@ mod tests {
|
||||
mock_env.setup_env_file(".env.development", "TEST_KEY=development_value");
|
||||
mock_env.setup_env_file(".env.development.local", "TEST_KEY=local_dev_value");
|
||||
|
||||
load_env_vars(Mode::Dev);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Dev);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["TEST_KEY"]);
|
||||
|
||||
@@ -176,7 +197,9 @@ mod tests {
|
||||
mock_env.setup_env_file(".env.production", "TEST_KEY=production_value");
|
||||
mock_env.setup_env_file(".env.production.local", "TEST_KEY=local_prod_value");
|
||||
|
||||
load_env_vars(Mode::Prod);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Prod);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["TEST_KEY"]);
|
||||
|
||||
@@ -191,7 +214,9 @@ mod tests {
|
||||
mock_env.setup_env_file(".env.development", "TEST_KEY=development_value");
|
||||
mock_env.setup_env_file(".env.production", "TEST_KEY=production_value");
|
||||
|
||||
load_env_vars(Mode::Prod);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Prod);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["TEST_KEY"]);
|
||||
|
||||
@@ -205,7 +230,9 @@ mod tests {
|
||||
|
||||
mock_env.setup_env_file(".env", "");
|
||||
|
||||
load_env_vars(Mode::Dev);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Dev);
|
||||
}
|
||||
|
||||
assert!(env::var("NON_EXISTENT_KEY").is_err());
|
||||
}
|
||||
@@ -216,8 +243,9 @@ mod tests {
|
||||
let mut mock_env = MockEnv::new();
|
||||
|
||||
mock_env.setup_env_file(".env", "INVALID_LINE\nMISSING_EQUALS_SIGN");
|
||||
|
||||
load_env_vars(Mode::Dev);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Dev);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["INVALID_LINE", "MISSING_EQUALS_SIGN"]);
|
||||
|
||||
@@ -232,7 +260,9 @@ mod tests {
|
||||
|
||||
mock_env.setup_env_file(".env", r#"TEST_KEY="quoted_value""#);
|
||||
|
||||
load_env_vars(Mode::Dev);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Dev);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["TEST_KEY"]);
|
||||
|
||||
@@ -243,8 +273,9 @@ mod tests {
|
||||
#[serial]
|
||||
fn test_non_existent_env_file() {
|
||||
let mut mock_env = MockEnv::new();
|
||||
|
||||
load_env_vars(Mode::Dev);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Dev);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["NON_EXISTENT_KEY"]);
|
||||
|
||||
@@ -258,7 +289,9 @@ mod tests {
|
||||
|
||||
mock_env.setup_env_file(".env", "KEY1=value1\nKEY2=value2");
|
||||
|
||||
load_env_vars(Mode::Dev);
|
||||
unsafe {
|
||||
load_env_vars(Mode::Dev);
|
||||
}
|
||||
|
||||
mock_env.capture_keys(&["KEY1", "KEY2"]);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ pub use mode::Mode;
|
||||
pub use payload::Payload;
|
||||
pub use request::Request;
|
||||
pub use response::{Props, Response};
|
||||
pub use server::{tuono_internal_init_v8_platform, Server};
|
||||
pub use server::{Server, tuono_internal_init_v8_platform};
|
||||
pub use tuono_lib_macros::{api, handler};
|
||||
|
||||
// Re-exports
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::config::GLOBAL_CONFIG;
|
||||
use crate::manifest::MANIFEST;
|
||||
use crate::mode::{Mode, GLOBAL_MODE};
|
||||
use crate::mode::{GLOBAL_MODE, Mode};
|
||||
use erased_serde::Serialize;
|
||||
use regex::Regex;
|
||||
use serde::Serialize as SerdeSerialize;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::Request;
|
||||
use crate::{ssr::Js, Payload};
|
||||
use crate::{Payload, ssr::Js};
|
||||
use axum::Json;
|
||||
use axum::http::{HeaderMap, StatusCode};
|
||||
use axum::response::{Html, IntoResponse, Redirect};
|
||||
use axum::Json;
|
||||
use axum_extra::extract::cookie::{Cookie, CookieJar};
|
||||
use erased_serde::Serialize;
|
||||
|
||||
@@ -82,7 +82,7 @@ impl Props {
|
||||
}
|
||||
|
||||
impl Response {
|
||||
pub fn render_to_string(&self, req: Request) -> impl IntoResponse {
|
||||
pub fn render_to_string(&self, req: Request) -> impl IntoResponse + use<> {
|
||||
match self {
|
||||
Self::Props(Props {
|
||||
data,
|
||||
@@ -106,7 +106,7 @@ impl Response {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn json(&self) -> impl IntoResponse {
|
||||
pub fn json(&self) -> impl IntoResponse + use<> {
|
||||
match self {
|
||||
Self::Props(Props {
|
||||
data,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::config::GLOBAL_CONFIG;
|
||||
use crate::manifest::load_manifest;
|
||||
use crate::mode::{Mode, GLOBAL_MODE};
|
||||
use axum::routing::{get, Router};
|
||||
use crate::mode::{GLOBAL_MODE, Mode};
|
||||
use axum::routing::{Router, get};
|
||||
use colored::Colorize;
|
||||
use ssr_rs::Ssr;
|
||||
use tower_http::services::ServeDir;
|
||||
@@ -63,7 +63,13 @@ impl Server {
|
||||
|
||||
let server_address = format!("{}:{}", config.server.host, config.server.port);
|
||||
|
||||
load_env_vars(mode);
|
||||
unsafe {
|
||||
// This function is unsafe because it modifies the OS env variables
|
||||
// which is not thread-safe.
|
||||
// However, we are using it in a controlled environment which hasn't
|
||||
// spawned any threads yet.
|
||||
load_env_vars(mode);
|
||||
}
|
||||
|
||||
Server {
|
||||
router,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use colored::Colorize;
|
||||
use http::{method::Method, Request, Response};
|
||||
use http::{Request, Response, method::Method};
|
||||
use pin_project::pin_project;
|
||||
use std::fmt::Debug;
|
||||
use std::future::Future;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::mode::{Mode, GLOBAL_MODE};
|
||||
use crate::mode::{GLOBAL_MODE, Mode};
|
||||
use ssr_rs::{Ssr, SsrError};
|
||||
use std::cell::RefCell;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
@@ -4,8 +4,8 @@ use axum::response::IntoResponse;
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
use tokio_tungstenite::connect_async;
|
||||
use tokio_tungstenite::tungstenite::{Error, Message};
|
||||
use tungstenite::client::IntoClientRequest;
|
||||
use tungstenite::ClientRequestBuilder;
|
||||
use tungstenite::client::IntoClientRequest;
|
||||
|
||||
const VITE_WS_PROTOCOL: &str = "vite-hmr";
|
||||
|
||||
|
||||
@@ -71,11 +71,13 @@ async fn index_html_route() {
|
||||
|
||||
// TODO: This should return a 404 status code
|
||||
assert!(response.status().is_success());
|
||||
assert!(response
|
||||
.text()
|
||||
.await
|
||||
.unwrap()
|
||||
.starts_with("<!DOCTYPE html>"));
|
||||
assert!(
|
||||
response
|
||||
.text()
|
||||
.await
|
||||
.unwrap()
|
||||
.starts_with("<!DOCTYPE html>")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use tuono_lib::axum::http::StatusCode;
|
||||
use tuono_lib::Request;
|
||||
use tuono_lib::axum::http::StatusCode;
|
||||
|
||||
#[tuono_lib::api(GET)]
|
||||
async fn health_check(_req: Request) -> StatusCode {
|
||||
|
||||
@@ -3,9 +3,9 @@ use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::{env, fs};
|
||||
use tempfile::{tempdir, TempDir};
|
||||
use tempfile::{TempDir, tempdir};
|
||||
use tuono_lib::axum::routing::get;
|
||||
use tuono_lib::{axum::Router, tuono_internal_init_v8_platform, Mode, Server};
|
||||
use tuono_lib::{Mode, Server, axum::Router, tuono_internal_init_v8_platform};
|
||||
|
||||
use crate::utils::catch_all::get_tuono_internal_api as catch_all;
|
||||
use crate::utils::dynamic_parameter::get_tuono_internal_api as dynamic_parameter;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "tuono_lib_macros"
|
||||
version = "0.19.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
description = "Superfast React fullstack framework"
|
||||
homepage = "https://tuono.dev"
|
||||
keywords = [ "react", "typescript", "fullstack", "web", "ssr"]
|
||||
|
||||
@@ -6,7 +6,7 @@ use proc_macro::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::token::Comma;
|
||||
use syn::{parse_macro_input, FnArg, Ident, ItemFn, Pat};
|
||||
use syn::{FnArg, Ident, ItemFn, Pat, parse_macro_input};
|
||||
|
||||
pub fn api_core(attrs: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let item = parse_macro_input!(item as ItemFn);
|
||||
|
||||
@@ -7,7 +7,7 @@ use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::token::Comma;
|
||||
use syn::{parse_macro_input, FnArg, ItemFn, Pat};
|
||||
use syn::{FnArg, ItemFn, Pat, parse_macro_input};
|
||||
|
||||
pub fn handler_core(_args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let item = parse_macro_input!(item as ItemFn);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use quote::quote;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::token::Comma;
|
||||
use syn::{parse2, parse_quote, FnArg, Pat, Stmt};
|
||||
use syn::{FnArg, Pat, Stmt, parse_quote, parse2};
|
||||
|
||||
pub fn create_struct_fn_arg() -> FnArg {
|
||||
parse2(quote! {
|
||||
|
||||
Reference in New Issue
Block a user