diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f3c68b..4a0beed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## Changed - Minimum Supported Rust Version is now 1.56.1 +- Removed internal `dotenv_codegen_impl` crate and `proc_macro_hack` dependency ## [0.15.6] - 2022-10-17 diff --git a/Cargo.toml b/Cargo.toml index fcdc3c5..68bfba3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] -members = ["dotenv", "dotenv_codegen", "dotenv_codegen_impl"] +members = ["dotenv", "dotenv_codegen"] diff --git a/README.md b/README.md index b3bff64..cb7b144 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,7 @@ This library loads environment variables from a _.env_ file. This is convenient 1. [`dotenvy`](https://crates.io/crates/dotenvy) crate - A well-maintained fork of the `dotenv` crate. 2. [`dotenvy_macro`](https://crates.io/crates/dotenvy_codegen) crate - A macro for compile time dotenv inspection. This is a fork of `dotenv_codegen`. -3. [`dotenvy_codgen_impl`](https://crates.io/crates/dotenvy_codegen_impl) crate - Internal implementation for dotenvy_codegen. -4. `dotenvy` CLI tool for running a command using the environment from a _.env_ file (currently Unix only) +3. `dotenvy` CLI tool for running a command using the environment from a _.env_ file (currently Unix only) ## Usage diff --git a/dotenv/README.md b/dotenv/README.md index b3bff64..cb7b144 100644 --- a/dotenv/README.md +++ b/dotenv/README.md @@ -16,8 +16,7 @@ This library loads environment variables from a _.env_ file. This is convenient 1. [`dotenvy`](https://crates.io/crates/dotenvy) crate - A well-maintained fork of the `dotenv` crate. 2. [`dotenvy_macro`](https://crates.io/crates/dotenvy_codegen) crate - A macro for compile time dotenv inspection. This is a fork of `dotenv_codegen`. -3. [`dotenvy_codgen_impl`](https://crates.io/crates/dotenvy_codegen_impl) crate - Internal implementation for dotenvy_codegen. -4. `dotenvy` CLI tool for running a command using the environment from a _.env_ file (currently Unix only) +3. `dotenvy` CLI tool for running a command using the environment from a _.env_ file (currently Unix only) ## Usage diff --git a/dotenv_codegen/Cargo.toml b/dotenv_codegen/Cargo.toml index c38aa97..7719817 100644 --- a/dotenv_codegen/Cargo.toml +++ b/dotenv_codegen/Cargo.toml @@ -1,5 +1,7 @@ -[package] +[lib] +proc-macro = true +[package] name = "dotenvy_macro" version = "0.15.1" authors = [ @@ -20,5 +22,7 @@ edition = "2018" rust-version = "1.56.1" [dependencies] -dotenvy_codegen_impl = { version = "0.15", path = "../dotenv_codegen_impl" } -proc-macro-hack = "0.5" +proc-macro2 = "1" +quote = "1" +syn = "1" +dotenvy = { version = "0.15", path = "../dotenv" } diff --git a/dotenv_codegen/README.md b/dotenv_codegen/README.md index 3ca2d53..ab9f94d 100644 --- a/dotenv_codegen/README.md +++ b/dotenv_codegen/README.md @@ -6,5 +6,3 @@ A macro for compile time dotenv inspection. This is a well-maintained fork of `dotenv_codegen`. - -Warning: there is an outstanding issue with rust-analyzer ([rust-analyzer #9606](https://github.com/rust-analyzer/rust-analyzer/issues/9606)) related to the `dotenv!` macro diff --git a/dotenv_codegen/src/lib.rs b/dotenv_codegen/src/lib.rs index ae3d20e..1630966 100644 --- a/dotenv_codegen/src/lib.rs +++ b/dotenv_codegen/src/lib.rs @@ -1,6 +1,69 @@ #![forbid(unsafe_code)] -use proc_macro_hack::proc_macro_hack; +use std::env::{self, VarError}; -#[proc_macro_hack] -pub use dotenvy_codegen_impl::dotenv; +use quote::quote; +use syn::parse::Parser; +use syn::punctuated::Punctuated; +use syn::spanned::Spanned; +use syn::Token; + +#[proc_macro] +pub fn dotenv(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + dotenv_inner(input.into()).into() +} + +fn dotenv_inner(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream { + if let Err(err) = dotenvy::dotenv() { + let msg = format!("Error loading .env file: {}", err); + return quote! { + compile_error!(#msg); + }; + } + + match expand_env(input) { + Ok(stream) => stream, + Err(e) => e.to_compile_error(), + } +} + +fn expand_env(input_raw: proc_macro2::TokenStream) -> syn::Result { + let args = >::parse_terminated + .parse(input_raw.into()) + .expect("expected macro to be called with a comma-separated list of string literals"); + + let mut iter = args.iter(); + + let var_name = iter + .next() + .ok_or_else(|| syn::Error::new(args.span(), "dotenv! takes 1 or 2 arguments"))? + .value(); + let err_msg = iter.next(); + + if iter.next().is_some() { + return Err(syn::Error::new( + args.span(), + "dotenv! takes 1 or 2 arguments", + )); + } + + match env::var(&var_name) { + Ok(val) => Ok(quote!(#val)), + Err(e) => Err(syn::Error::new( + var_name.span(), + err_msg.map_or_else( + || match e { + VarError::NotPresent => { + format!("environment variable `{}` not defined", var_name) + } + + VarError::NotUnicode(s) => format!( + "environment variable `{}` was not valid unicode: {:?}", + var_name, s + ), + }, + |lit| lit.value(), + ), + )), + } +} diff --git a/dotenv_codegen_impl/Cargo.toml b/dotenv_codegen_impl/Cargo.toml deleted file mode 100644 index b8e0c85..0000000 --- a/dotenv_codegen_impl/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[lib] -proc-macro = true - -[package] - -name = "dotenvy_codegen_impl" -version = "0.15.1" -authors = [ - "Santiago Lapresta ", - "Craig Hills ", - "Mike Piccolo ", - "Alice Maz ", - "Sean Griffin ", - "Allan Zhang ", -] -readme = "../README.md" -keywords = ["dotenv", "env", "environment", "settings", "config"] -license = "MIT" -homepage = "https://github.com/allan2/dotenvy" -repository = "https://github.com/allan2/dotenvy" -description = "Internal implementation for dotenvy_codegen" -edition = "2018" -rust-version = "1.56.1" - -[dependencies] -proc-macro2 = "1" -quote = "1" -syn = "1" -proc-macro-hack = "0.5" -dotenvy = { version = "0.15", path = "../dotenv" } diff --git a/dotenv_codegen_impl/README.md b/dotenv_codegen_impl/README.md deleted file mode 100644 index 5e80d4b..0000000 --- a/dotenv_codegen_impl/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# dotenvy_codgen_impl - -[![crates.io](https://img.shields.io/crates/v/dotenvy_codegen_impl.svg)](https://crates.io/crates/dotenvy_codgen_impl) -[![Released API docs](https://docs.rs/dotenvy_codegen_impl/badge.svg)](https://docs.rs/dotenvy_codegen_impl) - -Internal implementation for [dotenvy_codgen](https://docs.rs/dotenvy_codegen_impl). - -This is a well-maintained fork of [dotenv_codegen_implementation](https://docs.rs/dotenv_codegen_implementation). diff --git a/dotenv_codegen_impl/src/lib.rs b/dotenv_codegen_impl/src/lib.rs deleted file mode 100644 index befcda8..0000000 --- a/dotenv_codegen_impl/src/lib.rs +++ /dev/null @@ -1,67 +0,0 @@ -#![forbid(unsafe_code)] - -use std::env::{self, VarError}; - -use proc_macro::TokenStream; -use proc_macro_hack::proc_macro_hack; -use quote::quote; -use syn::parse::Parser; -use syn::punctuated::Punctuated; -use syn::spanned::Spanned; -use syn::Token; - -#[proc_macro_hack] -pub fn dotenv(input: TokenStream) -> TokenStream { - if let Err(err) = dotenvy::dotenv() { - let msg = format!("Error loading .env file: {}", err); - return quote! { - compile_error!(#msg); - } - .into(); - } - - match expand_env(input) { - Ok(stream) => stream, - Err(e) => e.to_compile_error().into(), - } -} - -fn expand_env(input_raw: TokenStream) -> syn::Result { - let args = >::parse_terminated - .parse(input_raw) - .expect("expected macro to be called with a comma-separated list of string literals"); - - let mut iter = args.iter(); - - let var_name = iter - .next() - .ok_or_else(|| syn::Error::new(args.span(), "dotenv! takes 1 or 2 arguments"))? - .value(); - let err_msg = iter.next(); - - if iter.next().is_some() { - return Err(syn::Error::new( - args.span(), - "dotenv! takes 1 or 2 arguments", - )); - } - - match env::var(&var_name) { - Ok(val) => Ok(quote!(#val).into()), - Err(e) => Err(syn::Error::new( - var_name.span(), - err_msg.map_or_else( - || match e { - VarError::NotPresent => { - format!("environment variable `{}` not defined", var_name) - } - VarError::NotUnicode(s) => format!( - "environment variable `{}` was not valid unicode: {:?}", - var_name, s - ), - }, - |lit| lit.value(), - ), - )), - } -}