浏览代码

idl: Add `IdlBuilder` (#3188)

acheron 1 年之前
父节点
当前提交
84fdf31d58
共有 3 个文件被更改,包括 93 次插入38 次删除
  1. 1 0
      CHANGELOG.md
  2. 13 14
      cli/src/lib.rs
  3. 79 24
      idl/src/build.rs

+ 1 - 0
CHANGELOG.md

@@ -40,6 +40,7 @@ The minor version will be incremented upon a breaking change and the patch versi
 - cli: Add `--no-idl` option to the `test` command ([#3175](https://github.com/coral-xyz/anchor/pull/3175)).
 - spl: Add `burn_checked`, `mint_to_checked` and `approve_checked` instructions ([#3186]([https://github.com/coral-xyz/anchor/pull/3186)).
 - cli: Migrate to `agave-install` when `solana_version` is `>= 1.18.19` ([#3185](https://github.com/coral-xyz/anchor/pull/3185)).
+- idl: Add `IdlBuilder` ([#3188](https://github.com/coral-xyz/anchor/pull/3188)).
 
 ### Fixes
 

+ 13 - 14
cli/src/lib.rs

@@ -2722,13 +2722,13 @@ fn idl_build(
         }
     };
     check_idl_build_feature().ok();
-    let idl = anchor_lang_idl::build::build_idl_with_cargo_args(
-        program_path,
-        cfg.features.resolution,
-        cfg.features.skip_lint || skip_lint,
-        no_docs,
-        &cargo_args,
-    )?;
+    let idl = anchor_lang_idl::build::IdlBuilder::new()
+        .program_path(program_path)
+        .resolution(cfg.features.resolution)
+        .skip_lint(cfg.features.skip_lint || skip_lint)
+        .no_docs(no_docs)
+        .cargo_args(cargo_args)
+        .build()?;
     let out = match out {
         Some(path) => OutFile::File(PathBuf::from(path)),
         None => OutFile::Stdout,
@@ -2776,13 +2776,12 @@ in `{path}`."#
 
     check_idl_build_feature().ok();
 
-    anchor_lang_idl::build::build_idl_with_cargo_args(
-        std::env::current_dir()?,
-        cfg.features.resolution,
-        cfg.features.skip_lint || skip_lint,
-        no_docs,
-        cargo_args,
-    )
+    anchor_lang_idl::build::IdlBuilder::new()
+        .resolution(cfg.features.resolution)
+        .skip_lint(cfg.features.skip_lint || skip_lint)
+        .no_docs(no_docs)
+        .cargo_args(cargo_args.into())
+        .build()
 }
 
 fn idl_fetch(cfg_override: &ConfigOverride, address: Pubkey, out: Option<String>) -> Result<()> {

+ 79 - 24
idl/src/build.rs

@@ -1,7 +1,7 @@
 use std::{
     collections::BTreeMap,
     env, mem,
-    path::Path,
+    path::{Path, PathBuf},
     process::{Command, Stdio},
 };
 
@@ -43,36 +43,91 @@ pub trait IdlBuild {
     }
 }
 
-/// Generate IDL via compilation.
-pub fn build_idl(
-    program_path: impl AsRef<Path>,
-    resolution: bool,
-    skip_lint: bool,
-    no_docs: bool,
-) -> Result<Idl> {
-    build_idl_with_cargo_args(program_path, resolution, skip_lint, no_docs, &[])
+/// IDL builder using builder pattern.
+///
+/// # Example
+///
+/// ```ignore
+/// let idl = IdlBuilder::new().program_path(path).skip_lint(true).build()?;
+/// ```
+#[derive(Default)]
+pub struct IdlBuilder {
+    program_path: Option<PathBuf>,
+    resolution: Option<bool>,
+    skip_lint: Option<bool>,
+    no_docs: Option<bool>,
+    cargo_args: Option<Vec<String>>,
+}
+
+impl IdlBuilder {
+    /// Create a new [`IdlBuilder`] instance.
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    /// Set the program path (default: current directory)
+    pub fn program_path(mut self, program_path: PathBuf) -> Self {
+        self.program_path.replace(program_path);
+        self
+    }
+
+    /// Set whether to include account resolution information in the IDL (default: true).
+    pub fn resolution(mut self, resolution: bool) -> Self {
+        self.resolution.replace(resolution);
+        self
+    }
+    /// Set whether to skip linting (default: false).
+    pub fn skip_lint(mut self, skip_lint: bool) -> Self {
+        self.skip_lint.replace(skip_lint);
+        self
+    }
+
+    /// Set whether to skip generating docs in the IDL (default: false).
+    pub fn no_docs(mut self, no_docs: bool) -> Self {
+        self.no_docs.replace(no_docs);
+        self
+    }
+
+    /// Set the `cargo` args that will get passed to the underyling `cargo` command when building
+    /// IDLs (default: empty).
+    pub fn cargo_args(mut self, cargo_args: Vec<String>) -> Self {
+        self.cargo_args.replace(cargo_args);
+        self
+    }
+
+    /// Build the IDL with the current configuration.
+    pub fn build(self) -> Result<Idl> {
+        let idl = build(
+            &self
+                .program_path
+                .unwrap_or_else(|| std::env::current_dir().expect("Failed to get program path")),
+            self.resolution.unwrap_or(true),
+            self.skip_lint.unwrap_or_default(),
+            self.no_docs.unwrap_or_default(),
+            &self.cargo_args.unwrap_or_default(),
+        )
+        .map(convert_module_paths)
+        .map(sort)?;
+        verify(&idl)?;
+
+        Ok(idl)
+    }
 }
 
-/// Generate IDL via compilation with passing cargo arguments.
-pub fn build_idl_with_cargo_args(
+/// Generate IDL via compilation.
+#[deprecated(since = "0.1.2", note = "Use `IdlBuilder` instead")]
+pub fn build_idl(
     program_path: impl AsRef<Path>,
     resolution: bool,
     skip_lint: bool,
     no_docs: bool,
-    cargo_args: &[String],
 ) -> Result<Idl> {
-    let idl = build(
-        program_path.as_ref(),
-        resolution,
-        skip_lint,
-        no_docs,
-        cargo_args,
-    )?;
-    let idl = convert_module_paths(idl);
-    let idl = sort(idl);
-    verify(&idl)?;
-
-    Ok(idl)
+    IdlBuilder::new()
+        .program_path(program_path.as_ref().into())
+        .resolution(resolution)
+        .skip_lint(skip_lint)
+        .no_docs(no_docs)
+        .build()
 }
 
 /// Build IDL.