aboutsummaryrefslogtreecommitdiff
path: root/syn/examples
diff options
context:
space:
mode:
Diffstat (limited to 'syn/examples')
-rw-r--r--syn/examples/README.md19
-rw-r--r--syn/examples/dump-syntax/Cargo.toml17
-rw-r--r--syn/examples/dump-syntax/README.md28
-rw-r--r--syn/examples/dump-syntax/src/main.rs149
-rw-r--r--syn/examples/heapsize/Cargo.toml2
-rw-r--r--syn/examples/heapsize/README.md72
-rw-r--r--syn/examples/heapsize/example/Cargo.toml9
-rw-r--r--syn/examples/heapsize/example/src/main.rs28
-rw-r--r--syn/examples/heapsize/heapsize/Cargo.toml9
-rw-r--r--syn/examples/heapsize/heapsize/src/lib.rs64
-rw-r--r--syn/examples/heapsize/heapsize_derive/Cargo.toml14
-rw-r--r--syn/examples/heapsize/heapsize_derive/src/lib.rs96
-rw-r--r--syn/examples/lazy-static/Cargo.toml2
-rw-r--r--syn/examples/lazy-static/README.md42
-rw-r--r--syn/examples/lazy-static/example/Cargo.toml10
-rw-r--r--syn/examples/lazy-static/example/src/main.rs20
-rw-r--r--syn/examples/lazy-static/lazy-static/Cargo.toml14
-rw-r--r--syn/examples/lazy-static/lazy-static/src/lib.rs143
-rw-r--r--syn/examples/trace-var/Cargo.toml2
-rw-r--r--syn/examples/trace-var/README.md61
-rw-r--r--syn/examples/trace-var/example/Cargo.toml9
-rw-r--r--syn/examples/trace-var/example/src/main.rs15
-rw-r--r--syn/examples/trace-var/trace-var/Cargo.toml14
-rw-r--r--syn/examples/trace-var/trace-var/src/lib.rs180
24 files changed, 0 insertions, 1019 deletions
diff --git a/syn/examples/README.md b/syn/examples/README.md
deleted file mode 100644
index fdd69d6..0000000
--- a/syn/examples/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-### [`dump-syntax`](dump-syntax)
-
-Little utility to parse a Rust source file into a `syn::File` and print out a
-debug representation of the syntax tree.
-
-### [`heapsize`](heapsize)
-
-An example implementation of a derive macro that generates trait impls.
-
-### [`lazy-static`](lazy-static)
-
-An example of parsing a custom syntax within a `functionlike!(...)` procedural
-macro. Demonstrates how to trigger custom warnings and error messages on
-individual tokens of the input.
-
-### [`trace-var`](trace-var)
-
-An attribute procedural macro that uses a syntax tree traversal to transform
-certain syntax tree nodes in a function body.
diff --git a/syn/examples/dump-syntax/Cargo.toml b/syn/examples/dump-syntax/Cargo.toml
deleted file mode 100644
index 0bc9f62..0000000
--- a/syn/examples/dump-syntax/Cargo.toml
+++ /dev/null
@@ -1,17 +0,0 @@
-[package]
-name = "dump-syntax"
-version = "0.0.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-publish = false
-
-[dependencies]
-colored = "1.7"
-proc-macro2 = { version = "1.0", features = ["span-locations"] }
-
-[dependencies.syn]
-path = "../.."
-default-features = false
-features = ["parsing", "full", "extra-traits"]
-
-[workspace]
diff --git a/syn/examples/dump-syntax/README.md b/syn/examples/dump-syntax/README.md
deleted file mode 100644
index 37c84d8..0000000
--- a/syn/examples/dump-syntax/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-Parse a Rust source file into a `syn::File` and print out a debug representation
-of the syntax tree.
-
-Use the following command from this directory to test this program by running it
-on its own source code:
-
-```
-cargo run -- src/main.rs
-```
-
-The output will begin with:
-
-```
-File {
- shebang: None,
- attrs: [
- Attribute {
- pound_token: Pound,
- style: Inner(
- Bang
- ),
- bracket_token: Bracket,
- path: Path {
- leading_colon: None,
- segments: [
- ...
-}
-```
diff --git a/syn/examples/dump-syntax/src/main.rs b/syn/examples/dump-syntax/src/main.rs
deleted file mode 100644
index 240b7a2..0000000
--- a/syn/examples/dump-syntax/src/main.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-//! Parse a Rust source file into a `syn::File` and print out a debug
-//! representation of the syntax tree.
-//!
-//! Use the following command from this directory to test this program by
-//! running it on its own source code:
-//!
-//! cargo run -- src/main.rs
-//!
-//! The output will begin with:
-//!
-//! File {
-//! shebang: None,
-//! attrs: [
-//! Attribute {
-//! pound_token: Pound,
-//! style: Inner(
-//! ...
-//! }
-
-use std::borrow::Cow;
-use std::env;
-use std::ffi::OsStr;
-use std::fmt::{self, Display};
-use std::fs;
-use std::io::{self, Write};
-use std::path::{Path, PathBuf};
-use std::process;
-
-use colored::Colorize;
-
-enum Error {
- IncorrectUsage,
- ReadFile(io::Error),
- ParseFile {
- error: syn::Error,
- filepath: PathBuf,
- source_code: String,
- },
-}
-
-impl Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- use self::Error::*;
-
- match self {
- IncorrectUsage => write!(f, "Usage: dump-syntax path/to/filename.rs"),
- ReadFile(error) => write!(f, "Unable to read file: {}", error),
- ParseFile {
- error,
- filepath,
- source_code,
- } => render_location(f, error, filepath, source_code),
- }
- }
-}
-
-fn main() {
- if let Err(error) = try_main() {
- let _ = writeln!(io::stderr(), "{}", error);
- process::exit(1);
- }
-}
-
-fn try_main() -> Result<(), Error> {
- let mut args = env::args_os();
- let _ = args.next(); // executable name
-
- let filepath = match (args.next(), args.next()) {
- (Some(arg), None) => PathBuf::from(arg),
- _ => return Err(Error::IncorrectUsage),
- };
-
- let code = fs::read_to_string(&filepath).map_err(Error::ReadFile)?;
- let syntax = syn::parse_file(&code).map_err({
- |error| Error::ParseFile {
- error,
- filepath,
- source_code: code,
- }
- })?;
- println!("{:#?}", syntax);
-
- Ok(())
-}
-
-// Render a rustc-style error message, including colors.
-//
-// error: Syn unable to parse file
-// --> main.rs:40:17
-// |
-// 40 | fn fmt(&self formatter: &mut fmt::Formatter) -> fmt::Result {
-// | ^^^^^^^^^ expected `,`
-//
-fn render_location(
- formatter: &mut fmt::Formatter,
- err: &syn::Error,
- filepath: &Path,
- code: &str,
-) -> fmt::Result {
- let start = err.span().start();
- let mut end = err.span().end();
-
- if start.line == end.line && start.column == end.column {
- return render_fallback(formatter, err);
- }
-
- let code_line = match code.lines().nth(start.line - 1) {
- Some(line) => line,
- None => return render_fallback(formatter, err),
- };
-
- if end.line > start.line {
- end.line = start.line;
- end.column = code_line.len();
- }
-
- let filename = filepath
- .file_name()
- .map(OsStr::to_string_lossy)
- .unwrap_or(Cow::Borrowed("main.rs"));
-
- write!(
- formatter,
- "\n\
- {error}{header}\n\
- {indent}{arrow} {filename}:{linenum}:{colnum}\n\
- {indent} {pipe}\n\
- {label} {pipe} {code}\n\
- {indent} {pipe} {offset}{underline} {message}\n\
- ",
- error = "error".red().bold(),
- header = ": Syn unable to parse file".bold(),
- indent = " ".repeat(start.line.to_string().len()),
- arrow = "-->".blue().bold(),
- filename = filename,
- linenum = start.line,
- colnum = start.column,
- pipe = "|".blue().bold(),
- label = start.line.to_string().blue().bold(),
- code = code_line.trim_end(),
- offset = " ".repeat(start.column),
- underline = "^".repeat(end.column - start.column).red().bold(),
- message = err.to_string().red(),
- )
-}
-
-fn render_fallback(formatter: &mut fmt::Formatter, err: &syn::Error) -> fmt::Result {
- write!(formatter, "Unable to parse file: {}", err)
-}
diff --git a/syn/examples/heapsize/Cargo.toml b/syn/examples/heapsize/Cargo.toml
deleted file mode 100644
index 9b19214..0000000
--- a/syn/examples/heapsize/Cargo.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[workspace]
-members = ["example", "heapsize", "heapsize_derive"]
diff --git a/syn/examples/heapsize/README.md b/syn/examples/heapsize/README.md
deleted file mode 100644
index e789559..0000000
--- a/syn/examples/heapsize/README.md
+++ /dev/null
@@ -1,72 +0,0 @@
-A derive macro that generates trait impls.
-
-- [`heapsize/src/lib.rs`](heapsize/src/lib.rs)
-- [`heapsize_derive/src/lib.rs`](heapsize_derive/src/lib.rs)
-- [`example/src/main.rs`](example/src/main.rs)
-
-We are deriving the `HeapSize` trait which computes an estimate of the amount of
-heap memory owned by a value.
-
-```rust
-pub trait HeapSize {
- /// Total number of bytes of heap memory owned by `self`.
- fn heap_size_of_children(&self) -> usize;
-}
-```
-
-The derive macro allows users to write `#[derive(HeapSize)]` on data structures
-in their program.
-
-```rust
-#[derive(HeapSize)]
-struct Demo<'a, T: ?Sized> {
- a: Box<T>,
- b: u8,
- c: &'a str,
- d: String,
-}
-```
-
-The trait impl generated by the derive macro here would look like:
-
-```rust
-impl<'a, T: ?Sized + heapsize::HeapSize> heapsize::HeapSize for Demo<'a, T> {
- fn heap_size_of_children(&self) -> usize {
- 0 + heapsize::HeapSize::heap_size_of_children(&self.a)
- + heapsize::HeapSize::heap_size_of_children(&self.b)
- + heapsize::HeapSize::heap_size_of_children(&self.c)
- + heapsize::HeapSize::heap_size_of_children(&self.d)
- }
-}
-```
-
-The implementation of `heapsize_derive` demonstrates some attention to "spans"
-of error messages. For each subexpression in the generated code we apply the
-span of the input fragment under which we would want to trigger a compiler error
-if the subexpression fails to compile. In this example, each recursive call to
-`heap_size_of_children` is associated with the span of the corresponding struct
-field. Thus we get errors in the right place if any of the field types do not
-implement the `HeapSize` trait.
-
-```
-error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
- --> src/main.rs:7:5
- |
-7 | bad: std::thread::Thread,
- | ^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
-```
-
-Some unstable APIs in the `proc-macro2` crate let us improve this further by
-joining together the span of the field name and the field type. There is no
-difference in our code &mdash; everything is as shown in this directory &mdash;
-but building the example crate with `cargo build` shows errors like the one
-above and building with `RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build`
-is able to show errors like the following.
-
-```
-error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
- --> src/main.rs:7:5
- |
-7 | bad: std::thread::Thread,
- | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
-```
diff --git a/syn/examples/heapsize/example/Cargo.toml b/syn/examples/heapsize/example/Cargo.toml
deleted file mode 100644
index 85c7699..0000000
--- a/syn/examples/heapsize/example/Cargo.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-[package]
-name = "heapsize_example"
-version = "0.0.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-publish = false
-
-[dependencies]
-heapsize = { path = "../heapsize" }
diff --git a/syn/examples/heapsize/example/src/main.rs b/syn/examples/heapsize/example/src/main.rs
deleted file mode 100644
index 9332b11..0000000
--- a/syn/examples/heapsize/example/src/main.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-use heapsize::HeapSize;
-
-#[derive(HeapSize)]
-struct Demo<'a, T: ?Sized> {
- a: Box<T>,
- b: u8,
- c: &'a str,
- d: String,
-}
-
-fn main() {
- let demo = Demo {
- a: b"bytestring".to_vec().into_boxed_slice(),
- b: 255,
- c: "&'static str",
- d: "String".to_owned(),
- };
-
- // 10 + 0 + 0 + 6 = 16
- println!(
- "heap size = {} + {} + {} + {} = {}",
- demo.a.heap_size_of_children(),
- demo.b.heap_size_of_children(),
- demo.c.heap_size_of_children(),
- demo.d.heap_size_of_children(),
- demo.heap_size_of_children()
- );
-}
diff --git a/syn/examples/heapsize/heapsize/Cargo.toml b/syn/examples/heapsize/heapsize/Cargo.toml
deleted file mode 100644
index 27bb954..0000000
--- a/syn/examples/heapsize/heapsize/Cargo.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-[package]
-name = "heapsize"
-version = "0.0.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-publish = false
-
-[dependencies]
-heapsize_derive = { path = "../heapsize_derive" }
diff --git a/syn/examples/heapsize/heapsize/src/lib.rs b/syn/examples/heapsize/heapsize/src/lib.rs
deleted file mode 100644
index 30bb6d6..0000000
--- a/syn/examples/heapsize/heapsize/src/lib.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-use std::mem;
-
-pub use heapsize_derive::*;
-
-pub trait HeapSize {
- /// Total number of bytes of heap memory owned by `self`.
- ///
- /// Does not include the size of `self` itself, which may or may not be on
- /// the heap. Includes only children of `self`, meaning things pointed to by
- /// `self`.
- fn heap_size_of_children(&self) -> usize;
-}
-
-//
-// In a real version of this library there would be lots more impls here, but
-// here are some interesting ones.
-//
-
-impl HeapSize for u8 {
- /// A `u8` does not own any heap memory.
- fn heap_size_of_children(&self) -> usize {
- 0
- }
-}
-
-impl HeapSize for String {
- /// A `String` owns enough heap memory to hold its reserved capacity.
- fn heap_size_of_children(&self) -> usize {
- self.capacity()
- }
-}
-
-impl<T> HeapSize for Box<T>
-where
- T: ?Sized + HeapSize,
-{
- /// A `Box` owns however much heap memory was allocated to hold the value of
- /// type `T` that we placed on the heap, plus transitively however much `T`
- /// itself owns.
- fn heap_size_of_children(&self) -> usize {
- mem::size_of_val(&**self) + (**self).heap_size_of_children()
- }
-}
-
-impl<T> HeapSize for [T]
-where
- T: HeapSize,
-{
- /// Sum of heap memory owned by each element of a dynamically sized slice of
- /// `T`.
- fn heap_size_of_children(&self) -> usize {
- self.iter().map(HeapSize::heap_size_of_children).sum()
- }
-}
-
-impl<'a, T> HeapSize for &'a T
-where
- T: ?Sized,
-{
- /// A shared reference does not own heap memory.
- fn heap_size_of_children(&self) -> usize {
- 0
- }
-}
diff --git a/syn/examples/heapsize/heapsize_derive/Cargo.toml b/syn/examples/heapsize/heapsize_derive/Cargo.toml
deleted file mode 100644
index f4357b9..0000000
--- a/syn/examples/heapsize/heapsize_derive/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "heapsize_derive"
-version = "0.0.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-publish = false
-
-[lib]
-proc-macro = true
-
-[dependencies]
-proc-macro2 = "1.0"
-quote = "1.0"
-syn = { path = "../../.." }
diff --git a/syn/examples/heapsize/heapsize_derive/src/lib.rs b/syn/examples/heapsize/heapsize_derive/src/lib.rs
deleted file mode 100644
index 9176b29..0000000
--- a/syn/examples/heapsize/heapsize_derive/src/lib.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-extern crate proc_macro;
-
-use proc_macro2::TokenStream;
-use quote::{quote, quote_spanned};
-use syn::spanned::Spanned;
-use syn::{parse_macro_input, parse_quote, Data, DeriveInput, Fields, GenericParam, Generics, Index};
-
-#[proc_macro_derive(HeapSize)]
-pub fn derive_heap_size(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
- // Parse the input tokens into a syntax tree.
- let input = parse_macro_input!(input as DeriveInput);
-
- // Used in the quasi-quotation below as `#name`.
- let name = input.ident;
-
- // Add a bound `T: HeapSize` to every type parameter T.
- let generics = add_trait_bounds(input.generics);
- let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
-
- // Generate an expression to sum up the heap size of each field.
- let sum = heap_size_sum(&input.data);
-
- let expanded = quote! {
- // The generated impl.
- impl #impl_generics heapsize::HeapSize for #name #ty_generics #where_clause {
- fn heap_size_of_children(&self) -> usize {
- #sum
- }
- }
- };
-
- // Hand the output tokens back to the compiler.
- proc_macro::TokenStream::from(expanded)
-}
-
-// Add a bound `T: HeapSize` to every type parameter T.
-fn add_trait_bounds(mut generics: Generics) -> Generics {
- for param in &mut generics.params {
- if let GenericParam::Type(ref mut type_param) = *param {
- type_param.bounds.push(parse_quote!(heapsize::HeapSize));
- }
- }
- generics
-}
-
-// Generate an expression to sum up the heap size of each field.
-fn heap_size_sum(data: &Data) -> TokenStream {
- match *data {
- Data::Struct(ref data) => {
- match data.fields {
- Fields::Named(ref fields) => {
- // Expands to an expression like
- //
- // 0 + self.x.heap_size() + self.y.heap_size() + self.z.heap_size()
- //
- // but using fully qualified function call syntax.
- //
- // We take some care to use the span of each `syn::Field` as
- // the span of the corresponding `heap_size_of_children`
- // call. This way if one of the field types does not
- // implement `HeapSize` then the compiler's error message
- // underlines which field it is. An example is shown in the
- // readme of the parent directory.
- let recurse = fields.named.iter().map(|f| {
- let name = &f.ident;
- quote_spanned! {f.span()=>
- heapsize::HeapSize::heap_size_of_children(&self.#name)
- }
- });
- quote! {
- 0 #(+ #recurse)*
- }
- }
- Fields::Unnamed(ref fields) => {
- // Expands to an expression like
- //
- // 0 + self.0.heap_size() + self.1.heap_size() + self.2.heap_size()
- let recurse = fields.unnamed.iter().enumerate().map(|(i, f)| {
- let index = Index::from(i);
- quote_spanned! {f.span()=>
- heapsize::HeapSize::heap_size_of_children(&self.#index)
- }
- });
- quote! {
- 0 #(+ #recurse)*
- }
- }
- Fields::Unit => {
- // Unit structs cannot own more than 0 bytes of heap memory.
- quote!(0)
- }
- }
- }
- Data::Enum(_) | Data::Union(_) => unimplemented!(),
- }
-}
diff --git a/syn/examples/lazy-static/Cargo.toml b/syn/examples/lazy-static/Cargo.toml
deleted file mode 100644
index 586e547..0000000
--- a/syn/examples/lazy-static/Cargo.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[workspace]
-members = ["example", "lazy-static"]
diff --git a/syn/examples/lazy-static/README.md b/syn/examples/lazy-static/README.md
deleted file mode 100644
index bc64585..0000000
--- a/syn/examples/lazy-static/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-An example of parsing a custom syntax within a `functionlike!(...)` procedural
-macro. Demonstrates how to trigger custom warnings and error messages on
-individual tokens of the input.
-
-- [`lazy-static/src/lib.rs`](lazy-static/src/lib.rs)
-- [`example/src/main.rs`](example/src/main.rs)
-
-The library implements a `lazy_static!` macro similar to the one from the real
-[`lazy_static`](https://docs.rs/lazy_static/1.0.0/lazy_static/) crate on
-crates.io.
-
-```rust
-lazy_static! {
- static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
-}
-```
-
-Compile and run the example by doing `cargo run` in the directory of the
-`example` crate.
-
-The implementation shows how to trigger custom warnings and error messages on
-the macro input. For example if you try adding an uncreatively named `FOO` lazy
-static, the macro will scold you with the following warning.
-
-```
-warning: come on, pick a more creative name
- --> src/main.rs:10:16
- |
-10 | static ref FOO: String = "lazy_static".to_owned();
- | ^^^
-```
-
-And if you try to lazily initialize `() = ()`, the macro will outright refuse to
-compile it for you.
-
-```
-error: I can't think of a legitimate use for lazily initializing the value `()`
- --> src/main.rs:10:27
- |
-10 | static ref UNIT: () = ();
- | ^^
-```
diff --git a/syn/examples/lazy-static/example/Cargo.toml b/syn/examples/lazy-static/example/Cargo.toml
deleted file mode 100644
index 716b08c..0000000
--- a/syn/examples/lazy-static/example/Cargo.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[package]
-name = "example"
-version = "0.0.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-publish = false
-
-[dependencies]
-lazy_static = { path = "../lazy-static" }
-regex = "0.2"
diff --git a/syn/examples/lazy-static/example/src/main.rs b/syn/examples/lazy-static/example/src/main.rs
deleted file mode 100644
index c4f64af..0000000
--- a/syn/examples/lazy-static/example/src/main.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use lazy_static::lazy_static;
-use regex::Regex;
-
-lazy_static! {
- static ref USERNAME: Regex = {
- println!("Compiling username regex...");
- Regex::new("^[a-z0-9_-]{3,16}$").unwrap()
- };
-}
-
-fn main() {
- println!("Let's validate some usernames.");
- validate("fergie");
- validate("will.i.am");
-}
-
-fn validate(name: &str) {
- // The USERNAME regex is compiled lazily the first time its value is accessed.
- println!("is_match({:?}): {}", name, USERNAME.is_match(name));
-}
diff --git a/syn/examples/lazy-static/lazy-static/Cargo.toml b/syn/examples/lazy-static/lazy-static/Cargo.toml
deleted file mode 100644
index bf65787..0000000
--- a/syn/examples/lazy-static/lazy-static/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "lazy_static"
-version = "0.0.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-publish = false
-
-[lib]
-proc-macro = true
-
-[dependencies]
-proc-macro2 = { version = "1.0", features = ["nightly"] }
-quote = "1.0"
-syn = { path = "../../../", features = ["full"] }
diff --git a/syn/examples/lazy-static/lazy-static/src/lib.rs b/syn/examples/lazy-static/lazy-static/src/lib.rs
deleted file mode 100644
index 254ca72..0000000
--- a/syn/examples/lazy-static/lazy-static/src/lib.rs
+++ /dev/null
@@ -1,143 +0,0 @@
-#![recursion_limit = "128"]
-#![feature(proc_macro_diagnostic)]
-
-extern crate proc_macro;
-use self::proc_macro::TokenStream;
-
-use quote::{quote, quote_spanned};
-use syn::parse::{Parse, ParseStream, Result};
-use syn::spanned::Spanned;
-use syn::{parse_macro_input, Expr, Ident, Token, Type, Visibility};
-
-/// Parses the following syntax, which aligns with the input of the real
-/// `lazy_static` crate.
-///
-/// lazy_static! {
-/// $VISIBILITY static ref $NAME: $TYPE = $EXPR;
-/// }
-///
-/// For example:
-///
-/// lazy_static! {
-/// static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
-/// }
-struct LazyStatic {
- visibility: Visibility,
- name: Ident,
- ty: Type,
- init: Expr,
-}
-
-impl Parse for LazyStatic {
- fn parse(input: ParseStream) -> Result<Self> {
- let visibility: Visibility = input.parse()?;
- input.parse::<Token![static]>()?;
- input.parse::<Token![ref]>()?;
- let name: Ident = input.parse()?;
- input.parse::<Token![:]>()?;
- let ty: Type = input.parse()?;
- input.parse::<Token![=]>()?;
- let init: Expr = input.parse()?;
- input.parse::<Token![;]>()?;
- Ok(LazyStatic {
- visibility,
- name,
- ty,
- init,
- })
- }
-}
-
-#[proc_macro]
-pub fn lazy_static(input: TokenStream) -> TokenStream {
- let LazyStatic {
- visibility,
- name,
- ty,
- init,
- } = parse_macro_input!(input as LazyStatic);
-
- // The warning looks like this.
- //
- // warning: come on, pick a more creative name
- // --> src/main.rs:10:16
- // |
- // 10 | static ref FOO: String = "lazy_static".to_owned();
- // | ^^^
- if name == "FOO" {
- name.span()
- .unwrap()
- .warning("come on, pick a more creative name")
- .emit();
- }
-
- // The error looks like this.
- //
- // error: I can't think of a legitimate use for lazily initializing the value `()`
- // --> src/main.rs:10:27
- // |
- // 10 | static ref UNIT: () = ();
- // | ^^
- if let Expr::Tuple(ref init) = init {
- if init.elems.is_empty() {
- init.span()
- .unwrap()
- .error("I can't think of a legitimate use for lazily initializing the value `()`")
- .emit();
- return TokenStream::new();
- }
- }
-
- // Assert that the static type implements Sync. If not, user sees an error
- // message like the following. We span this assertion with the field type's
- // line/column so that the error message appears in the correct place.
- //
- // error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied
- // --> src/main.rs:10:21
- // |
- // 10 | static ref PTR: *const () = &();
- // | ^^^^^^^^^ `*const ()` cannot be shared between threads safely
- let assert_sync = quote_spanned! {ty.span()=>
- struct _AssertSync where #ty: std::marker::Sync;
- };
-
- // Check for Sized. Not vital to check here, but the error message is less
- // confusing this way than if they get a Sized error in one of our
- // implementation details where it assumes Sized.
- //
- // error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
- // --> src/main.rs:10:19
- // |
- // 10 | static ref A: str = "";
- // | ^^^ `str` does not have a constant size known at compile-time
- let assert_sized = quote_spanned! {ty.span()=>
- struct _AssertSized where #ty: std::marker::Sized;
- };
-
- let init_ptr = quote_spanned! {init.span()=>
- Box::into_raw(Box::new(#init))
- };
-
- let expanded = quote! {
- #visibility struct #name;
-
- impl std::ops::Deref for #name {
- type Target = #ty;
-
- fn deref(&self) -> &#ty {
- #assert_sync
- #assert_sized
-
- static ONCE: std::sync::Once = std::sync::Once::new();
- static mut VALUE: *mut #ty = 0 as *mut #ty;
-
- unsafe {
- ONCE.call_once(|| VALUE = #init_ptr);
- &*VALUE
- }
- }
- }
- };
-
- TokenStream::from(expanded)
-}
diff --git a/syn/examples/trace-var/Cargo.toml b/syn/examples/trace-var/Cargo.toml
deleted file mode 100644
index b54454d..0000000
--- a/syn/examples/trace-var/Cargo.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[workspace]
-members = ["example", "trace-var"]
diff --git a/syn/examples/trace-var/README.md b/syn/examples/trace-var/README.md
deleted file mode 100644
index b93fae2..0000000
--- a/syn/examples/trace-var/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-An example of an attribute procedural macro. The `#[trace_var(...)]` attribute
-prints the value of the given variables each time they are reassigned.
-
-- [`trace-var/src/lib.rs`](trace-var/src/lib.rs)
-- [`example/src/main.rs`](example/src/main.rs)
-
-Consider the following factorial implementation.
-
-```rust
-#[trace_var(p, n)]
-fn factorial(mut n: u64) -> u64 {
- let mut p = 1;
- while n > 1 {
- p *= n;
- n -= 1;
- }
- p
-}
-```
-
-Invoking this with `factorial(8)` prints all the values of `p` and `n` during
-the execution of the function.
-
-```
-p = 1
-p = 8
-n = 7
-p = 56
-n = 6
-p = 336
-n = 5
-p = 1680
-n = 4
-p = 6720
-n = 3
-p = 20160
-n = 2
-p = 40320
-n = 1
-```
-
-The procedural macro uses a syntax tree [`Fold`] to rewrite every `let`
-statement and assignment expression in the following way:
-
-[`Fold`]: https://docs.rs/syn/1.0/syn/fold/trait.Fold.html
-
-```rust
-// Before
-let VAR = INIT;
-
-// After
-let VAR = { let VAR = INIT; println!("VAR = {:?}", VAR); VAR };
-```
-
-```rust
-// Before
-VAR = INIT
-
-// After
-{ VAR = INIT; println!("VAR = {:?}", VAR); }
-```
diff --git a/syn/examples/trace-var/example/Cargo.toml b/syn/examples/trace-var/example/Cargo.toml
deleted file mode 100644
index d2ad650..0000000
--- a/syn/examples/trace-var/example/Cargo.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-[package]
-name = "example"
-version = "0.0.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-publish = false
-
-[dependencies]
-trace-var = { path = "../trace-var" }
diff --git a/syn/examples/trace-var/example/src/main.rs b/syn/examples/trace-var/example/src/main.rs
deleted file mode 100644
index da2c10b..0000000
--- a/syn/examples/trace-var/example/src/main.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use trace_var::trace_var;
-
-fn main() {
- println!("{}", factorial(8));
-}
-
-#[trace_var(p, n)]
-fn factorial(mut n: u64) -> u64 {
- let mut p = 1;
- while n > 1 {
- p *= n;
- n -= 1;
- }
- p
-}
diff --git a/syn/examples/trace-var/trace-var/Cargo.toml b/syn/examples/trace-var/trace-var/Cargo.toml
deleted file mode 100644
index 72f56e9..0000000
--- a/syn/examples/trace-var/trace-var/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "trace-var"
-version = "0.0.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-publish = false
-
-[lib]
-proc-macro = true
-
-[dependencies]
-proc-macro2 = { version = "1.0", features = ["nightly"] }
-quote = "1.0"
-syn = { path = "../../../", features = ["full", "fold"] }
diff --git a/syn/examples/trace-var/trace-var/src/lib.rs b/syn/examples/trace-var/trace-var/src/lib.rs
deleted file mode 100644
index 0ecfb47..0000000
--- a/syn/examples/trace-var/trace-var/src/lib.rs
+++ /dev/null
@@ -1,180 +0,0 @@
-extern crate proc_macro;
-use self::proc_macro::TokenStream;
-
-use quote::{quote, ToTokens};
-use std::collections::HashSet as Set;
-use syn::fold::{self, Fold};
-use syn::parse::{Parse, ParseStream, Result};
-use syn::punctuated::Punctuated;
-use syn::{parse_macro_input, parse_quote, Expr, Ident, ItemFn, Local, Pat, Stmt, Token};
-
-/// Parses a list of variable names separated by commas.
-///
-/// a, b, c
-///
-/// This is how the compiler passes in arguments to our attribute -- it is
-/// everything inside the delimiters after the attribute name.
-///
-/// #[trace_var(a, b, c)]
-/// ^^^^^^^
-struct Args {
- vars: Set<Ident>,
-}
-
-impl Parse for Args {
- fn parse(input: ParseStream) -> Result<Self> {
- let vars = Punctuated::<Ident, Token![,]>::parse_terminated(input)?;
- Ok(Args {
- vars: vars.into_iter().collect(),
- })
- }
-}
-
-impl Args {
- /// Determines whether the given `Expr` is a path referring to one of the
- /// variables we intend to print. Expressions are used as the left-hand side
- /// of the assignment operator.
- fn should_print_expr(&self, e: &Expr) -> bool {
- match *e {
- Expr::Path(ref e) => {
- if e.path.leading_colon.is_some() {
- false
- } else if e.path.segments.len() != 1 {
- false
- } else {
- let first = e.path.segments.first().unwrap();
- self.vars.contains(&first.ident) && first.arguments.is_empty()
- }
- }
- _ => false,
- }
- }
-
- /// Determines whether the given `Pat` is an identifier equal to one of the
- /// variables we intend to print. Patterns are used as the left-hand side of
- /// a `let` binding.
- fn should_print_pat(&self, p: &Pat) -> bool {
- match p {
- Pat::Ident(ref p) => self.vars.contains(&p.ident),
- _ => false,
- }
- }
-
- /// Produces an expression that assigns the right-hand side to the left-hand
- /// side and then prints the value.
- ///
- /// // Before
- /// VAR = INIT
- ///
- /// // After
- /// { VAR = INIT; println!("VAR = {:?}", VAR); }
- fn assign_and_print(&mut self, left: Expr, op: &dyn ToTokens, right: Expr) -> Expr {
- let right = fold::fold_expr(self, right);
- parse_quote!({
- #left #op #right;
- println!(concat!(stringify!(#left), " = {:?}"), #left);
- })
- }
-
- /// Produces a let-binding that assigns the right-hand side to the left-hand
- /// side and then prints the value.
- ///
- /// // Before
- /// let VAR = INIT;
- ///
- /// // After
- /// let VAR = { let VAR = INIT; println!("VAR = {:?}", VAR); VAR };
- fn let_and_print(&mut self, local: Local) -> Stmt {
- let Local { pat, init, .. } = local;
- let init = self.fold_expr(*init.unwrap().1);
- let ident = match pat {
- Pat::Ident(ref p) => &p.ident,
- _ => unreachable!(),
- };
- parse_quote! {
- let #pat = {
- #[allow(unused_mut)]
- let #pat = #init;
- println!(concat!(stringify!(#ident), " = {:?}"), #ident);
- #ident
- };
- }
- }
-}
-
-/// The `Fold` trait is a way to traverse an owned syntax tree and replace some
-/// of its nodes.
-///
-/// Syn provides two other syntax tree traversal traits: `Visit` which walks a
-/// shared borrow of a syntax tree, and `VisitMut` which walks an exclusive
-/// borrow of a syntax tree and can mutate it in place.
-///
-/// All three traits have a method corresponding to each type of node in Syn's
-/// syntax tree. All of these methods have default no-op implementations that
-/// simply recurse on any child nodes. We can override only those methods for
-/// which we want non-default behavior. In this case the traversal needs to
-/// transform `Expr` and `Stmt` nodes.
-impl Fold for Args {
- fn fold_expr(&mut self, e: Expr) -> Expr {
- match e {
- Expr::Assign(e) => {
- if self.should_print_expr(&e.left) {
- self.assign_and_print(*e.left, &e.eq_token, *e.right)
- } else {
- Expr::Assign(fold::fold_expr_assign(self, e))
- }
- }
- Expr::AssignOp(e) => {
- if self.should_print_expr(&e.left) {
- self.assign_and_print(*e.left, &e.op, *e.right)
- } else {
- Expr::AssignOp(fold::fold_expr_assign_op(self, e))
- }
- }
- _ => fold::fold_expr(self, e),
- }
- }
-
- fn fold_stmt(&mut self, s: Stmt) -> Stmt {
- match s {
- Stmt::Local(s) => {
- if s.init.is_some() && self.should_print_pat(&s.pat) {
- self.let_and_print(s)
- } else {
- Stmt::Local(fold::fold_local(self, s))
- }
- }
- _ => fold::fold_stmt(self, s),
- }
- }
-}
-
-/// Attribute to print the value of the given variables each time they are
-/// reassigned.
-///
-/// # Example
-///
-/// ```
-/// #[trace_var(p, n)]
-/// fn factorial(mut n: u64) -> u64 {
-/// let mut p = 1;
-/// while n > 1 {
-/// p *= n;
-/// n -= 1;
-/// }
-/// p
-/// }
-/// ```
-#[proc_macro_attribute]
-pub fn trace_var(args: TokenStream, input: TokenStream) -> TokenStream {
- let input = parse_macro_input!(input as ItemFn);
-
- // Parse the list of variables the user wanted to print.
- let mut args = parse_macro_input!(args as Args);
-
- // Use a syntax tree traversal to transform the function body.
- let output = args.fold_item_fn(input);
-
- // Hand the resulting function body back to the compiler.
- TokenStream::from(quote!(#output))
-}