Skip to content

Commit

Permalink
Add option to emit expand result to stdout
Browse files Browse the repository at this point in the history
commit-id:bdf0cf3c
  • Loading branch information
maciektr committed Jun 13, 2024
1 parent 7b92e31 commit c07d13e
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 22 deletions.
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

0 comments on commit c07d13e

Please sign in to comment.