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

Add option to emit expand result to stdout #1357

Merged
merged 1 commit into from
Jun 14, 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
12 changes: 10 additions & 2 deletions scarb/src/bin/scarb/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ use std::ffi::OsString;

use anyhow::Result;
use camino::Utf8PathBuf;
use clap::{CommandFactory, Parser, Subcommand};
use scarb::ops::EmitTarget;
use clap::{CommandFactory, Parser, Subcommand, ValueEnum};
use smol_str::SmolStr;
use url::Url;

Expand Down Expand Up @@ -203,6 +202,11 @@ pub enum Command {
External(Vec<OsString>),
}

#[derive(ValueEnum, Clone, Debug)]
pub enum EmitTarget {
Stdout,
}

/// Arguments accepted by the `build` command.
#[derive(Parser, Clone, Debug)]
pub struct BuildArgs {
Expand Down Expand Up @@ -239,6 +243,10 @@ pub struct ExpandArgs {
/// Do not attempt formatting.
#[arg(long, default_value_t = false)]
pub ugly: bool,

/// Emit the expanded file to stdout
#[arg(short, long)]
pub emit: Option<EmitTarget>,
}

/// Arguments accepted by the `run` command.
Expand Down
11 changes: 10 additions & 1 deletion scarb/src/bin/scarb/commands/expand.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Result;
use smol_str::ToSmolStr;

use crate::args::ExpandArgs;
use crate::args::{EmitTarget, ExpandArgs};
use scarb::core::{Config, TargetKind};
use scarb::ops;
use scarb::ops::ExpandOpts;
Expand All @@ -15,6 +15,15 @@ pub fn run(args: ExpandArgs, config: &Config) -> Result<()> {
ugly: args.ugly,
target_name: args.target_name.map(|n| n.to_smolstr()),
target_kind: args.target_kind.map(TargetKind::try_new).transpose()?,
emit: args.emit.map(|e| e.into()),
};
ops::expand(package, opts, &ws)
}

impl From<EmitTarget> for ops::ExpandEmitTarget {
fn from(target: EmitTarget) -> Self {
match target {
EmitTarget::Stdout => ops::ExpandEmitTarget::Stdout,
}
}
}
12 changes: 10 additions & 2 deletions scarb/src/bin/scarb/commands/fmt.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::Result;

