1// Protocol Buffers for Go with Gadgets 2// 3// Copyright (c) 2013, The GoGo Authors. All rights reserved. 4// http://github.com/gogo/protobuf 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: 9// 10// * Redistributions of source code must retain the above copyright 11// notice, this list of conditions and the following disclaimer. 12// * Redistributions in binary form must reproduce the above 13// copyright notice, this list of conditions and the following disclaimer 14// in the documentation and/or other materials provided with the 15// distribution. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29/* 30The oneofcheck plugin is used to check whether oneof is not used incorrectly. 31For instance: 32An error is caused if a oneof field: 33 - is used in a face 34 - is an embedded field 35 36*/ 37package oneofcheck 38 39import ( 40 "fmt" 41 "github.com/gogo/protobuf/gogoproto" 42 "github.com/gogo/protobuf/protoc-gen-gogo/generator" 43 "os" 44) 45 46type plugin struct { 47 *generator.Generator 48} 49 50func NewPlugin() *plugin { 51 return &plugin{} 52} 53 54func (p *plugin) Name() string { 55 return "oneofcheck" 56} 57 58func (p *plugin) Init(g *generator.Generator) { 59 p.Generator = g 60} 61 62func (p *plugin) Generate(file *generator.FileDescriptor) { 63 for _, msg := range file.Messages() { 64 face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto) 65 for _, field := range msg.GetField() { 66 if field.OneofIndex == nil { 67 continue 68 } 69 if face { 70 fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in a face and oneof\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name)) 71 os.Exit(1) 72 } 73 if gogoproto.IsEmbed(field) { 74 fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and an embedded field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name)) 75 os.Exit(1) 76 } 77 if !gogoproto.IsNullable(field) { 78 fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and a non-nullable field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name)) 79 os.Exit(1) 80 } 81 if gogoproto.IsUnion(file.FileDescriptorProto, msg.DescriptorProto) { 82 fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and in an union (deprecated)\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name)) 83 os.Exit(1) 84 } 85 } 86 } 87} 88 89func (p *plugin) GenerateImports(*generator.FileDescriptor) {} 90 91func init() { 92 generator.RegisterPlugin(NewPlugin()) 93} 94