Skip to content

Commit

Permalink
Add flexible, extensible configuration infrastructure, with support f…
Browse files Browse the repository at this point in the history
…or toml, CLI, and attr based config (#776)
  • Loading branch information
ambiguousname authored Mar 8, 2025
1 parent 5c383d6 commit a5f1514
Show file tree
Hide file tree
Showing 18 changed files with 432 additions and 57 deletions.
8 changes: 4 additions & 4 deletions Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ script_runner = "@duckscript"
script = '''
exit_on_error true
!include_files ./support/functions.ds
generate_generic feature_tests demo_gen demo "-l diplomat-demo-conf.toml"
generate_generic feature_tests demo_gen demo
'''

[tasks.gen-demo-example]
Expand All @@ -469,7 +469,7 @@ script_runner = "@duckscript"
script = '''
exit_on_error true
!include_files ./support/functions.ds
generate_generic example demo_gen demo "-l diplomat-demo-conf.toml"
generate_generic example demo_gen demo
'''

[tasks.gen-dart-feature]
Expand Down Expand Up @@ -498,7 +498,7 @@ script_runner = "@duckscript"
script = '''
exit_on_error true
!include_files ./support/functions.ds
generate_generic feature_tests kotlin somelib "-l diplomat-kt-conf.toml" /src/main/kotlin
generate_generic feature_tests kotlin somelib "" /src/main/kotlin
'''

[tasks.gen-kotlin-example]
Expand All @@ -507,7 +507,7 @@ script_runner = "@duckscript"
script = '''
exit_on_error true
!include_files ./support/functions.ds
generate_generic example kotlin somelib "-l diplomat-kt-conf.toml" /src/main/kotlin
generate_generic example kotlin somelib "" /src/main/kotlin
'''

# Build deps
Expand Down
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- [Introduction](./intro.md)
- [User Guide](user.md)
- [Basics](./basics.md)
- [Configuration](./config.md)
- [Types](./types.md)
- [Opaque types](./opaque.md)
- [Structs and enums](./structs.md)
Expand Down
71 changes: 71 additions & 0 deletions book/src/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Configuring Diplomat

Some Diplomat backends have configurable parameters to change the behavior of their output.

For instance, Kotlin requires a `domain` parameter and `lib_name` parameter. These two parameters are used to generate a package name and folder structure on generation.

## Configuration Structures
Documentation on what configuration options are available in [`config.rs` on GitHub](https://github.com/rust-diplomat/diplomat/tree/main/tool/src/config.rs).

Note that every configuration option uses `snake_case` for consistency, and that the `SharedConfig` struct is flattened. So for setting `--config shared_config.lib_name="some_value"`, this would instead be `--config lib_name="some_value"`.

## Configuration Interfaces

Configuration information can be set in four ways:

### `config.toml`

By default, Diplomat scans for a `config.toml` in the folder where `diplomat_tool` is being run. You can change the location of this folder with the `--config_file` parameter.

The structure of `config.toml` is as follows:

```toml
# Top level table specifies Shared Config settings that apply to all backends:
lib-name = "MyLibrary"

[kotlin]
# Individual tables can override Shared Config settings:
lib-name = "LibraryNameOverride"
# Along with backend specific settings:
domain = "org.myOrganization"

[demo_gen]
explicit-generation = true

[other-library-name]
some-value = 100
```

### `diplomat-tool` CLI
When running `diplomat-tool`, you may pass in the `--config` flag for each option you wish to set:

```
./diplomat-tool kotlin ./kotlin-folder --config lib_name="MyLibrary" --config kotlin.domain = "org.myOrganization"
```

`diplomat-tool` flags take priority over `config.toml`.

### `diplomat_tool::gen`

If you call `diplomat_tool::gen` manually, then you have the option of setting configuration yourself, with the `diplomat_tool::config::Config` struct.

See [Backend Structures](#backend-structures) for more on these structures.

### `#[diplomat::config(...)]`

In `lib.rs`, any top-level `mod`ule, `struct`, or `impl` block can use the `#[diplomat::config]` attribute:

```rust
#[diplomat::config(lib_name="MyLibrary")]
struct SomeConfig;

#[diplomat::config(kotlin.domain="org.myOrganization")]
mod kotlin_specific_mod;

#[diplomat::config(...)]
impl SomeConfig {

}
```

Due to a quirk of how Diplomat reads these attributes, `#[diplomat::config]` has priority over all other methods of setting configuration.
14 changes: 6 additions & 8 deletions book/src/demo_gen/markup.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
# Configuring Markup
Diplomat takes the `-l` or `--library-config` option (in `diplomat_tool::gen` this is the `library_config` parameter). This represents a path to a `.toml` file that demo_gen will then read and convert into `DemoConfig`.

Here's a sample .toml file for configuration (with comments for clarity):
Through [Diplomat's configuration interfaces](../config.md), you can customize some of demo_gen's output. Here's a sample .toml file for configuration (with comments for clarity):

```toml
# If false, demo_gen will automatically search all methods for functions it can generate demonstration JS for.
# If true, demo_gen will look for any methods explicitly flagged with #[diplomat::demo(generate)] to perform generation.
explicit-generation=true # default = false (bool)
explicit_generation=true # default = false (bool)

# This removes the rendering/ folder.
hide-default-renderer=true # default = false (bool)
hide_default_renderer=true # default = false (bool)

# Adjusts all imports that demo_gen creates to a specific module. Setting this will not generate the js/ folder.
#
# So for instance, this setting will adjust imports to: `import { type } from "icu4x";
module-name="icu4x" # (string)
module_name="icu4x" # (string)

# Adjusts all imports that demo_gen creates to a relative path where Diplomat JS output should be. Setting this will not generate the js/ folder.
#
# Setting this will adjust imports to: `import {type} from "../js/folder/here/index.mjs";
#
# Intended to be a mutually exclusive setting with module-name, although you can set both simultaneously to import modules from a relative path.
relative-js-path="../js/folder/here" # (string)
# Intended to be a mutually exclusive setting with module_name, although you can set both simultaneously to import modules from a relative path.
relative_js_path="../js/folder/here" # (string)
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
source: core/src/ast/attrs.rs
expression: attr
---
key_value_pairs:
- key: test.out
value: "24"
- key: other.out
value: test
- key: somefinal.out
value: "\"testing spaces\""
7 changes: 7 additions & 0 deletions example/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
lib-name = "somelib"

[kotlin]
domain = "dev.diplomattest"

[demo-gen]
relative-js-path = "../../js/lib/api/"
2 changes: 0 additions & 2 deletions example/diplomat-demo-conf.toml

This file was deleted.

2 changes: 0 additions & 2 deletions example/diplomat-kt-conf.toml

This file was deleted.

7 changes: 7 additions & 0 deletions feature_tests/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
lib-name = "This Will Be Ignored For Testing Purposes (Check src/lib.rs)"

[kotlin]
domain = "dev.diplomattest"

[demo-gen]
relative-js-path = "../../js/api/"
1 change: 0 additions & 1 deletion feature_tests/diplomat-demo-conf.toml

This file was deleted.

2 changes: 0 additions & 2 deletions feature_tests/diplomat-kt-conf.toml

This file was deleted.

7 changes: 7 additions & 0 deletions feature_tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
clippy::should_implement_trait
)]

#[diplomat::config(lib_name = "this is also a test value, see below")]
struct Config;

extern crate alloc;

pub mod attrs;
Expand All @@ -21,3 +24,7 @@ pub mod selftype;
pub mod slices;
pub mod structs;
pub mod traits;

// Feel free to add overrides for other languages for the lib_name, this is meant to showcase overriding SharedConfig.
#[diplomat::config(kotlin.lib_name = somelib)]
struct KotlinConfig;
11 changes: 11 additions & 0 deletions macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ impl AttributeInfo {
// diplomat::bridge doesn't read this, but it's handled separately
// as an attribute
return true;
} else if seg == "config" {
panic!("#[diplomat::config] is restricted to top level types in lib.rs.");
} else {
panic!("Only #[diplomat::opaque] and #[diplomat::rust_link] are supported: {:?}", seg)
}
Expand Down Expand Up @@ -608,6 +610,15 @@ pub fn bridge(
proc_macro::TokenStream::from(expanded.to_token_stream())
}

// Config is done in [`diplomat_tool::gen`], so we just set things to be ignored here.
#[proc_macro_attribute]
pub fn config(
_attr: proc_macro::TokenStream,
_input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
"".parse().unwrap()
}

/// Generate From and Into implementations for a Diplomat enum
///
/// This is invoked as `#[diplomat::enum_convert(OtherEnumName)]`
Expand Down
Loading

0 comments on commit a5f1514

Please sign in to comment.