use crate::args::FmtArgs;
use crate::args::{EmitTarget, FmtArgs};
use crate::errors::error_with_exit_code;
use scarb::core::Config;
use scarb::ops::{self, FmtAction};
Expand All @@ -12,7 +12,7 @@ pub fn run(args: FmtArgs, config: &Config) -> Result<()> {
let action = if args.check {
FmtAction::Check
} else if let Some(emit_target) = args.emit {
FmtAction::Emit(emit_target)
FmtAction::Emit(emit_target.into())
} else {
// Format in place is the default option
FmtAction::Fix
Expand All @@ -37,3 +37,11 @@ pub fn run(args: FmtArgs, config: &Config) -> Result<()> {
error_with_exit_code(1)
}
}

impl From<EmitTarget> for ops::FmtEmitTarget {
fn from(target: EmitTarget) -> Self {
match target {
EmitTarget::Stdout => ops::FmtEmitTarget::Stdout,
}
}
}
97 changes: 85 additions & 12 deletions scarb/src/ops/expand.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::compiler::db::{build_scarb_root_database, ScarbDatabase};
use crate::compiler::helpers::{build_compiler_config, write_string};
use crate::compiler::{CairoCompilationUnit, CompilationUnit, CompilationUnitAttributes};
use crate::core::{Package, TargetKind, Workspace};
use crate::core::{Package, PackageId, TargetKind, Workspace};
use crate::ops;
use crate::ops::{get_test_package_ids, FeaturesOpts};
use anyhow::{bail, Context, Result};
Expand All @@ -16,15 +16,25 @@ use cairo_lang_parser::db::ParserGroup;
use cairo_lang_syntax::node::helpers::UsePathEx;
use cairo_lang_syntax::node::{ast, TypedStablePtr, TypedSyntaxNode};
use cairo_lang_utils::Upcast;
use scarb_ui::Message;
use serde::{Serialize, Serializer};
use smol_str::SmolStr;
use std::collections::HashSet;
use std::collections::{BTreeMap, HashSet};

#[derive(Debug, Clone, Default)]
pub enum ExpandEmitTarget {
Stdout,
#[default]
File,
}

#[derive(Clone, Debug)]
pub struct ExpandOpts {
pub features: FeaturesOpts,
pub target_kind: Option<TargetKind>,
pub target_name: Option<SmolStr>,
pub ugly: bool,
pub emit: Option<ExpandEmitTarget>,
}

pub fn expand(package: Package, opts: ExpandOpts, ws: &Workspace<'_>) -> Result<()> {
Expand Down Expand Up @@ -209,19 +219,82 @@ fn do_expand(
format_cairo(content.clone()).unwrap_or(content)
};

let file_name = format!(
"{}.expanded.cairo",
compilation_unit
.main_component()
.first_target()
.name
.clone()
);
let target_dir = compilation_unit.target_dir(ws);
write_string(file_name.as_str(), "output file", &target_dir, ws, content)?;
opts.emit
.unwrap_or_default()
.emit(content, compilation_unit, ws)?;

Ok(())
}

impl ExpandEmitTarget {
fn emit(
&self,
content: String,
compilation_unit: &CairoCompilationUnit,
ws: &Workspace<'_>,
) -> Result<()> {
match self {
Self::Stdout => {
ws.config()
.ui()
.force_print(EmittedText::new(content, compilation_unit));
}
Self::File => {
let file_name = format!(
"{}.expanded.cairo",
compilation_unit
.main_component()
.first_target()
.name
.clone()
);
let target_dir = compilation_unit.target_dir(ws);
write_string(file_name.as_str(), "output file", &target_dir, ws, content)?;
}
}
Ok(())
}
}

struct EmittedText {
expanded: String,
package_id: PackageId,
target: String,
}

impl EmittedText {
pub fn new(expanded: String, compilation_unit: &CairoCompilationUnit) -> Self {
Self {
expanded,
package_id: compilation_unit.main_package_id(),
target: compilation_unit
.main_component()
.first_target()
.name
.clone()
.to_string(),
}
}
}

impl Message for EmittedText {
fn text(self) -> String {
self.expanded
}

fn structured<S: Serializer>(self, ser: S) -> std::result::Result<S::Ok, S::Error>
where
Self: Sized,
{
BTreeMap::from_iter(vec![
("package_id".to_string(), self.package_id.to_string()),
("target_name".to_string(), self.target),
("expanded".to_string(), self.expanded),
])
.serialize(ser)
}
}

fn format_cairo(content: String) -> Option<String> {
let formatter = CairoFormatter::new(FormatterConfig::default());
let content = formatter.format_to_string(&content).ok()?;
Expand Down
9 changes: 4 additions & 5 deletions scarb/src/ops/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use anyhow::Result;
use cairo_lang_diagnostics::Severity;
use cairo_lang_formatter::cairo_formatter::FormattingError;
use cairo_lang_formatter::{CairoFormatter, FormatOutcome, FormatterConfig};
use clap::ValueEnum;
use ignore::WalkState::{Continue, Skip};
use ignore::{DirEntry, Error, ParallelVisitor, ParallelVisitorBuilder, WalkState};
use tracing::{info, warn};
Expand All @@ -15,8 +14,8 @@ use crate::core::workspace::Workspace;
use crate::core::PackageId;
use crate::internal::serdex::toml_merge;

#[derive(Debug, Clone, ValueEnum)]
pub enum EmitTarget {
#[derive(Debug, Clone)]
pub enum FmtEmitTarget {
Stdout,
}

Expand All @@ -27,7 +26,7 @@ pub enum FmtAction {
#[default]
Fix,
Check,
Emit(EmitTarget),
Emit(FmtEmitTarget),
}

#[derive(Debug)]
Expand Down Expand Up @@ -159,7 +158,7 @@ pub trait Emittable {
fn emit(&self, ws: &Workspace<'_>, path: &Path, formatted: &str);
}

impl Emittable for EmitTarget {
impl Emittable for FmtEmitTarget {
fn emit(&self, ws: &Workspace<'_>, path: &Path, formatted: &str) {
match self {
Self::Stdout => ws
Expand Down
58 changes: 58 additions & 0 deletions scarb/tests/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,64 @@ fn expand_package_simple() {
);
}

#[test]
fn can_expand_to_stdout() {
let t = TempDir::new().unwrap();
ProjectBuilder::start()
.name("hello")
.lib_cairo(indoc! {r#"
fn hello() -> felt252 {
0

"#})
.build(&t);
Scarb::quick_snapbox()
.arg("expand")
.arg("--emit=stdout")
.current_dir(&t)
.assert()
.success()
.stdout_matches(indoc! {r#"
error: Missing token TerminalRBrace.
--> [..]lib.cairo:2:6
0
^


mod hello {
fn hello() -> felt252 {
0
}

"#});
assert!(!t.child("target").exists());
}

#[test]
fn can_expand_to_stdout_json() {
let t = TempDir::new().unwrap();
ProjectBuilder::start()
.name("hello")
.lib_cairo(indoc! {r#"
fn hello() -> felt252 {
0

"#})
.build(&t);
Scarb::quick_snapbox()
.arg("--json")
.arg("expand")
.arg("--emit=stdout")
.current_dir(&t)
.assert()
.success()
.stdout_matches(indoc! {r#"
{"type":"error","message":"Missing token TerminalRBrace./n --> [..]lib.cairo:2:6/n 0/n ^/n"}
{"expanded":"/nmod hello {/nfn hello() -> felt252 {/n 0/n}/n","package_id":"hello v1.0.0 ([..]Scarb.toml)","target_name":"hello"}
"#});
assert!(!t.child("target").exists());
}

#[test]
fn expand_integration_test() {
let t = TempDir::new().unwrap();
Expand Down
Loading