Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

separate slang_solidity_cli into a separate crate #1079

Merged
merged 1 commit into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
}
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