Fix shared type generation, external union conversions, and gRPC clients - #4010
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Goa could choose different Go packages or names for the same reused type, omit imports needed by generated conversions, and fail to preserve valid values across transport conversions. This change makes the complete generation choose shared type ownership and keeps declarations, imports, and their callers on that decision.
A type placed with
struct:pkg:pathnow supplies the package for its unlocated authored descendants. An explicitly located child retains its own package and supplies it to its descendants. Ambiguous ownership and required generated-package import cycles fail before source emission. Imported design declarations are not annotated or mutated. Plugins can query the retained original attribute and Go layout withservice.Plan.UserTypeLayout, and register imports for either a complete value or just its type reference throughGeneratedImportPlan.HTTP conversion helpers now retain the complete source and target layouts selected by the enclosing conversion. When one inline union is reused beneath two generated owners, each helper uses that owner's actual declaration and constructor.
TransformPlan.HelperLayoutsselects those existing layouts by helper ID; it rejects a mismatched root or path.GoTypePlan.PreferredImportNameexposes the planned package-name preference before import aliases become final. HTTP uses that preference with the selected owner; gRPC distinguishes imports needed only for a named reference from imports needed by a complete conversion. Copied built-in errors retaingoa.ServiceErrorand its complete field layout, so generated HTTP clients construct the declared error type. These queries do not add design annotations or runtime lookup.HTTP and JSON-RPC mapped fields now use the same names and requiredness in declarations and conversion planning. For example,
detail:messagekeeps service fieldDetailand body fieldMessage, with requiredness and defaults belonging todetail. The HTTP planner enables the newGoTypePlanOptions.MappedFieldsoption; ordinary service planning keeps its existing behavior. Existing keyed options literals remain valid. Generator plugins using positional literals must change them to keyed literals. The JSON body, error envelope and validation contract are unchanged.ConvertToandCreateFromuse authoredOneOfbranches and external unions' publicKind,AsX, andSetXmethods. Planning checks the method and type contracts; emitted conversions preserve exact external named scalar and collection types, including nested and optional values. Conversions that would have to name an inaccessible external Go type now fail during planning, with the type, location and direction in the error. Legal read-only conversions keep private scalar and collection-entry values when generated code does not need to name their types. This reuses the existing transform and package-name plans and does not inspect private union storage.Generated HTTP headers use the underlying scalar kind for chained aliases while keeping the named service type and inherited validation. Generated protobuf-to-service conversions construct empty required arrays and maps after the wire discards collection presence; required JSON properties and singular protobuf presence retain their validation. Generated gRPC clients keep a stream after initial-send EOF so Recv or CloseAndRecv can read the server status. Stream opening also avoids the invoker's unary metadata capture options, while preserving caller-provided options and asynchronous opening.
Regenerate the complete generated tree with the updated Goa module and generator. Shared child declarations may move packages, so update handwritten Go imports and direct generated-type references where needed. This adds generator APIs but no DSL API, runtime mode, dependency, protobuf field/tag change, or persisted-data migration. These corrections do not require a coordinated server/client rollout. Restore the prior generator/module, design and generated tree together to roll back. Review
package_placement.go, the retained import and helper-layout operations,http/codegen/wire_catalog.go, external conversion planning, HTTP alias shaping, and the two gRPC template changes first.Final focused checks passed: external accessibility and readable-value controls (5 tests/19 subtests), external union and conversion preservation (6 tests/37 subtests), the generated direct/recursive collection transport fixture, and repository lint. The collection fixture compiles generated services and transports, crosses actual protobuf bytes in both directions, and retains required JSON, scalar/message presence, length and element checks. A separate baseline reproduced all five inaccessible-name compiler failures before the correction; the legal read-only controls passed before and after it. The unchanged original HTTP/gRPC/JSON-RPC relocation compilation test also passes. Final focused checks pass all ten enclosing-owner/constructor/roundtrip cases and forty built-in/custom-error, client-output and type-layout cases. The final complete core-codegen, HTTP and generator package run passes 2,160 tests/subtests. The complete JSON-RPC package passes 106 tests/subtests, with its existing optional check skipped; the original designed-error runtime test and all goldens remain unchanged. The mapped-field controls add 16 passing cases covering required/default/pointer rules, explicit names, shared children, recursion and all four HTTP request/response directions. The gRPC package passed the earlier broader run. Full CI results for the updated PR head are pending.