...

Source file src/go.einride.tech/aip/cmd/protoc-gen-go-aip/internal/genaip/plugin.go

Documentation: go.einride.tech/aip/cmd/protoc-gen-go-aip/internal/genaip

     1  package genaip
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"google.golang.org/genproto/googleapis/api/annotations"
     7  	"google.golang.org/protobuf/compiler/protogen"
     8  	"google.golang.org/protobuf/proto"
     9  	"google.golang.org/protobuf/reflect/protoreflect"
    10  	"google.golang.org/protobuf/reflect/protoregistry"
    11  )
    12  
    13  // PluginName is the name of the AIP Go protobuf compiler plugin.
    14  const PluginName = "protoc-gen-go-aip"
    15  
    16  const generatedFilenameSuffix = "_aip.go"
    17  
    18  type Config struct {
    19  	IncludeResourceDefinitions bool
    20  }
    21  
    22  // Run the AIP Go protobuf compiler plugin.
    23  func Run(gen *protogen.Plugin, config Config) error {
    24  	var files protoregistry.Files
    25  	for _, file := range gen.Files {
    26  		if err := files.RegisterFile(file.Desc); err != nil {
    27  			return err
    28  		}
    29  	}
    30  	for _, file := range gen.Files {
    31  		file := file
    32  		if !file.Generate {
    33  			continue
    34  		}
    35  		g := newGeneratedFile(gen, file)
    36  		g.Skip()
    37  		var rangeErr error
    38  		rangeResourcesInFile(
    39  			file.Desc,
    40  			func(resource *annotations.ResourceDescriptor, extension protoreflect.ExtensionType) bool {
    41  				if !config.IncludeResourceDefinitions && extension == annotations.E_ResourceDefinition {
    42  					return true
    43  				}
    44  				g.Unskip()
    45  				if err := (resourceNameCodeGenerator{
    46  					resource: resource,
    47  					files:    &files,
    48  					file:     file,
    49  				}).GenerateCode(g); err != nil {
    50  					rangeErr = err
    51  					return false
    52  				}
    53  				return true
    54  			},
    55  		)
    56  		if rangeErr != nil {
    57  			return rangeErr
    58  		}
    59  	}
    60  	return nil
    61  }
    62  
    63  func newGeneratedFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
    64  	g := gen.NewGeneratedFile(file.GeneratedFilenamePrefix+generatedFilenameSuffix, file.GoImportPath)
    65  	g.P("// Code generated by ", PluginName, ". DO NOT EDIT.")
    66  	g.P("//")
    67  	g.P("// versions:")
    68  	g.P("// \t", PluginName, " ", PluginVersion)
    69  	g.P("// \tprotoc ", getProtocVersion(gen))
    70  	g.P("// source: ", file.Desc.Path())
    71  	g.P()
    72  	g.P("package ", file.GoPackageName)
    73  	return g
    74  }
    75  
    76  func getProtocVersion(gen *protogen.Plugin) string {
    77  	if v := gen.Request.GetCompilerVersion(); v != nil {
    78  		return fmt.Sprintf("v%v.%v.%v", v.GetMajor(), v.GetMinor(), v.GetPatch())
    79  	}
    80  	return "(unknown)"
    81  }
    82  
    83  func rangeResourcesInFile(
    84  	file protoreflect.FileDescriptor,
    85  	fn func(resource *annotations.ResourceDescriptor, extension protoreflect.ExtensionType) bool,
    86  ) {
    87  	for _, resource := range proto.GetExtension(
    88  		file.Options(), annotations.E_ResourceDefinition,
    89  	).([]*annotations.ResourceDescriptor) {
    90  		if !fn(resource, annotations.E_ResourceDefinition) {
    91  			return
    92  		}
    93  	}
    94  	for i := 0; i < file.Messages().Len(); i++ {
    95  		resource := proto.GetExtension(
    96  			file.Messages().Get(i).Options(), annotations.E_Resource,
    97  		).(*annotations.ResourceDescriptor)
    98  		if resource == nil {
    99  			continue
   100  		}
   101  		if !fn(resource, annotations.E_Resource) {
   102  			return
   103  		}
   104  	}
   105  }
   106  

View as plain text