diff options
| author | Robin Krahl <robin.krahl@ireas.org> | 2020-01-07 11:18:04 +0000 | 
|---|---|---|
| committer | Daniel Mueller <deso@posteo.net> | 2020-01-08 09:20:25 -0800 | 
| commit | 5e20a29b4fdc8a2d442d1093681b396dcb4b816b (patch) | |
| tree | 55ab083fa8999d2ccbb5e921c1ffe52560dca152 /syn/examples/dump-syntax | |
| parent | 203e691f46d591a2cc8acdfd850fa9f5b0fb8a98 (diff) | |
| download | nitrocli-5e20a29b4fdc8a2d442d1093681b396dcb4b816b.tar.gz nitrocli-5e20a29b4fdc8a2d442d1093681b396dcb4b816b.tar.bz2 | |
Add structopt dependency in version 0.3.7
This patch series replaces argparse with structopt in the argument
handling code. As a first step, we need structopt as a dependency.
Import subrepo structopt/:structopt at efbdda4753592e27bc430fb01f7b9650b2f3174d
Import subrepo bitflags/:bitflags at 30668016aca6bd3b02c766e8347e0b4080d4c296
Import subrepo clap/:clap at 784524f7eb193e35f81082cc69454c8c21b948f7
Import subrepo heck/:heck at 093d56fbf001e1506e56dbfa38631d99b1066df1
Import subrepo proc-macro-error/:proc-macro-error at 6c4cfe79a622c5de8ae68557993542be46eacae2
Import subrepo proc-macro2/:proc-macro2 at d5d48eddca4566e5438e8a2cbed4a74e049544de
Import subrepo quote/:quote at 727436c6c137b20f0f34dde5d8fda2679b9747ad
Import subrepo rustversion/:rustversion at 0c5663313516263059ce9059ef81fc7a1cf655ca
Import subrepo syn-mid/:syn-mid at 5d3d85414a9e6674e1857ec22a87b96e04a6851a
Import subrepo syn/:syn at e87c27e87f6f4ef8919d0372bdb056d53ef0d8f3
Import subrepo textwrap/:textwrap at abcd618beae3f74841032aa5b53c1086b0a57ca2
Import subrepo unicode-segmentation/:unicode-segmentation at 637c9874c4fe0c205ff27787faf150a40295c6c3
Import subrepo unicode-width/:unicode-width at 3033826f8bf05e82724140a981d5941e48fce393
Import subrepo unicode-xid/:unicode-xid at 4baae9fffb156ba229665b972a9cd5991787ceb7
Diffstat (limited to 'syn/examples/dump-syntax')
| -rw-r--r-- | syn/examples/dump-syntax/Cargo.toml | 17 | ||||
| -rw-r--r-- | syn/examples/dump-syntax/README.md | 28 | ||||
| -rw-r--r-- | syn/examples/dump-syntax/src/main.rs | 149 | 
3 files changed, 194 insertions, 0 deletions
| diff --git a/syn/examples/dump-syntax/Cargo.toml b/syn/examples/dump-syntax/Cargo.toml new file mode 100644 index 0000000..0bc9f62 --- /dev/null +++ b/syn/examples/dump-syntax/Cargo.toml @@ -0,0 +1,17 @@ +[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 new file mode 100644 index 0000000..37c84d8 --- /dev/null +++ b/syn/examples/dump-syntax/README.md @@ -0,0 +1,28 @@ +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 new file mode 100644 index 0000000..240b7a2 --- /dev/null +++ b/syn/examples/dump-syntax/src/main.rs @@ -0,0 +1,149 @@ +//! 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) +} | 
