func checkTag(comments []string, require ...string) bool { values := types.ExtractCommentTags("+", comments)[tagName] if len(require) == 0 { return len(values) == 1 && values[0] == "" } return reflect.DeepEqual(values, require) }
// hasOptionalTag returns true if the member has +optional in its comments or // omitempty in its json tags. func hasOptionalTag(m *types.Member) bool { hasOptionalCommentTag := types.ExtractCommentTags( "+", m.CommentLines)[tagOptional] != nil hasOptionalJsonTag := strings.Contains( reflect.StructTag(m.Tags).Get("json"), "omitempty") return hasOptionalCommentTag || hasOptionalJsonTag }
func hasOpenAPITagValue(comments []string, value string) bool { tagValues := types.ExtractCommentTags("+", comments)[tagName] if tagValues == nil { return false } for _, val := range tagValues { if val == value { return true } } return false }
// Filter ignores types that are identified as not exportable. func (g *genProtoIDL) Filter(c *generator.Context, t *types.Type) bool { tagVals := types.ExtractCommentTags("+", t.CommentLines)["protobuf"] if tagVals != nil { if tagVals[0] == "false" { // Type specified "false". return false } if tagVals[0] == "true" { // Type specified "true". return true } glog.Fatalf(`Comment tag "protobuf" must be true or false, found: %q`, tagVals[0]) } if !g.generateAll { // We're not generating everything. return false } seen := map[*types.Type]bool{} ok := isProtoable(seen, t) return ok }
func extractTag(comments []string) *tagValue { tagVals := types.ExtractCommentTags("+", comments)[tagName] if tagVals == nil { // No match for the tag. return nil } // If there are multiple values, abort. if len(tagVals) > 1 { glog.Fatalf("Found %d %s tags: %q", len(tagVals), tagName, tagVals) } // If we got here we are returning something. tag := &tagValue{} // Get the primary value. parts := strings.Split(tagVals[0], ",") if len(parts) >= 1 { tag.value = parts[0] } // Parse extra arguments. parts = parts[1:] for i := range parts { kv := strings.SplitN(parts[i], "=", 2) k := kv[0] v := "" if len(kv) == 2 { v = kv[1] } switch k { case "register": if v != "false" { tag.register = true } default: glog.Fatalf("Unsupported %s param: %q", tagName, parts[i]) } } return tag }
func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") const pkgRESTClient = "k8s.io/kubernetes/pkg/client/restclient" const pkgRegistered = "k8s.io/kubernetes/pkg/apimachinery/registered" const pkgAPI = "k8s.io/kubernetes/pkg/api" const pkgSerializer = "k8s.io/kubernetes/pkg/runtime/serializer" apiPath := func(group string) string { if len(g.apiPath) > 0 { return `"` + g.apiPath + `"` } if group == "core" { return `"/api"` } return `"/apis"` } groupName := g.group if g.group == "core" { groupName = "" } // allow user to define a group name that's different from the one parsed from the directory. p := c.Universe.Package(g.inputPacakge) if override := types.ExtractCommentTags("+", p.DocComments)["groupName"]; override != nil { groupName = override[0] } m := map[string]interface{}{ "group": normalization.BeforeFirstDot(g.group), "Group": namer.IC(normalization.BeforeFirstDot(g.group)), "groupName": groupName, "types": g.types, "Config": c.Universe.Type(types.Name{Package: pkgRESTClient, Name: "Config"}), "DefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: pkgRESTClient, Name: "DefaultKubernetesUserAgent"}), "RESTClientInterface": c.Universe.Type(types.Name{Package: pkgRESTClient, Name: "Interface"}), "RESTClientFor": c.Universe.Function(types.Name{Package: pkgRESTClient, Name: "RESTClientFor"}), "latestGroup": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "Group"}), "GroupOrDie": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "GroupOrDie"}), "apiPath": apiPath(g.group), "codecs": c.Universe.Variable(types.Name{Package: pkgAPI, Name: "Codecs"}), "directCodecFactory": c.Universe.Variable(types.Name{Package: pkgSerializer, Name: "DirectCodecFactory"}), "Errorf": c.Universe.Variable(types.Name{Package: "fmt", Name: "Errorf"}), } sw.Do(groupInterfaceTemplate, m) sw.Do(groupClientTemplate, m) for _, t := range g.types { wrapper := map[string]interface{}{ "type": t, "Group": namer.IC(normalization.BeforeFirstDot(g.group)), } namespaced := !extractBoolTagOrDie("nonNamespaced", t.SecondClosestCommentLines) if namespaced { sw.Do(getterImplNamespaced, wrapper) } else { sw.Do(getterImplNonNamespaced, wrapper) } } sw.Do(newClientForConfigTemplate, m) sw.Do(newClientForConfigOrDieTemplate, m) sw.Do(newClientForRESTClientTemplate, m) if g.version == "unversioned" { sw.Do(setInternalVersionClientDefaultsTemplate, m) } else { sw.Do(setClientDefaultsTemplate, m) } sw.Do(getRESTClient, m) return sw.Error() }
func hasOptionalTag(comments []string) bool { tagValues := types.ExtractCommentTags("+", comments)[tagOptional] return tagValues != nil }
// GenerateType makes the body of a file implementing the individual typed client for type t. func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") pkg := filepath.Base(t.Name.Package) const pkgTestingCore = "k8s.io/kubernetes/pkg/client/testing/core" namespaced := !extractBoolTagOrDie("nonNamespaced", t.SecondClosestCommentLines) canonicalGroup := g.group if canonicalGroup == "core" { canonicalGroup = "" } groupName := g.group if g.group == "core" { groupName = "" } // allow user to define a group name that's different from the one parsed from the directory. p := c.Universe.Package(g.inputPackage) if override := types.ExtractCommentTags("+", p.DocComments)["groupName"]; override != nil { groupName = override[0] } m := map[string]interface{}{ "type": t, "package": pkg, "Package": namer.IC(pkg), "namespaced": namespaced, "Group": namer.IC(g.group), "GroupVersion": namer.IC(g.group) + namer.IC(g.version), "group": canonicalGroup, "groupName": groupName, "version": g.version, "watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/watch", Name: "Interface"}), "GroupVersionResource": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/runtime/schema", Name: "GroupVersionResource"}), "PatchType": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "PatchType"}), "Everything": c.Universe.Function(types.Name{Package: "k8s.io/kubernetes/pkg/labels", Name: "Everything"}), "NewRootListAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootListAction"}), "NewListAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewListAction"}), "NewRootGetAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootGetAction"}), "NewGetAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewGetAction"}), "NewRootDeleteAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootDeleteAction"}), "NewDeleteAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewDeleteAction"}), "NewRootDeleteCollectionAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootDeleteCollectionAction"}), "NewDeleteCollectionAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewDeleteCollectionAction"}), "NewRootUpdateAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootUpdateAction"}), "NewUpdateAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewUpdateAction"}), "NewRootCreateAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootCreateAction"}), "NewCreateAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewCreateAction"}), "NewRootWatchAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootWatchAction"}), "NewWatchAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewWatchAction"}), "NewUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewUpdateSubresourceAction"}), "NewRootUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootUpdateSubresourceAction"}), "NewRootPatchAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootPatchAction"}), "NewPatchAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewPatchAction"}), "NewRootPatchSubresourceAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootPatchSubresourceAction"}), "NewPatchSubresourceAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewPatchSubresourceAction"}), "ExtractFromListOptions": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "ExtractFromListOptions"}), } if g.version == "" { m["DeleteOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "DeleteOptions"}) m["ListOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "ListOptions"}) } else { m["DeleteOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api/v1", Name: "DeleteOptions"}) m["ListOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api/v1", Name: "ListOptions"}) } m["GetOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/apis/meta/v1", Name: "GetOptions"}) noMethods := extractBoolTagOrDie("noMethods", t.SecondClosestCommentLines) == true if namespaced { sw.Do(structNamespaced, m) } else { sw.Do(structNonNamespaced, m) } if !noMethods { sw.Do(resource, m) sw.Do(createTemplate, m) sw.Do(updateTemplate, m) // Generate the UpdateStatus method if the type has a status if genStatus(t) { sw.Do(updateStatusTemplate, m) } sw.Do(deleteTemplate, m) sw.Do(deleteCollectionTemplate, m) sw.Do(getTemplate, m) if hasObjectMeta(t) { sw.Do(listUsingOptionsTemplate, m) } else { sw.Do(listTemplate, m) } sw.Do(watchTemplate, m) sw.Do(patchTemplate, m) } return sw.Error() }
func extractTag(comments []string) []string { return types.ExtractCommentTags("+", comments)[tagName] }
func (b bodyGen) doStruct(sw *generator.SnippetWriter) error { if len(b.t.Name.Name) == 0 { return nil } if namer.IsPrivateGoName(b.t.Name.Name) { return nil } var alias *types.Type var fields []protoField options := []string{} allOptions := types.ExtractCommentTags("+", b.t.CommentLines) for k, v := range allOptions { switch { case strings.HasPrefix(k, "protobuf.options."): key := strings.TrimPrefix(k, "protobuf.options.") switch key { case "marshal": if v[0] == "false" { if !b.omitGogo { options = append(options, "(gogoproto.marshaler) = false", "(gogoproto.unmarshaler) = false", "(gogoproto.sizer) = false", ) } } default: if !b.omitGogo || !strings.HasPrefix(key, "(gogoproto.") { if key == "(gogoproto.goproto_stringer)" && v[0] == "false" { options = append(options, "(gogoproto.stringer) = false") } options = append(options, fmt.Sprintf("%s = %s", key, v[0])) } } // protobuf.as allows a type to have the same message contents as another Go type case k == "protobuf.as": fields = nil if alias = b.locator.GoTypeForName(types.Name{Name: v[0]}); alias == nil { return fmt.Errorf("type %v references alias %q which does not exist", b.t, v[0]) } // protobuf.embed instructs the generator to use the named type in this package // as an embedded message. case k == "protobuf.embed": fields = []protoField{ { Tag: 1, Name: v[0], Type: &types.Type{ Name: types.Name{ Name: v[0], Package: b.localPackage.Package, Path: b.localPackage.Path, }, }, }, } } } if alias == nil { alias = b.t } // If we don't explicitly embed anything, generate fields by traversing fields. if fields == nil { memberFields, err := membersToFields(b.locator, alias, b.localPackage, b.omitFieldTypes) if err != nil { return fmt.Errorf("type %v cannot be converted to protobuf: %v", b.t, err) } fields = memberFields } out := sw.Out() genComment(out, b.t.CommentLines, "") sw.Do(`message $.Name.Name$ { `, b.t) if len(options) > 0 { sort.Sort(sort.StringSlice(options)) for _, s := range options { fmt.Fprintf(out, " option %s;\n", s) } fmt.Fprintln(out) } for i, field := range fields { genComment(out, field.CommentLines, " ") fmt.Fprintf(out, " ") switch { case field.Map: case field.Repeated: fmt.Fprintf(out, "repeated ") case field.Required: fmt.Fprintf(out, "required ") default: fmt.Fprintf(out, "optional ") } sw.Do(`$.Type|local$ $.Name$ = $.Tag$`, field) if len(field.Extras) > 0 { extras := []string{} for k, v := range field.Extras { if b.omitGogo && strings.HasPrefix(k, "(gogoproto.") { continue } extras = append(extras, fmt.Sprintf("%s = %s", k, v)) } sort.Sort(sort.StringSlice(extras)) if len(extras) > 0 { fmt.Fprintf(out, " [") fmt.Fprint(out, strings.Join(extras, ", ")) fmt.Fprintf(out, "]") } } fmt.Fprintf(out, ";\n") if i != len(fields)-1 { fmt.Fprintf(out, "\n") } } fmt.Fprintf(out, "}\n\n") return nil }