Skip to content

Commit

Permalink
separate slang_solidity_cli into a separate crate
Browse files Browse the repository at this point in the history
and update documentation everywhere.
  • Loading branch information
OmarTawfik committed Aug 19, 2024
1 parent 7870dc9 commit cddedb0
Show file tree
Hide file tree
Showing 36 changed files with 734 additions and 396 deletions.
5 changes: 5 additions & 0 deletions .changeset/rare-shrimps-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nomicfoundation/slang": minor
---

Move the Rust CLI into a separate `slang_solidity_cli` crate.
11 changes: 9 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ members = [
"crates/metaslang/graph_builder",

"crates/solidity/inputs/language",
"crates/solidity/outputs/cargo/slang_solidity_cli",
"crates/solidity/outputs/cargo/slang_solidity_node_addon",
"crates/solidity/outputs/cargo/slang_solidity",
"crates/solidity/outputs/cargo/tests",
Expand Down Expand Up @@ -68,6 +69,7 @@ metaslang_graph_builder = { path = "crates/metaslang/graph_builder", version = "
metaslang_cst = { path = "crates/metaslang/cst", version = "0.16.0" }

slang_solidity = { path = "crates/solidity/outputs/cargo/slang_solidity", version = "0.16.0" }
slang_solidity_cli = { path = "crates/solidity/outputs/cargo/slang_solidity_cli", version = "0.16.0" }
slang_solidity_node_addon = { path = "crates/solidity/outputs/cargo/slang_solidity_node_addon", version = "0.16.0" }
solidity_cargo_tests = { path = "crates/solidity/outputs/cargo/tests", version = "0.16.0" }
solidity_language = { path = "crates/solidity/inputs/language", version = "0.16.0" }
Expand Down
4 changes: 2 additions & 2 deletions crates/codegen/runtime/cargo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ description = "Cargo runtime copied over by codegen"

# __RUST_PRODUCT_CRATE_FEATURES__ (keep in sync)
[features]
default = ["cli"]
cli = ["dep:ariadne", "dep:clap", "dep:serde_json"]
default = []
__experimental_bindings_api = ["dep:metaslang_bindings"]
__private_cli_execution = ["dep:ariadne", "dep:clap", "dep:serde_json"]
__private_testing_utils = ["dep:ariadne"]
__private_wit_bindings = ["dep:paste", "dep:wit-bindgen"]

Expand Down
17 changes: 0 additions & 17 deletions crates/codegen/runtime/cargo/src/runtime/cli/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1 @@
use thiserror::Error;

pub mod parse;

#[derive(Debug, Error)]
pub enum CommandError {
#[error("File not found: {0:?}")]
FileNotFound(String),

#[error(transparent)]
Io(#[from] std::io::Error),

#[error(transparent)]
LanguageError(#[from] crate::language::Error),

#[error("Parsing failed: {0}")]
ParseFailed(String),
}
85 changes: 46 additions & 39 deletions crates/codegen/runtime/cargo/src/runtime/cli/commands/parse.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,59 @@
use std::fs;
use std::path::PathBuf;

use clap::Parser;
use semver::Version;

use super::CommandError;
use crate::diagnostic;
use crate::language::Language;
use crate::parse_output::ParseOutput;

pub fn execute(file_path_string: &str, version: Version, json: bool) -> Result<(), CommandError> {
parse_source_file(file_path_string, version, |output| {
#[derive(Parser, Debug)]
pub struct ParseCommand {
/// File path to the source file to parse
file_path: PathBuf,

/// The language version to use for parsing
#[arg(short, long)]
version: Version,

/// Print the concrete syntax tree as JSON
#[clap(long)]
json: bool,
}

impl ParseCommand {
pub fn execute(self) {
let Self {
file_path,
version,
json,
} = self;

let file_path = file_path
.canonicalize()
.unwrap_or_else(|_| panic!("File not found: {file_path:?}"));

let input = fs::read_to_string(&file_path).unwrap();
let language = Language::new(version).unwrap();
let parse_output = language.parse(Language::ROOT_KIND, &input);

if !parse_output.is_valid() {
const COLOR: bool = true;

let report = parse_output
.errors()
.iter()
.map(|error| diagnostic::render(error, file_path.to_str().unwrap(), &input, COLOR))
.collect::<Vec<_>>()
.join("\n");

panic!("Parse failed:\n{report}");
}

if json {
let root_node = output.tree();
let json = serde_json::to_string_pretty(&root_node).expect("JSON serialization failed");
let json = serde_json::to_string_pretty(&parse_output.tree()).unwrap();

println!("{json}");
}
})
.map(|_| ())
}

pub(crate) fn parse_source_file<F>(
file_path_string: &str,
version: Version,
run_before_checking: F,
) -> Result<ParseOutput, CommandError>
where
F: FnOnce(&ParseOutput),
{
let file_path = PathBuf::from(&file_path_string)
.canonicalize()
.map_err(|_| CommandError::FileNotFound(file_path_string.to_string()))?;

let input = fs::read_to_string(file_path)?;
let language = Language::new(version)?;
let parse_output = language.parse(Language::ROOT_KIND, &input);

run_before_checking(&parse_output);

if parse_output.is_valid() {
Ok(parse_output)
} else {
const COLOR: bool = true;
let report = parse_output
.errors()
.iter()
.map(|error| diagnostic::render(error, file_path_string, &input, COLOR))
.collect::<Vec<_>>()
.join("\n");
Err(CommandError::ParseFailed(report))
}
}
55 changes: 22 additions & 33 deletions crates/codegen/runtime/cargo/src/runtime/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,31 @@
use std::process::ExitCode;
mod commands;

use clap::Subcommand;
use semver::Version;
use clap::{Parser, Subcommand};

pub mod commands;
use crate::cli::commands::parse::ParseCommand;

#[derive(Parser, Debug)]
#[command(next_line_help = true)]
#[command(author, about)]
struct Cli {
#[command(subcommand)]
command: Commands,
}

#[derive(Subcommand, Debug)]
pub enum Commands {
enum Commands {
/// Parses a source file, and outputs any syntax errors, or a JSON concrete syntax tree
Parse {
/// File path to the source file to parse
file_path: String,

/// The language version to use for parsing
#[arg(short, long)]
version: Version,
Parse(ParseCommand),
}

/// Print the concrete syntax tree as JSON
#[clap(long)]
json: bool,
},
pub fn execute() {
match Cli::parse().command {
Commands::Parse(command) => command.execute(),
};
}

impl Commands {
pub fn execute(self) -> ExitCode {
let command_result = match self {
Commands::Parse {
file_path,
version,
json,
} => commands::parse::execute(&file_path, version, json),
};
match command_result {
Ok(()) => ExitCode::SUCCESS,
Err(error) => {
eprintln!("{error}");
ExitCode::FAILURE
}
}
}
#[test]
fn verify_clap_cli() {
// Catches problems earlier in the development cycle:
<Cli as clap::CommandFactory>::command().debug_assert();
}
5 changes: 4 additions & 1 deletion crates/codegen/runtime/cargo/src/runtime/diagnostic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ pub trait Diagnostic {
fn message(&self) -> String;
}

#[cfg(any(feature = "cli", feature = "__private_testing_utils"))]
#[cfg(any(
feature = "__private_cli_execution",
feature = "__private_testing_utils"
))]
pub fn render<D: Diagnostic>(error: &D, source_id: &str, source: &str, with_color: bool) -> String {
use ariadne::{Color, Config, Label, Report, ReportKind, Source};

Expand Down
14 changes: 7 additions & 7 deletions crates/codegen/runtime/cargo/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ pub mod parse_output;
pub mod query;
pub mod text_index;

#[cfg(feature = "__private_wit_bindings")]
pub mod wit;
#[cfg(feature = "__experimental_bindings_api")]
pub mod bindings;

#[cfg(feature = "__private_cli_execution")]
pub mod cli;

#[cfg(feature = "__private_napi_interfaces")]
pub mod napi_interface;

#[cfg(feature = "cli")]
pub mod cli;

#[cfg(feature = "__experimental_bindings_api")]
pub mod bindings;
#[cfg(feature = "__private_wit_bindings")]
pub mod wit;
1 change: 1 addition & 0 deletions crates/infra/cli/src/commands/publish/cargo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const USER_FACING_CRATES: &[&str] = &[
"metaslang_graph_builder",
"metaslang_bindings",
"slang_solidity",
"slang_solidity_cli",
];

#[derive(Clone, Debug, Parser)]
Expand Down
16 changes: 7 additions & 9 deletions crates/metaslang/bindings/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
<!-- markdownlint-disable -->

# metaslang_bindings

The `metaslang_bindings` library allows computing language semantic bindings
by building stack graphs (see crate `stack-graphs`) from graphs constructed
using the `metaslang_graph_builder` library from source code parsed by parsers
generated by `metaslang`.

# metaslang_bindings

<!-- _PRODUCT_README_ (keep in sync) -->
Expand All @@ -16,6 +7,13 @@ generated by `metaslang`.

## Solidity compiler tooling by [@NomicFoundation](https://github.com/NomicFoundation)

A modular set of compiler APIs empowering the next generation of Solidity code analysis and developer tooling.
Written in Rust and distributed in multiple languages.

- [Announcement Post](https://medium.com/nomic-foundation-blog/slang-rethnet-2ad465fd7880)
- [How to write your own Solidity linter using Slang, in 25 lines of code!](https://blog.nomic.foundation/how-to-write-your-own-solidity-linter-using-slang-356e7565ad1b/)
- [User Guide](https://nomicfoundation.github.io/slang/latest/user-guide/rust-crate/)

> ❗ This project is still in alpha, and is under active development.
> If you are planning on using it, please [reach out to us on Telegram](https://t.me/+pxApdT-Ssn5hMTFh) so we can help you get started.
Expand Down
7 changes: 6 additions & 1 deletion crates/metaslang/cst/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@

## Solidity compiler tooling by [@NomicFoundation](https://github.com/NomicFoundation)

This crate provides support for parse trees used in the Solidity compiler tooling.
A modular set of compiler APIs empowering the next generation of Solidity code analysis and developer tooling.
Written in Rust and distributed in multiple languages.

- [Announcement Post](https://medium.com/nomic-foundation-blog/slang-rethnet-2ad465fd7880)
- [How to write your own Solidity linter using Slang, in 25 lines of code!](https://blog.nomic.foundation/how-to-write-your-own-solidity-linter-using-slang-356e7565ad1b/)
- [User Guide](https://nomicfoundation.github.io/slang/latest/user-guide/rust-crate/)

> ❗ This project is still in alpha, and is under active development.
> If you are planning on using it, please [reach out to us on Telegram](https://t.me/+pxApdT-Ssn5hMTFh) so we can help you get started.
Expand Down
2 changes: 1 addition & 1 deletion crates/metaslang/graph_builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ regex = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
smallvec = { workspace = true }
string-interner = { workspace = true }
thiserror = { workspace = true }

[dev-dependencies]
env_logger = { workspace = true }
indoc = { workspace = true }
string-interner = { workspace = true }
strum = { workspace = true }
strum_macros = { workspace = true }

Expand Down
19 changes: 6 additions & 13 deletions crates/metaslang/graph_builder/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
<!-- markdownlint-disable -->

# metaslang_graph_builder

Based on `tree-sitter-graph` [![DOI](https://zenodo.org/badge/368886913.svg)](https://zenodo.org/badge/latestdoi/368886913)

The `metaslang_graph_builder` library defines a DSL for constructing arbitrary graph
structures from source code that has been parsed using parsers generated using `metaslang`.

This library is currently not intended to be

# metaslang_graph_builder

<!-- _PRODUCT_README_ (keep in sync) -->
Expand All @@ -18,8 +7,12 @@ This library is currently not intended to be

## Solidity compiler tooling by [@NomicFoundation](https://github.com/NomicFoundation)

This crate defines a DSL for constructing arbitrary graph
structures from source code that has been parsed using parsers generated using `metaslang`.
A modular set of compiler APIs empowering the next generation of Solidity code analysis and developer tooling.
Written in Rust and distributed in multiple languages.

- [Announcement Post](https://medium.com/nomic-foundation-blog/slang-rethnet-2ad465fd7880)
- [How to write your own Solidity linter using Slang, in 25 lines of code!](https://blog.nomic.foundation/how-to-write-your-own-solidity-linter-using-slang-356e7565ad1b/)
- [User Guide](https://nomicfoundation.github.io/slang/latest/user-guide/rust-crate/)

> ❗ This project is still in alpha, and is under active development.
> If you are planning on using it, please [reach out to us on Telegram](https://t.me/+pxApdT-Ssn5hMTFh) so we can help you get started.
Expand Down
5 changes: 1 addition & 4 deletions crates/metaslang/graph_builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,8 @@
#![allow(clippy::single_char_pattern)]
#![allow(clippy::unused_unit)]

use string_interner as _;
#[cfg(feature = "cli")]
use {anyhow as _, clap as _, env_logger as _, tree_sitter_config as _, tree_sitter_loader as _};
#[cfg(test)]
use {env_logger as _, indoc as _, strum as _, strum_macros as _};
use {env_logger as _, indoc as _, string_interner as _, strum as _, strum_macros as _};

#[cfg(doc)]
pub mod reference;
Expand Down
Loading

0 comments on commit cddedb0

Please sign in to comment.