Skip to content

Commit 6d64a5a

Browse files
authored
Merge pull request #11 from mkpro118/create-compiler-macros-crate
Add compiler-macros with AstLeafNode, AstContainerNode, EnumKindName
2 parents ac59281 + 9b8367c commit 6d64a5a

File tree

9 files changed

+386
-2
lines changed

9 files changed

+386
-2
lines changed

.clippy.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
allow-expect-in-tests = true
2+
allow-unwrap-in-tests = true

.gitignore

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,16 @@
1-
/target
1+
# Generated by Cargo
2+
# will have compiled files and executables
3+
**/debug
4+
**/target
5+
6+
# These are backup files generated by rustfmt
7+
**/*.rs.bk
8+
9+
# MSVC Windows builds of rustc generate these, which store debugging information
10+
*.pdb
11+
12+
# Generated by cargo mutants
13+
# Contains mutation testing data
14+
**/mutants.out*/
15+
16+
.cov

Cargo.lock

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ version = "0.1.0"
44
edition = "2024"
55

66
[dependencies]
7+
compiler-macros = { path = "./compiler_macros" }

compiler_macros/Cargo.lock

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler_macros/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "compiler-macros"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[lib]
7+
proc-macro = true
8+
9+
[dependencies]
10+
proc-macro2 = "1.0"
11+
quote = "1.0"
12+
syn = { version = "2.0", features = ["full"] }

compiler_macros/prd.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Simple Builder Proc-Macro PRD
2+
3+
## 1. Objective
4+
5+
To provide a simple and ergonomic solution for creating builder patterns in Rust. This proc-macro will automate the generation of a basic builder, reducing boilerplate code for simple use cases.
6+
7+
## 2. Background
8+
9+
The builder pattern is a useful way to construct complex objects. However, writing the builder struct and its methods can be tedious. This proc-macro automates the creation of a simple builder.
10+
11+
## 3. User Persona
12+
13+
This tool is for Rust developers who want a quick and easy way to create a builder for their structs without the complexity of a full type-state implementation.
14+
15+
## 4. API Definition
16+
17+
The public API will consist of a single derive macro:
18+
19+
```rust
20+
use simple_builder::SimpleBuilder;
21+
22+
#[derive(SimpleBuilder, Default)]
23+
#[builder_name = "MyCustomBuilderName"] // Optional: to rename the builder struct
24+
pub struct MyStruct {
25+
// ... fields
26+
}
27+
```
28+
29+
- `#[derive(SimpleBuilder)]`: The main entry point. It will trigger the builder generation.
30+
- `#[builder_name = "..."]` (optional attribute): Allows the user to specify a custom name for the generated builder struct. If not provided, it will default to `[StructName]Builder`.
31+
32+
### Constraints
33+
34+
- The target struct **must** implement the `Default` trait.
35+
36+
## 5. Requirements & Features
37+
38+
### 5.1. "With Defaults" Builder Logic
39+
40+
The builder will follow a "with defaults" strategy. This means:
41+
42+
- The `build()` method can be called at any time.
43+
- If a field has been set using its `with_...` method, the builder will use that value.
44+
- If a field has not been set, the builder will use the value from the struct's `Default` implementation.
45+
46+
### 5.2. Generated Code
47+
48+
The macro will generate:
49+
50+
1. A public `...Builder` struct with `Option` fields.
51+
2. A `new()` method to create an empty builder.
52+
3. A `with_<field_name>()` method for each field in the target struct.
53+
4. A `build()` method that constructs the target struct, intelligently combining user-provided values with default values.
54+
55+
## 6. Acceptance Criteria
56+
57+
To consider this feature complete and correct, the following criteria must be met:
58+
59+
1. **Compilation:** A struct decorated with `#[derive(SimpleBuilder, Default)]` must compile successfully.
60+
2. **Builder Generation:** The corresponding `...Builder` struct must be generated and be publicly accessible.
61+
3. **`new()` Method:** The `...Builder::new()` method must exist and return a new builder instance.
62+
4. **`with_...` Methods:** Each field in the target struct must have a corresponding `with_<field_name>()` method on the builder.
63+
5. **`build()` Method:** The `build()` method must be callable on the builder at any time.
64+
6. **Correctness (Set Fields):** When a field is set via its `with_...` method, the `build()` method must produce a struct with that exact value for that field.
65+
7. **Correctness (Unset Fields):** When a field is not set, the `build()` method must produce a struct where that field has the value from the `Default` implementation.
66+
67+
## 7. Out of Scope (Future Work)
68+
69+
- **Type-State Builder:** A more advanced builder that uses the type-state pattern to enforce compile-time correctness.
70+
- **Generic Structs:** Support for structs with generic parameters.
71+
- **Required Fields:** An attribute to mark certain fields as required.
72+
- **Validation:** Adding validation logic to the `build()` method.

0 commit comments

Comments
 (0)