| // Copyright 2024 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package protodetecttypes identifies static types (go/types, typically |
| // obtained at build time) generated by protoc-gen-go. The protodetectreflect |
| // package is the counterpart for dynamic types (reflect, obtained at runtime). |
| package protodetecttypes |
| |
| import ( |
| "go/types" |
| "reflect" |
| "strings" |
| ) |
| |
| // Type represents a go/types.Type obtained at build time. |
| type Type struct{ T types.Type } |
| |
| // IsMessage reports whether t is a generated message. |
| func (t Type) IsMessage() bool { |
| return t.MessageAPI() != Invalid |
| } |
| |
| // MessageAPI determines the API of the generated message. |
| func (t Type) MessageAPI() MessageAPI { |
| if t, ok := t.T.Underlying().(*types.Struct); ok && t.NumFields() > 0 { |
| return determineAPI(reflect.StructTag(t.Tag(0))) |
| } |
| return Invalid |
| } |
| |
| // MessageAPI determines which API is used for the generated message type. |
| type MessageAPI int |
| |
| const ( |
| // Invalid indicates the specified type is not a proto message. |
| Invalid MessageAPI = iota |
| |
| // OpenAPI indicates a message generated in the open struct API, |
| // where the message representation is a Go struct with exported fields. |
| OpenAPI |
| |
| // HybridAPI indicates a message generated in the hybrid API, |
| // where the message has properties of both OpenAPI and OpaqueAPI. |
| HybridAPI |
| |
| // OpaqueAPI indicates a message generated in the opaque API, |
| // where the message can only be interacted with through accessor methods. |
| OpaqueAPI |
| ) |
| |
| // DetermineAPI determines the message API from a magic struct tag that |
| // protoc-gen-go emits for all messages. |
| func determineAPI(tag reflect.StructTag) MessageAPI { |
| switch s := tag.Get("protogen"); { |
| case strings.HasPrefix(s, "open."): |
| return OpenAPI |
| case strings.HasPrefix(s, "hybrid."): |
| return HybridAPI |
| case strings.HasPrefix(s, "opaque."): |
| return OpaqueAPI |
| default: |
| return Invalid |
| } |
| } |