Purpose: httpgen is the most complex generator with the widest annotation surface area. Migrating it first validates the shared package's API covers the most demanding use case. After this plan, httpgen has zero duplicated annotation parsing code.
Output: httpgen fully migrated to shared annotations, old annotations.go deleted, all tests passing.
<execution_context> @/Users/sebastienmelki/.claude/get-shit-done/workflows/execute-plan.md @/Users/sebastienmelki/.claude/get-shit-done/templates/summary.md </execution_context>
generator.go (6 call sites):
getMethodHTTPConfig(method)->annotations.GetMethodHTTPConfig(method)(lines ~790, ~810, ~819)- Where config.Method is used: no change needed (shared package returns uppercase, httpgen already uses uppercase)
- Where config.PathParams is used: no change needed (same type)
getServiceHTTPConfig(service)-> calls need adjustment: replacegetServiceHTTPConfig(service)withannotations.GetServiceBasePath(service)and use the returned string directly instead ofserviceConfig.BasePath. Look at line ~801 whereconfig := getServiceHTTPConfig(service)is called andconfig.BasePathis accessed -- replace withbasePath := annotations.GetServiceBasePath(service).getServiceHeaders(service)->annotations.GetServiceHeaders(service)(line ~1417)getMethodHeaders(method)->annotations.GetMethodHeaders(method)(line ~1436)getQueryParams(method.Input)->annotations.GetQueryParams(method.Input)(line ~1482)- IMPORTANT: httpgen's QueryParam only has FieldName, FieldGoName, ParamName, Required. The shared QueryParam has additional fields (FieldJSONName, FieldKind, Field). httpgen code accesses only the fields it needs, so this works without any extra changes. But verify every access pattern:
.FieldName,.FieldGoName,.ParamName,.Required-- all still valid.
- IMPORTANT: httpgen's QueryParam only has FieldName, FieldGoName, ParamName, Required. The shared QueryParam has additional fields (FieldJSONName, FieldKind, Field). httpgen code accesses only the fields it needs, so this works without any extra changes. But verify every access pattern:
getFieldExamples(field)->annotations.GetFieldExamples(field)(in mock_generator.go line ~69)lowerFirst(...)->annotations.LowerFirst(...)(line ~827 area -- but lowerFirst is also used extensively in generator.go for non-annotation purposes. Replace ALL occurrences.)- Remove
parseExistingAnnotationcall at line ~796 and replace with empty string or adjust the helper function that calls it. This is dead code (always returns "").
Also in generator.go: Remove the lowerFirst function definition (lines 827-832) and the parseExistingAnnotation usage. The function getPath at ~793 calls parseExistingAnnotation -- this always returns empty string, so just replace the body to return empty string directly, or remove the entire getPath function if it's only used in one place and inline the empty-string logic. Check all callers.
unwrap.go (5 call sites):
getUnwrapField(msg)->annotations.GetUnwrapField(msg)(lines ~90, ~136, ~178, ~252)- Type references:
*UnwrapFieldInfo->*annotations.UnwrapFieldInfo &UnwrapValidationError{...}-- this type is defined in annotations.go but the struct literal creation in unwrap.go should referenceannotations.UnwrapValidationErrorif needed. Check if unwrap.go creates anyUnwrapValidationErrordirectly or only receives them fromgetUnwrapField. (It only receives them --getUnwrapFieldreturns them.)UnwrapContextstruct references*UnwrapFieldInfoin its fields -- update to*annotations.UnwrapFieldInfo.GlobalUnwrapInfostruct'sUnwrapFieldsmap type:map[string]*UnwrapFieldInfo->map[string]*annotations.UnwrapFieldInfo
validation.go (2 call sites):
getMethodHTTPConfig(method)->annotations.GetMethodHTTPConfig(method)(line ~22)getQueryParams(method.Input)->annotations.GetQueryParams(method.Input)(line ~64)- The
getBodyFieldsfunction takes[]QueryParam-- update to[]annotations.QueryParam - The
ValidationErrorstruct stays local (it's httpgen-specific, not annotation-related)
mock_generator.go (1 call site):
getFieldExamples(field)->annotations.GetFieldExamples(field)(line ~69)
After ALL replacements, remove the HTTP method constants (httpMethodGET, etc.) from generator.go if they exist there (they're in annotations.go which will be deleted).
Run go build ./internal/httpgen/ after changes to verify compilation. Then run make lint-fix.
go build ./internal/httpgen/ compiles successfully.
go build ./cmd/protoc-gen-go-http/ compiles successfully.
make lint-fix produces no errors.
ALL of these are now in the shared package or removed (parseExistingAnnotation was dead code).
Delete internal/httpgen/annotations_test.go entirely (188 lines). The tests for pure functions (TestHttpMethodToString, TestExtractPathParams, benchmarks) were moved to the shared package in plan 02-01. The struct tests (TestHTTPConfig_Struct, TestQueryParam_Struct, TestServiceConfigImpl_Struct) tested local struct types that no longer exist -- equivalent tests exist in the shared package.
After deletion, verify:
go build ./internal/httpgen/still compiles (no missing references)go build ./cmd/protoc-gen-go-http/still compiles- Run
go test ./internal/httpgen/...-- all remaining tests pass - Run the golden file tests:
go test -v -run TestExhaustiveGoldenFiles ./internal/httpgen/...-- MUST pass with ZERO changes to golden files - Run
./scripts/run_tests.sh --fastfor full test suite - Run
make lint-fix
If any golden file test fails, the migration introduced a behavior change -- investigate and fix. The most likely causes:
- Missing import causing nil dereference
- QueryParam field name mismatch
- HTTP method case mismatch
Do NOT update golden files. If golden files need updating, the migration is wrong.
go build ./cmd/protoc-gen-go-http/ succeeds.
go test ./internal/httpgen/... all tests pass.
Golden file tests pass WITHOUT updating golden files.
./scripts/run_tests.sh --fast all tests pass.
ls internal/httpgen/annotations.go returns "No such file or directory".
ls internal/httpgen/annotations_test.go returns "No such file or directory".
make lint-fix clean.
<success_criteria>
- httpgen/annotations.go deleted (392 lines removed)
- httpgen/annotations_test.go deleted (188 lines removed)
- All httpgen source files import internal/annotations
- All golden file tests pass unchanged
- Full test suite passes
- Zero behavior change </success_criteria>
