Documentation
¶
Overview ¶
Package idents holds the Go-identifier conversion helpers used by both the semantic analyser and the codegen pass. Keeping it here - instead of inside codegen - lets semantic detect "user_id and userId map to the same Go field name" collisions during analysis without pulling in the rest of codegen.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var BuiltinTypes = map[string]bool{ "string": true, "bool": true, "int": true, "int8": true, "int16": true, "int32": true, "int64": true, "uint": true, "uint8": true, "uint16": true, "uint32": true, "uint64": true, "float32": true, "float64": true, "bytes": true, "any": true, "object": true, "file": true, }
BuiltinTypes is the closed set of primitive type spellings the DSL recognises out of the box. The semantic resolver, codegen, and the parser's disambiguation rules all consult it, so the table lives here in a transport-neutral package - adding a new primitive happens once, every consumer picks it up. `object` is the permissive bag-of-fields used inside `@example({...})`; `file` is the upload-only marker that codegen maps to `*multipart.FileHeader`.
Prefer the IsBuiltin / IsWireParseable helpers over reading this map directly so the predicates stay consistent across the 4+ call sites that previously duplicated the list inline.
Functions ¶
func GoFieldName ¶
GoFieldName converts a DSL field name (which is allowed to be lowercase, snake_case, or camelCase) into an exported Go identifier applying the common-initialism rule.
Hot path (called per field across codegen + collision detection): Builder keeps the per-part append allocation-free.
func IsBuiltin ¶
IsBuiltin reports whether name is one of the DSL's built-in type spellings (every entry in BuiltinTypes). Use this in code that has to differentiate "user-declared type" from "builtin" - codegen import resolution and semantic ref classification both reach for it.
func IsWireParseable ¶
IsWireParseable reports whether name is a primitive the wire-string binders (`@query`, `@header`, `@cookie`, `@form`) can parse from a single string. Excludes `bytes` / `any` / `object` / `file` - those need their own wire format. Mirrors the codegen's `queryPrims` table so semantic-time and gen-time rejections stay in sync without two hardcoded lists.
func SplitFieldName ¶
SplitFieldName breaks a name into word components on `_`, `-`, and camelCase boundaries. Consecutive uppercase letters are kept together as a single acronym word (so `DBError` → `["DB", "Error"]` and `HTTPRequest` → `["HTTP", "Request"]`); a new word starts whenever an uppercase letter follows a lowercase letter, OR when an uppercase letter sits between two other uppercase letters and is followed by a lowercase letter (the "acronym ends here" boundary).
Exported so callers outside this package (codegen path / error helpers) can derive their own kebab / snake forms without duplicating the boundary logic.
Types ¶
type Collision ¶
type Collision struct {
// DSLNames are the DSL spellings, in source order, that all
// converted to the same canonical Go identifier.
DSLNames []string
// CanonicalGoName is the Go identifier the first DSL name maps
// to - the "winner" that keeps its bare spelling.
CanonicalGoName string
// ResolvedGoNames pairs each DSLName index with the Go
// identifier emitted in the generated struct: index 0 is the
// canonical name; indices ≥ 1 carry the `_N` disambiguator.
ResolvedGoNames []string
}
Collision records one DSL → Go-identifier mapping inside a group of names that produced the same Go identifier under GoFieldName. The first occurrence keeps the bare Go name; subsequent ones are suffixed `_2`, `_3`, ... so the resulting struct compiles. Both the original and the resolved Go names are returned so callers (semantic warnings + codegen) stay consistent on what spelling each DSL name maps to in the emitted struct.
func DedupGoFieldNames ¶
DedupGoFieldNames takes the DSL field names of a single struct in source order and returns:
- resolved: the Go identifiers to emit in the struct, with `_N` suffixes appended to any duplicate beyond the first occurrence.
- collisions: one Collision per group whose size is > 1, in source-order of the first occurrence. Empty when the struct is collision-free, which is the overwhelming common case.
The dedup keeps the first DSL spelling at its bare Go name so a project that adds a colliding alias later doesn't retroactively rename the original field — generated code stays stable for already-published struct shapes.