src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

AGENTS.md (6765B)


      1 # AGENTS.md
      2 
      3 ## Project overview
      4 
      5 smithy-go is the Go code generator and runtime for [Smithy](https://smithy.io/).
      6 It has two major components:
      7 
      8 1. **Codegen** (`codegen/`) — A Smithy build plugin written in Java that
      9    generates Go client/server/shape code from Smithy models.
     10 2. **Runtime** (`./`, top-level Go module) — The Go packages that generated
     11    code depends on at runtime.
     12 
     13 The primary downstream consumer is
     14 [aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2).
     15 
     16 ## Repository layout
     17 
     18 ```
     19 .                               # Root Go module (github.com/aws/smithy-go)
     20 ├── auth/                       # Auth identity + scheme interfaces
     21 │   └── bearer/                 # Bearer token auth
     22 ├── aws-http-auth/              # Separate module: AWS SigV4/SigV4A HTTP signing
     23 ├── codegen/                    # Java/Gradle: Smithy code generator
     24 │   ├── smithy-go-codegen/      # Main codegen source (Java)
     25 │   └── smithy-go-codegen-test/ # Codegen integration tests
     26 ├── container/                  # Generic container types
     27 ├── context/                    # Context helpers
     28 ├── document/                   # Smithy document type abstraction
     29 │   └── json/                   # JSON document codec
     30 ├── encoding/                   # Wire format encoders/decoders
     31 │   ├── cbor/                   # CBOR (used by rpcv2Cbor)
     32 │   ├── httpbinding/            # HTTP binding serde helpers
     33 │   ├── json/                   # JSON encoder/decoder
     34 │   └── xml/                    # XML encoder/decoder
     35 ├── endpoints/                  # Endpoint resolution types
     36 ├── internal/                   # Internal utilities (singleflight, etc.)
     37 ├── io/                         # I/O helpers
     38 ├── logging/                    # Logging interfaces
     39 ├── metrics/                    # Metrics interfaces
     40 │   └── smithyotelmetrics/      # Separate module: OpenTelemetry metrics adapter
     41 ├── middleware/                 # Middleware stack (the core of the operation pipeline)
     42 ├── ptr/                        # Pointer-to/from-value helpers
     43 ├── testing/                    # Test assertion helpers for generated protocol tests
     44 │   └── xml/                    # XML comparison utilities
     45 ├── time/                       # Smithy timestamp format helpers
     46 ├── tracing/                    # Tracing interfaces
     47 │   └── smithyoteltracing/      # Separate module: OpenTelemetry tracing adapter
     48 └── transport/
     49     └── http/                   # HTTP request/response types and middleware
     50 ```
     51 
     52 ## Building and testing
     53 
     54 ### Runtime (Go)
     55 
     56 ```bash
     57 # Run unit tests
     58 make unit
     59 ```
     60 
     61 ### Codegen (Java)
     62 
     63 ```bash
     64 # Build and test codegen
     65 cd codegen && ./gradlew build
     66 
     67 # Publish to local Maven for downstream use
     68 cd codegen && ./gradlew publishToMavenLocal
     69 ```
     70 
     71 The codegen artifact version is published to Maven Central and bumped on each
     72 release. For local development against unreleased codegen changes, use
     73 `publishToMavenLocal` and point consumers at `mavenLocal()`.
     74 
     75 ## Runtime architecture
     76 
     77 ### Middleware stack
     78 
     79 The operation pipeline is built on a middleware stack defined in `middleware/`.
     80 Steps execute in order: Initialize → Serialize → Build → Finalize →
     81 Deserialize. Each step is a `middleware.Step` that holds an ordered list of
     82 middleware. The codegen generates middleware registrations for each operation.
     83 
     84 ### Encoding packages
     85 
     86 Each wire format has its own encoder/decoder under `encoding/`. These are
     87 low-level — they produce/consume raw tokens or values, not full Smithy shapes.
     88 Generated serde code calls into these packages.
     89 
     90 ## Codegen: GoWriter and template system
     91 
     92 GoWriter extends Smithy's `SymbolWriter` and is the primary mechanism for
     93 generating Go source. It has **two distinct writing styles** that must not be
     94 confused.
     95 
     96 ### Style 1: Positional args (`writer.write` / `writer.openBlock`)
     97 
     98 Inherited from `SymbolWriter`. Arguments are positional and referenced with
     99 `$`-prefixed format characters. Each `$X` consumes the next argument in order.
    100 
    101 Format characters:
    102 - `$L` — Literal (toString). Strings, names, anything that should be inserted
    103   verbatim.
    104 - `$S` — String, quoted. Wraps the value in Go double-quotes.
    105 - `$T` — Type (Symbol). Inserts the symbol name and auto-adds its import.
    106 - `$P` — Pointable type (Symbol). Like `$T` but prepends `*` if the symbol is
    107   marked pointable.
    108 - `$W` — Writable. Evaluates a `Writable` (lambda/closure) inline.
    109 - `$D` — Dependency. Adds a `GoDependency` import, expands to empty string.
    110 
    111 Numbered variants (`$1L`, `$2T`, etc.) allow reusing the same argument
    112 multiple times. The number is 1-indexed and refers to the position in the
    113 argument list:
    114 
    115 ```java
    116 // $1L is used twice, $2L once — only 2 args needed
    117 writer.write("type $1L struct{}\nvar _ $2L = (*$1L)(nil)",
    118     DEFAULT_NAME, INTERFACE_NAME);
    119 ```
    120 
    121 `openBlock`/`closeBlock` manage indentation for braced blocks. Arguments are
    122 positional:
    123 
    124 ```java
    125 writer.openBlock("func (c $P) $T(ctx $T) ($P, error) {", "}",
    126     serviceSymbol, operationSymbol, contextSymbol, outputSymbol,
    127     () -> {
    128         writer.write("return nil, nil");
    129     });
    130 ```
    131 
    132 ### Style 2: Named template args (`goTemplate` / `writeGoTemplate`)
    133 
    134 Uses `$name:X` syntax where `name` is a key in a `Map<String, Object>` and `X`
    135 is the format character. Arguments are passed as one or more maps. This is the
    136 **preferred style for new code** — it is more readable and less error-prone
    137 than positional args.
    138 
    139 ```java
    140 return goTemplate("""
    141     func $name:L(v $cborValue:T) ($type:T, error) {
    142         return $coercer:T(v)
    143     }
    144     """,
    145     Map.of(
    146         "name", getDeserializerName(shape),
    147         "cborValue", SmithyGoTypes.Encoding.Cbor.Value,
    148         "type", symbolProvider.toSymbol(shape),
    149         "coercer", coercer
    150     ));
    151 ```
    152 
    153 Rules:
    154 - `goTemplate(String, Map...)` is a **static** method that returns a
    155   `Writable` (a `Consumer<GoWriter>` lambda). It does NOT write immediately.
    156 - `writeGoTemplate(String, Map...)` is an **instance** method that writes
    157   immediately to the writer.
    158 - Maps are merged into the writer's context scope for the duration of the
    159   template. Multiple maps can be passed and are applied in order.
    160 - The writer pre-populates common symbols in context: `fmt.Sprintf`,
    161   `fmt.Errorf`, `errors.As`, `context.Context`, `time.Now`.
    162 
    163 ### Composing writables
    164 
    165 - `ChainWritable` — Collects multiple `Writable`s and composes them with
    166   newlines between each. Use `.compose()` (with newlines) or
    167   `.compose(false)` (without).
    168 
    169 ### Symbol constants
    170 
    171 For symbols, use `SmithyGoDependency.*.valueSymbol("Name")` or
    172 `SmithyGoDependency.*.pointableSymbol("Name")`.
    173